diff options
266 files changed, 10626 insertions, 9056 deletions
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 796707be03..1e717ba6c5 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,4 +1,4 @@ -blank_issues_enabled: true +blank_issues_enabled: false contact_links: - name: Question url: https://neovim.discourse.group/ diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 0000000000..25f8414008 --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,33 @@ +name: Backport +on: + pull_request_target: + types: [closed, labeled] + issue_comment: + types: [created] +jobs: + backport: + permissions: + contents: write + pull-requests: write + name: Backport Pull Request + if: > + github.repository_owner == 'neovim' && ( + github.event_name == 'pull_request' && + github.event.pull_request.merged + ) || ( + github.event_name == 'issue_comment' && + github.event.issue.pull_request && + contains(github.event.comment.body, '/backport') + ) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + # required to find all branches + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + - name: Create backport PRs + uses: zeebe-io/backport-action@v0.0.7 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + github_workspace: ${{ github.workspace }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0dbe484108..d07b9fdac7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,9 @@ name: CI on: push: - branches: '**' + branches: + - 'master' + - 'release-[0-9]+.[0-9]+' pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: @@ -33,10 +35,6 @@ jobs: - cc: clang runner: macos-11.0 os: osx - - flavor: functionaltest-lua - cc: gcc - runner: ubuntu-20.04 - os: linux runs-on: ${{ matrix.runner }} timeout-minutes: 45 if: github.event.pull_request.draft == false @@ -46,7 +44,7 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Setup commom environment variables + - name: Setup common environment variables run: ./.github/workflows/env.sh ${{ matrix.flavor }} - name: Install apt packages @@ -105,7 +103,7 @@ jobs: strategy: fail-fast: false matrix: - config: [ MINGW_64-gcov, MINGW_32, MSVC_64, MSVC_32 ] + config: [ MINGW_64-gcov, MSVC_64 ] name: windows (${{ matrix.config }}) steps: - uses: actions/checkout@v2 @@ -119,3 +117,69 @@ jobs: run: powershell ci\build.ps1 env: CONFIGURATION: ${{ matrix.config }} + + functionaltest: + name: ${{ matrix.runner }} ${{ matrix.flavor }} (cc=${{ matrix.cc }}) + strategy: + fail-fast: false + matrix: + include: + - flavor: functionaltest-lua + cc: gcc + runner: ubuntu-20.04 + os: linux + runs-on: ${{ matrix.runner }} + timeout-minutes: 45 + env: + CC: ${{ matrix.cc }} + CI_OS_NAME: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + + - name: Setup commom environment variables + run: ./.github/workflows/env.sh ${{ matrix.flavor }} + + - name: Install apt packages + run: | + sudo apt-get update + sudo apt-get install -y autoconf automake build-essential ccache cmake cpanminus cscope gcc-multilib gdb gettext gperf language-pack-tr libtool-bin locales ninja-build pkg-config python3 python3-pip python3-setuptools unzip valgrind xclip + + - name: Install minimum required version of cmake + env: + CMAKE_URL: 'https://cmake.org/files/v3.10/cmake-3.10.0-Linux-x86_64.sh' + CMAKE_VERSION: '3.10.0' + shell: bash + run: | + curl --retry 5 --silent --show-error --fail -o /tmp/cmake-installer.sh "$CMAKE_URL" + mkdir -p "$HOME/.local/bin" /opt/cmake-custom + chmod a+x /tmp/cmake-installer.sh + /tmp/cmake-installer.sh --prefix=/opt/cmake-custom --skip-license + ln -sfn /opt/cmake-custom/bin/cmake "$HOME/.local/bin/cmake" + cmake_version="$(cmake --version | head -1)" + echo "$cmake_version" | grep -qF "cmake version $CMAKE_VERSION" || { + echo "Unexpected CMake version: $cmake_version" + exit 1 + } + + - name: Setup interpreter packages + run: | + ./ci/before_install.sh + ./ci/install.sh + + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: | + ${{ env.CACHE_NVIM_DEPS_DIR }} + ~/.ccache + key: ${{ matrix.runner }}-${{ matrix.flavor }}-${{ matrix.cc }}-${{ hashFiles('cmake/*', 'third-party/**', '**/CMakeLists.txt') }}-${{ github.base_ref }} + + - name: Build third-party + run: ./ci/before_script.sh + + - name: Build and test + run: ./ci/script.sh + + - name: Cache dependencies + if: ${{ success() }} + run: ./ci/before_cache.sh diff --git a/.github/workflows/notes.md b/.github/workflows/notes.md new file mode 100644 index 0000000000..9928d472b3 --- /dev/null +++ b/.github/workflows/notes.md @@ -0,0 +1,40 @@ +``` +${NVIM_VERSION} +``` + +## Install + +### Windows + +1. Extract **nvim-win64.zip** +2. Run `nvim-qt.exe` + +### macOS + +1. Download **nvim-macos.tar.gz** +2. Extract: `tar xzvf nvim-macos.tar.gz` +3. Run `./nvim-osx64/bin/nvim` + +### Linux (x64) + +1. Download **nvim.appimage** +2. Run `chmod u+x nvim.appimage && ./nvim.appimage` + - If your system does not have FUSE you can [extract the appimage](https://github.com/AppImage/AppImageKit/wiki/FUSE#type-2-appimage): + ``` + ./nvim.appimage --appimage-extract + ./squashfs-root/usr/bin/nvim + ``` + +### Other + +- Install by [package manager](https://github.com/neovim/neovim/wiki/Installing-Neovim) + +## SHA256 Checksums + +``` +${SHA_LINUX_64} +${SHA_APP_IMAGE} +${SHA_APP_IMAGE_ZSYNC} +${SHA_MACOS} +${SHA_WIN_64} +``` diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c6d3eaf42b..f1ed05e6cb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -125,8 +125,6 @@ jobs: include: - config: MSVC_64 archive: nvim-win64 - - config: MSVC_32 - archive: nvim-win32 name: windows (${{ matrix.config }}) steps: - uses: actions/checkout@v2 @@ -145,10 +143,22 @@ jobs: publish: needs: [linux, appimage, macOS, windows] runs-on: ubuntu-20.04 + env: + GH_REPO: ${{ github.repository }} permissions: contents: write steps: + # Must perform checkout first, since it deletes the target directory + # before running, and would therefore delete the downloaded artifacts + - uses: actions/checkout@v2 + - uses: actions/download-artifact@v2 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y gettext-base + - if: github.event_name == 'workflow_dispatch' run: echo "TAG_NAME=${{ github.event.inputs.tag_name }}" >> $GITHUB_ENV - if: github.event_name == 'schedule' @@ -158,16 +168,21 @@ jobs: TAG_NAME=${{ github.ref }} echo "TAG_NAME=${TAG_NAME#refs/tags/}" >> $GITHUB_ENV - if: env.TAG_NAME == 'nightly' - run: echo 'SUBJECT=Nvim development (prerelease) build' >> $GITHUB_ENV + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + (echo 'SUBJECT=Nvim development (prerelease) build'; + echo 'PRERELEASE=--prerelease') >> $GITHUB_ENV + gh release delete nightly --yes || true + git push origin :nightly || true - if: env.TAG_NAME != 'nightly' - run: echo 'SUBJECT=Nvim release build' >> $GITHUB_ENV - - if: env.TAG_NAME == 'nightly' - uses: dev-drprasad/delete-tag-and-release@v0.1.2 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - delete_release: true - tag_name: nightly + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + (echo 'SUBJECT=Nvim release build'; + echo 'PRERELEASE=') >> $GITHUB_ENV + gh release delete stable --yes || true + git push origin :stable || true # `sha256sum` outputs <sha> <path>, so we cd into each dir to drop the # containing folder from the output. - name: Generate Linux64 SHA256 checksums @@ -190,77 +205,18 @@ jobs: cd ./nvim-macos sha256sum nvim-macos.tar.gz > nvim-macos.tar.gz.sha256sum echo "SHA_MACOS=$(cat nvim-macos.tar.gz.sha256sum)" >> $GITHUB_ENV - - name: Generate Win32 SHA256 checksums - run: | - cd ./nvim-win32 - sha256sum nvim-win32.zip > nvim-win32.zip.sha256sum - echo "SHA_WIN_32=$(cat nvim-win32.zip.sha256sum)" >> $GITHUB_ENV - name: Generate Win64 SHA256 checksums run: | cd ./nvim-win64 sha256sum nvim-win64.zip > nvim-win64.zip.sha256sum echo "SHA_WIN_64=$(cat nvim-win64.zip.sha256sum)" >> $GITHUB_ENV - - uses: meeDamian/github-release@2.0 - with: - token: ${{ secrets.GITHUB_TOKEN }} - tag: ${{ env.TAG_NAME }} - name: ${{ needs.linux.outputs.release }} - prerelease: ${{ env.TAG_NAME == 'nightly' }} - commitish: ${{ github.sha }} - gzip: false - allow_override: ${{ env.TAG_NAME == 'nightly' }} - files: | - nvim-macos.tar.gz:./nvim-macos/nvim-macos.tar.gz - nvim-macos.tar.gz.sha256sum:./nvim-macos/nvim-macos.tar.gz.sha256sum - nvim-linux64.tar.gz:./nvim-linux64/nvim-linux64.tar.gz - nvim-linux64.tar.gz.sha256sum:./nvim-linux64/nvim-linux64.tar.gz.sha256sum - nvim.appimage:./appimage/nvim.appimage - nvim.appimage.sha256sum:./appimage/nvim.appimage.sha256sum - nvim.appimage.zsync:./appimage/nvim.appimage.zsync - nvim.appimage.zsync.sha256sum:./appimage/nvim.appimage.zsync.sha256sum - nvim-win32.zip:./nvim-win32/nvim-win32.zip - nvim-win32.zip.sha256sum:./nvim-win32/nvim-win32.zip.sha256sum - nvim-win64.zip:./nvim-win64/nvim-win64.zip - nvim-win64.zip.sha256sum:./nvim-win64/nvim-win64.zip.sha256sum - body: | - ${{ env.SUBJECT }} - ``` - ${{ needs.linux.outputs.version }}``` - - ## Install - - ### Windows - - 1. Extract **nvim-win64.zip** (or **nvim-win32.zip**) - 2. Run `nvim-qt.exe` - - ### macOS - - 1. Download **nvim-macos.tar.gz** - 2. Extract: `tar xzvf nvim-macos.tar.gz` - 3. Run `./nvim-osx64/bin/nvim` - - ### Linux (x64) - - 1. Download **nvim.appimage** - 2. Run `chmod u+x nvim.appimage && ./nvim.appimage` - - If your system does not have FUSE you can [extract the appimage](https://github.com/AppImage/AppImageKit/wiki/FUSE#type-2-appimage): - ``` - ./nvim.appimage --appimage-extract - ./squashfs-root/usr/bin/nvim - ``` - - ### Other - - - Install by [package manager](https://github.com/neovim/neovim/wiki/Installing-Neovim) - - ## SHA256 Checksums - - ``` - ${{ env.SHA_LINUX_64 }} - ${{ env.SHA_APP_IMAGE }} - ${{ env.SHA_APP_IMAGE_ZSYNC }} - ${{ env.SHA_MACOS }} - ${{ env.SHA_WIN_64 }} - ${{ env.SHA_WIN_32 }} - ``` + - name: Publish release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NVIM_VERSION: ${{ needs.linux.outputs.version }} + run: | + envsubst < "$GITHUB_WORKSPACE/.github/workflows/notes.md" > "$RUNNER_TEMP/notes.md" + gh release create $TAG_NAME $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos/* nvim-linux64/* appimage/* nvim-win64/* + if [ "$TAG_NAME" != "nightly" ]; then + gh release create stable $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos/* nvim-linux64/* appimage/* nvim-win64/* + fi diff --git a/.travis.yml b/.travis.yml index 06547febba..ec7e19b2f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -133,8 +133,6 @@ jobs: - BUILD_32BIT=ON - CMAKE_FLAGS="$CMAKE_FLAGS -m32 -DCMAKE_TOOLCHAIN_FILE=$TRAVIS_BUILD_DIR/cmake/i386-linux-gnu.toolchain.cmake" - DEPS_CMAKE_FLAGS="$DEPS_CMAKE_FLAGS -m32 -DCMAKE_TOOLCHAIN_FILE=$TRAVIS_BUILD_DIR/cmake/i386-linux-gnu.toolchain.cmake" - # Minimum required CMake. - - CMAKE_URL=https://cmake.org/files/v2.8/cmake-2.8.12-Linux-i386.sh - *common-job-env - name: big-endian os: linux diff --git a/CMakeLists.txt b/CMakeLists.txt index 26c60ffbf1..f44937b5ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,8 @@ # intro: https://codingnest.com/basic-cmake/ # best practices (3.0+): https://gist.github.com/mbinna/c61dbb39bca0e4fb7d1f73b0d66a4fd1 -# Version should match the tested CMAKE_URL in .travis.yml. -cmake_minimum_required(VERSION 2.8.12) +# Version should match the tested CMAKE_URL in .github/workflows/ci.yml. +cmake_minimum_required(VERSION 3.10) project(nvim C) if(POLICY CMP0065) @@ -590,9 +590,7 @@ if(BUSTED_PRG) # console pool: to do so we need to use the USES_TERMINAL # option, but this is only available in CMake 3.2 set(TEST_TARGET_ARGS) - if(NOT (${CMAKE_VERSION} VERSION_LESS 3.2.0)) - list(APPEND TEST_TARGET_ARGS "USES_TERMINAL") - endif() + list(APPEND TEST_TARGET_ARGS "USES_TERMINAL") set(UNITTEST_PREREQS nvim-test unittest-headers) set(FUNCTIONALTEST_PREREQS nvim printenv-test printargs-test shell-test streams-test tty-test ${GENERATED_HELP_TAGS}) diff --git a/MAINTAIN.md b/MAINTAIN.md index 681ba91e3f..7df91b7d57 100644 --- a/MAINTAIN.md +++ b/MAINTAIN.md @@ -55,6 +55,14 @@ has a major bug: - The [nightly job](https://github.com/neovim/bot-ci/blob/master/ci/nightly.sh) will update the release assets based on the `stable` tag. +The neovim repository includes a backport [github action](https://github.com/zeebe-io/backport-action). +In order to trigger the action, a PR must be labeled with a label matching the +form `backport release-0.X`. If the label is applied before the PR is merged, +the backport will be filed automatically against the target branch. Otherwise, +comment `\backport` on the merged PR *after* the label has been applied to trigger +a backport. Note, the PR must have a description in the issue body, or the backport +will fail. + Third-party dependencies -------------- diff --git a/ci/before_install.sh b/ci/before_install.sh index c3fd8bdbde..f12f972fe0 100755 --- a/ci/before_install.sh +++ b/ci/before_install.sh @@ -44,16 +44,3 @@ fi source ~/.nvm/nvm.sh nvm install 10 - -if [[ -n "$CMAKE_URL" ]]; then - echo "Installing custom CMake: $CMAKE_URL" - curl --retry 5 --silent --show-error --fail -o /tmp/cmake-installer.sh "$CMAKE_URL" - mkdir -p "$HOME/.local/bin" /opt/cmake-custom - bash /tmp/cmake-installer.sh --prefix=/opt/cmake-custom --skip-license - ln -sfn /opt/cmake-custom/bin/cmake "$HOME/.local/bin/cmake" - cmake_version="$(cmake --version)" - echo "$cmake_version" | grep -qF '2.8.12' || { - echo "Unexpected CMake version: $cmake_version" - exit 1 - } -fi diff --git a/ci/build.ps1 b/ci/build.ps1 index 8876ac31ef..a81d351bc6 100644 --- a/ci/build.ps1 +++ b/ci/build.ps1 @@ -170,6 +170,11 @@ if (-not $NoTests) { } } +# Ensure choco's cpack is not in PATH otherwise, it conflicts with CMake's +if (Test-Path -Path $env:ChocolateyInstall\bin\cpack.exe) { + Remove-Item -Path $env:ChocolateyInstall\bin\cpack.exe -Force +} + # Build artifacts cpack -G ZIP -C RelWithDebInfo if ($env:APPVEYOR_REPO_TAG_NAME -ne $null) { diff --git a/cmake/InstallHelpers.cmake b/cmake/InstallHelpers.cmake index bebc0d0d17..9d997260cd 100644 --- a/cmake/InstallHelpers.cmake +++ b/cmake/InstallHelpers.cmake @@ -154,3 +154,25 @@ function(install_helper) ${RENAME}) endif() endfunction() + +# Without CONFIGURE_DEPENDS globbing reuses cached file tree on rebuild. +# For example it will ignore new files. +# CONFIGURE_DEPENDS was introduced in 3.12 + +function(glob_wrapper outvar) + if(${CMAKE_VERSION} VERSION_LESS 3.12) + file(GLOB ${outvar} ${ARGN}) + else() + file(GLOB ${outvar} CONFIGURE_DEPENDS ${ARGN}) + endif() + set(${outvar} ${${outvar}} PARENT_SCOPE) +endfunction() + +function(globrecurse_wrapper outvar root) + if(${CMAKE_VERSION} VERSION_LESS 3.12) + file(GLOB_RECURSE ${outvar} RELATIVE ${root} ${ARGN}) + else() + file(GLOB_RECURSE ${outvar} CONFIGURE_DEPENDS RELATIVE ${root} ${ARGN}) + endif() + set(${outvar} ${${outvar}} PARENT_SCOPE) +endfunction() diff --git a/config/CMakeLists.txt b/config/CMakeLists.txt index 6b88c92cf0..581f25857b 100644 --- a/config/CMakeLists.txt +++ b/config/CMakeLists.txt @@ -12,11 +12,6 @@ check_type_size("size_t" SIZEOF_SIZE_T) check_type_size("long long" SIZEOF_LONG_LONG) check_type_size("void *" SIZEOF_VOID_PTR) -if (CMAKE_HOST_SYSTEM_VERSION MATCHES ".*-(Microsoft|microsoft-standard)") - # Windows Subsystem for Linux - set(HAVE_WSL 1) -endif() - check_symbol_exists(_NSGetEnviron crt_externs.h HAVE__NSGETENVIRON) # Headers diff --git a/config/config.h.in b/config/config.h.in index 502f84bbcf..27a28116af 100644 --- a/config/config.h.in +++ b/config/config.h.in @@ -39,7 +39,6 @@ #cmakedefine HAVE_SYS_WAIT_H #cmakedefine HAVE_TERMIOS_H #cmakedefine HAVE_WORKING_LIBINTL -#cmakedefine HAVE_WSL #cmakedefine UNIX #cmakedefine CASE_INSENSITIVE_FILENAME #cmakedefine USE_FNAME_CASE diff --git a/man/nvim.1 b/man/nvim.1 index 3f57f397d2..b206b62343 100644 --- a/man/nvim.1 +++ b/man/nvim.1 @@ -201,7 +201,7 @@ Skip loading plugins. Implied by .Cm -u NONE . .It Fl -clean -Skip loading plugins and shada (viminfo) file. +Mimic a fresh install of Nvim. Skip loading non-builtin plugins and shada (viminfo) file. .It Fl o Ns Op Ar N Open .Ar N diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 4fdcfc0f33..37029874f2 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -21,12 +21,12 @@ add_custom_command(OUTPUT ${GENERATED_SYN_VIM} ${FUNCS_DATA} ) -file(GLOB PACKAGES ${PROJECT_SOURCE_DIR}/runtime/pack/dist/opt/*) +glob_wrapper(PACKAGES ${PROJECT_SOURCE_DIR}/runtime/pack/dist/opt/*) set(GENERATED_PACKAGE_TAGS) foreach(PACKAGE ${PACKAGES}) get_filename_component(PACKNAME ${PACKAGE} NAME) - file(GLOB "${PACKNAME}_DOC_FILES" ${PACKAGE}/doc/*.txt) + glob_wrapper("${PACKNAME}_DOC_FILES" ${PACKAGE}/doc/*.txt) if(${PACKNAME}_DOC_FILES) file(MAKE_DIRECTORY ${GENERATED_PACKAGE_DIR}/${PACKNAME}) add_custom_command(OUTPUT "${GENERATED_PACKAGE_DIR}/${PACKNAME}/doc/tags" @@ -54,7 +54,7 @@ foreach(PACKAGE ${PACKAGES}) endif() endforeach() -file(GLOB DOCFILES ${PROJECT_SOURCE_DIR}/runtime/doc/*.txt) +glob_wrapper(DOCFILES ${PROJECT_SOURCE_DIR}/runtime/doc/*.txt) set(BUILDDOCFILES) foreach(DF ${DOCFILES}) @@ -114,9 +114,7 @@ if(NOT APPLE) DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps) endif() -file(GLOB_RECURSE RUNTIME_PROGRAMS - RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - *.awk *.sh *.bat) +globrecurse_wrapper(RUNTIME_PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR} *.awk *.sh *.bat) foreach(PROG ${RUNTIME_PROGRAMS}) get_filename_component(BASEDIR ${PROG} PATH) @@ -124,10 +122,8 @@ foreach(PROG ${RUNTIME_PROGRAMS}) DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/${BASEDIR}) endforeach() -file(GLOB_RECURSE RUNTIME_FILES - RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - rgb.txt - *.vim *.lua *.dict *.py *.rb *.ps *.spl *.tutor *.tutor.json) +globrecurse_wrapper(RUNTIME_FILES ${CMAKE_CURRENT_SOURCE_DIR} + rgb.txt *.vim *.lua *.dict *.py *.rb *.ps *.spl *.tutor *.tutor.json) foreach(F ${RUNTIME_FILES}) get_filename_component(BASEDIR ${F} PATH) diff --git a/runtime/autoload/clojurecomplete.vim b/runtime/autoload/clojurecomplete.vim index 2c0f0eacd4..9f2c39081a 100644 --- a/runtime/autoload/clojurecomplete.vim +++ b/runtime/autoload/clojurecomplete.vim @@ -1,15 +1,15 @@ " Vim completion script " Language: Clojure -" Maintainer: Alex Vear <av@axvr.io> +" Maintainer: Alex Vear <alex@vear.uk> " Former Maintainers: Sung Pae <self@sungpae.com> " URL: https://github.com/clojure-vim/clojure.vim " License: Vim (see :h license) -" Last Change: 2021-02-13 +" Last Change: 2021-10-26 " -*- COMPLETION WORDS -*- -" Generated from https://github.com/clojure-vim/clojure.vim/blob/f8594e7030cdfb0b7990ac92953c77a08a7220f0/clj/src/vim_clojure_static/generate.clj -" Clojure version 1.10.2 -let s:words = ["*","*'","*1","*2","*3","*agent*","*allow-unresolved-vars*","*assert*","*clojure-version*","*command-line-args*","*compile-files*","*compile-path*","*compiler-options*","*data-readers*","*default-data-reader-fn*","*e","*err*","*file*","*flush-on-newline*","*fn-loader*","*in*","*math-context*","*ns*","*out*","*print-dup*","*print-length*","*print-level*","*print-meta*","*print-namespace-maps*","*print-readably*","*read-eval*","*reader-resolver*","*source-path*","*suppress-read*","*unchecked-math*","*use-context-classloader*","*verbose-defrecords*","*warn-on-reflection*","+","+'","-","-'","->","->>","->ArrayChunk","->Eduction","->Vec","->VecNode","->VecSeq","-cache-protocol-fn","-reset-methods",".","..","/","<","<=","=","==",">",">=","EMPTY-NODE","Inst","PrintWriter-on","StackTraceElement->vec","Throwable->map","accessor","aclone","add-classpath","add-tap","add-watch","agent","agent-error","agent-errors","aget","alength","alias","all-ns","alter","alter-meta!","alter-var-root","amap","ancestors","and","any?","apply","areduce","array-map","as->","aset","aset-boolean","aset-byte","aset-char","aset-double","aset-float","aset-int","aset-long","aset-short","assert","assoc!","assoc","assoc-in","associative?","atom","await","await-for","await1","bases","bean","bigdec","bigint","biginteger","binding","bit-and","bit-and-not","bit-clear","bit-flip","bit-not","bit-or","bit-set","bit-shift-left","bit-shift-right","bit-test","bit-xor","boolean","boolean-array","boolean?","booleans","bound-fn","bound-fn*","bound?","bounded-count","butlast","byte","byte-array","bytes","bytes?","case","case-fallthrough-err-impl","cast","cat","catch","char","char-array","char-escape-string","char-name-string","char?","chars","chunk","chunk-append","chunk-buffer","chunk-cons","chunk-first","chunk-next","chunk-rest","chunked-seq?","class","class?","clear-agent-errors","clojure-version","coll?","comment","commute","comp","comparator","compare","compare-and-set!","compile","complement","completing","concat","cond","cond->","cond->>","condp","conj!","conj","cons","constantly","construct-proxy","contains?","count","counted?","create-ns","create-struct","cycle","dec","dec'","decimal?","declare","dedupe","def","default-data-readers","definline","definterface","defmacro","defmethod","defmulti","defn","defn-","defonce","defprotocol","defrecord","defstruct","deftype","delay","delay?","deliver","denominator","deref","derive","descendants","destructure","disj!","disj","dissoc!","dissoc","distinct","distinct?","do","doall","dorun","doseq","dosync","dotimes","doto","double","double-array","double?","doubles","drop","drop-last","drop-while","eduction","empty","empty?","ensure","ensure-reduced","enumeration-seq","error-handler","error-mode","eval","even?","every-pred","every?","ex-cause","ex-data","ex-info","ex-message","extend","extend-protocol","extend-type","extenders","extends?","false?","ffirst","file-seq","filter","filterv","finally","find","find-keyword","find-ns","find-protocol-impl","find-protocol-method","find-var","first","flatten","float","float-array","float?","floats","flush","fn","fn","fn?","fnext","fnil","for","force","format","frequencies","future","future-call","future-cancel","future-cancelled?","future-done?","future?","gen-class","gen-interface","gensym","get","get-in","get-method","get-proxy-class","get-thread-bindings","get-validator","group-by","halt-when","hash","hash-combine","hash-map","hash-ordered-coll","hash-set","hash-unordered-coll","ident?","identical?","identity","if","if-let","if-not","if-some","ifn?","import","in-ns","inc","inc'","indexed?","init-proxy","inst-ms","inst-ms*","inst?","instance?","int","int-array","int?","integer?","interleave","intern","interpose","into","into-array","ints","io!","isa?","iterate","iterator-seq","juxt","keep","keep-indexed","key","keys","keyword","keyword?","last","lazy-cat","lazy-seq","let","let","letfn","line-seq","list","list*","list?","load","load-file","load-reader","load-string","loaded-libs","locking","long","long-array","longs","loop","loop","macroexpand","macroexpand-1","make-array","make-hierarchy","map","map-entry?","map-indexed","map?","mapcat","mapv","max","max-key","memfn","memoize","merge","merge-with","meta","method-sig","methods","min","min-key","mix-collection-hash","mod","monitor-enter","monitor-exit","munge","name","namespace","namespace-munge","nat-int?","neg-int?","neg?","new","newline","next","nfirst","nil?","nnext","not","not-any?","not-empty","not-every?","not=","ns","ns-aliases","ns-imports","ns-interns","ns-map","ns-name","ns-publics","ns-refers","ns-resolve","ns-unalias","ns-unmap","nth","nthnext","nthrest","num","number?","numerator","object-array","odd?","or","parents","partial","partition","partition-all","partition-by","pcalls","peek","persistent!","pmap","pop!","pop","pop-thread-bindings","pos-int?","pos?","pr","pr-str","prefer-method","prefers","primitives-classnames","print","print-ctor","print-dup","print-method","print-simple","print-str","printf","println","println-str","prn","prn-str","promise","proxy","proxy-call-with-super","proxy-mappings","proxy-name","proxy-super","push-thread-bindings","pvalues","qualified-ident?","qualified-keyword?","qualified-symbol?","quot","quote","rand","rand-int","rand-nth","random-sample","range","ratio?","rational?","rationalize","re-find","re-groups","re-matcher","re-matches","re-pattern","re-seq","read","read+string","read-line","read-string","reader-conditional","reader-conditional?","realized?","record?","recur","reduce","reduce-kv","reduced","reduced?","reductions","ref","ref-history-count","ref-max-history","ref-min-history","ref-set","refer","refer-clojure","reify","release-pending-sends","rem","remove","remove-all-methods","remove-method","remove-ns","remove-tap","remove-watch","repeat","repeatedly","replace","replicate","require","requiring-resolve","reset!","reset-meta!","reset-vals!","resolve","rest","restart-agent","resultset-seq","reverse","reversible?","rseq","rsubseq","run!","satisfies?","second","select-keys","send","send-off","send-via","seq","seq?","seqable?","seque","sequence","sequential?","set!","set","set-agent-send-executor!","set-agent-send-off-executor!","set-error-handler!","set-error-mode!","set-validator!","set?","short","short-array","shorts","shuffle","shutdown-agents","simple-ident?","simple-keyword?","simple-symbol?","slurp","some","some->","some->>","some-fn","some?","sort","sort-by","sorted-map","sorted-map-by","sorted-set","sorted-set-by","sorted?","special-symbol?","spit","split-at","split-with","str","string?","struct","struct-map","subs","subseq","subvec","supers","swap!","swap-vals!","symbol","symbol?","sync","tagged-literal","tagged-literal?","take","take-last","take-nth","take-while","tap>","test","the-ns","thread-bound?","throw","time","to-array","to-array-2d","trampoline","transduce","transient","tree-seq","true?","try","type","unchecked-add","unchecked-add-int","unchecked-byte","unchecked-char","unchecked-dec","unchecked-dec-int","unchecked-divide-int","unchecked-double","unchecked-float","unchecked-inc","unchecked-inc-int","unchecked-int","unchecked-long","unchecked-multiply","unchecked-multiply-int","unchecked-negate","unchecked-negate-int","unchecked-remainder-int","unchecked-short","unchecked-subtract","unchecked-subtract-int","underive","unquote","unquote-splicing","unreduced","unsigned-bit-shift-right","update","update-in","update-proxy","uri?","use","uuid?","val","vals","var","var-get","var-set","var?","vary-meta","vec","vector","vector-of","vector?","volatile!","volatile?","vreset!","vswap!","when","when-first","when-let","when-not","when-some","while","with-bindings","with-bindings*","with-in-str","with-loading-context","with-local-vars","with-meta","with-open","with-out-str","with-precision","with-redefs","with-redefs-fn","xml-seq","zero?","zipmap"] +" Generated from https://github.com/clojure-vim/clojure.vim/blob/62b215f079ce0f3834fd295c7a7f6bd8cc54bcc3/clj/src/vim_clojure_static/generate.clj +" Clojure version 1.10.3 +let s:words = ["*","*'","*1","*2","*3","*agent*","*allow-unresolved-vars*","*assert*","*clojure-version*","*command-line-args*","*compile-files*","*compile-path*","*compiler-options*","*data-readers*","*default-data-reader-fn*","*e","*err*","*file*","*flush-on-newline*","*fn-loader*","*in*","*math-context*","*ns*","*out*","*print-dup*","*print-length*","*print-level*","*print-meta*","*print-namespace-maps*","*print-readably*","*read-eval*","*reader-resolver*","*source-path*","*suppress-read*","*unchecked-math*","*use-context-classloader*","*verbose-defrecords*","*warn-on-reflection*","+","+'","-","-'","->","->>","->ArrayChunk","->Eduction","->Vec","->VecNode","->VecSeq","-cache-protocol-fn","-reset-methods",".","..","/","<","<=","=","==",">",">=","EMPTY-NODE","Inst","PrintWriter-on","StackTraceElement->vec","Throwable->map","accessor","aclone","add-classpath","add-tap","add-watch","agent","agent-error","agent-errors","aget","alength","alias","all-ns","alter","alter-meta!","alter-var-root","amap","ancestors","and","any?","apply","areduce","array-map","as->","aset","aset-boolean","aset-byte","aset-char","aset-double","aset-float","aset-int","aset-long","aset-short","assert","assoc!","assoc","assoc-in","associative?","atom","await","await-for","await1","bases","bean","bigdec","bigint","biginteger","binding","bit-and","bit-and-not","bit-clear","bit-flip","bit-not","bit-or","bit-set","bit-shift-left","bit-shift-right","bit-test","bit-xor","boolean","boolean-array","boolean?","booleans","bound-fn","bound-fn*","bound?","bounded-count","butlast","byte","byte-array","bytes","bytes?","case","cast","cat","catch","char","char-array","char-escape-string","char-name-string","char?","chars","chunk","chunk-append","chunk-buffer","chunk-cons","chunk-first","chunk-next","chunk-rest","chunked-seq?","class","class?","clear-agent-errors","clojure-version","coll?","comment","commute","comp","comparator","compare","compare-and-set!","compile","complement","completing","concat","cond","cond->","cond->>","condp","conj!","conj","cons","constantly","construct-proxy","contains?","count","counted?","create-ns","create-struct","cycle","dec","dec'","decimal?","declare","dedupe","def","default-data-readers","definline","definterface","defmacro","defmethod","defmulti","defn","defn-","defonce","defprotocol","defrecord","defstruct","deftype","delay","delay?","deliver","denominator","deref","derive","descendants","destructure","disj!","disj","dissoc!","dissoc","distinct","distinct?","do","doall","dorun","doseq","dosync","dotimes","doto","double","double-array","double?","doubles","drop","drop-last","drop-while","eduction","empty","empty?","ensure","ensure-reduced","enumeration-seq","error-handler","error-mode","eval","even?","every-pred","every?","ex-cause","ex-data","ex-info","ex-message","extend","extend-protocol","extend-type","extenders","extends?","false?","ffirst","file-seq","filter","filterv","finally","find","find-keyword","find-ns","find-protocol-impl","find-protocol-method","find-var","first","flatten","float","float-array","float?","floats","flush","fn","fn","fn?","fnext","fnil","for","force","format","frequencies","future","future-call","future-cancel","future-cancelled?","future-done?","future?","gen-class","gen-interface","gensym","get","get-in","get-method","get-proxy-class","get-thread-bindings","get-validator","group-by","halt-when","hash","hash-combine","hash-map","hash-ordered-coll","hash-set","hash-unordered-coll","ident?","identical?","identity","if","if-let","if-not","if-some","ifn?","import","in-ns","inc","inc'","indexed?","init-proxy","inst-ms","inst-ms*","inst?","instance?","int","int-array","int?","integer?","interleave","intern","interpose","into","into-array","ints","io!","isa?","iterate","iterator-seq","juxt","keep","keep-indexed","key","keys","keyword","keyword?","last","lazy-cat","lazy-seq","let","let","letfn","line-seq","list","list*","list?","load","load-file","load-reader","load-string","loaded-libs","locking","long","long-array","longs","loop","loop","macroexpand","macroexpand-1","make-array","make-hierarchy","map","map-entry?","map-indexed","map?","mapcat","mapv","max","max-key","memfn","memoize","merge","merge-with","meta","method-sig","methods","min","min-key","mix-collection-hash","mod","monitor-enter","monitor-exit","munge","name","namespace","namespace-munge","nat-int?","neg-int?","neg?","new","newline","next","nfirst","nil?","nnext","not","not-any?","not-empty","not-every?","not=","ns","ns-aliases","ns-imports","ns-interns","ns-map","ns-name","ns-publics","ns-refers","ns-resolve","ns-unalias","ns-unmap","nth","nthnext","nthrest","num","number?","numerator","object-array","odd?","or","parents","partial","partition","partition-all","partition-by","pcalls","peek","persistent!","pmap","pop!","pop","pop-thread-bindings","pos-int?","pos?","pr","pr-str","prefer-method","prefers","primitives-classnames","print","print-ctor","print-dup","print-method","print-simple","print-str","printf","println","println-str","prn","prn-str","promise","proxy","proxy-call-with-super","proxy-mappings","proxy-name","proxy-super","push-thread-bindings","pvalues","qualified-ident?","qualified-keyword?","qualified-symbol?","quot","quote","rand","rand-int","rand-nth","random-sample","range","ratio?","rational?","rationalize","re-find","re-groups","re-matcher","re-matches","re-pattern","re-seq","read","read+string","read-line","read-string","reader-conditional","reader-conditional?","realized?","record?","recur","reduce","reduce-kv","reduced","reduced?","reductions","ref","ref-history-count","ref-max-history","ref-min-history","ref-set","refer","refer-clojure","reify","release-pending-sends","rem","remove","remove-all-methods","remove-method","remove-ns","remove-tap","remove-watch","repeat","repeatedly","replace","replicate","require","requiring-resolve","reset!","reset-meta!","reset-vals!","resolve","rest","restart-agent","resultset-seq","reverse","reversible?","rseq","rsubseq","run!","satisfies?","second","select-keys","send","send-off","send-via","seq","seq?","seqable?","seque","sequence","sequential?","set!","set","set-agent-send-executor!","set-agent-send-off-executor!","set-error-handler!","set-error-mode!","set-validator!","set?","short","short-array","shorts","shuffle","shutdown-agents","simple-ident?","simple-keyword?","simple-symbol?","slurp","some","some->","some->>","some-fn","some?","sort","sort-by","sorted-map","sorted-map-by","sorted-set","sorted-set-by","sorted?","special-symbol?","spit","split-at","split-with","str","string?","struct","struct-map","subs","subseq","subvec","supers","swap!","swap-vals!","symbol","symbol?","sync","tagged-literal","tagged-literal?","take","take-last","take-nth","take-while","tap>","test","the-ns","thread-bound?","throw","time","to-array","to-array-2d","trampoline","transduce","transient","tree-seq","true?","try","type","unchecked-add","unchecked-add-int","unchecked-byte","unchecked-char","unchecked-dec","unchecked-dec-int","unchecked-divide-int","unchecked-double","unchecked-float","unchecked-inc","unchecked-inc-int","unchecked-int","unchecked-long","unchecked-multiply","unchecked-multiply-int","unchecked-negate","unchecked-negate-int","unchecked-remainder-int","unchecked-short","unchecked-subtract","unchecked-subtract-int","underive","unquote","unquote-splicing","unreduced","unsigned-bit-shift-right","update","update-in","update-proxy","uri?","use","uuid?","val","vals","var","var-get","var-set","var?","vary-meta","vec","vector","vector-of","vector?","volatile!","volatile?","vreset!","vswap!","when","when-first","when-let","when-not","when-some","while","with-bindings","with-bindings*","with-in-str","with-loading-context","with-local-vars","with-meta","with-open","with-out-str","with-precision","with-redefs","with-redefs-fn","xml-seq","zero?","zipmap"] " Simple word completion for special forms and public vars in clojure.core function! clojurecomplete#Complete(findstart, base) diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 878fc2b301..bb8e83f84a 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -1078,7 +1078,7 @@ nvim_get_keymap({mode}) *nvim_get_keymap()* Array of maparg()-like dictionaries describing mappings. The "buffer" key is always zero. -nvim_get_mark({name}) *nvim_get_mark()* +nvim_get_mark({name}, {opts}) *nvim_get_mark()* Return a tuple (row, col, buffer, buffername) representing the position of the uppercase/file named mark. See |mark-motions|. @@ -1090,6 +1090,7 @@ nvim_get_mark({name}) *nvim_get_mark()* Parameters: ~ {name} Mark name + {opts} Optional parameters. Reserved for future use. Return: ~ 4-tuple (row, col, buffer, buffername), (0, 0, 0, '') if @@ -1877,7 +1878,7 @@ nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()* callbacks. {opts} Optional parameters. • on_lines: Lua callback invoked on change. - Return`true`to detach. Args: + Return `true` to detach. Args: • the string "lines" • buffer handle • b:changedtick @@ -1893,7 +1894,7 @@ nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()* • on_bytes: lua callback invoked on change. This callback receives more granular information about the change compared to - on_lines. Return`true`to detach. Args: + on_lines. Return `true` to detach. Args: • the string "bytes" • buffer handle • b:changedtick @@ -2332,7 +2333,7 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts}) • hl_mode : control how highlights are combined with the highlights of the text. Currently only affects virt_text highlights, but might - affect`hl_group`in later versions. + affect `hl_group` in later versions. • "replace": only show the virt_text color. This is the default • "combine": combine with background text @@ -2420,7 +2421,7 @@ nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing}, {replacement}) {replacement} Array of lines to use as replacement *nvim_buf_set_mark()* -nvim_buf_set_mark({buffer}, {name}, {line}, {col}) +nvim_buf_set_mark({buffer}, {name}, {line}, {col}, {opts}) Sets a named mark in the given buffer, all marks are allowed file/uppercase, visual, last change, etc. See |mark-motions|. @@ -2434,6 +2435,7 @@ nvim_buf_set_mark({buffer}, {name}, {line}, {col}) {name} Mark name {line} Line number {col} Column/row number + {opts} Optional parameters. Reserved for future use. Return: ~ true if the mark was set, else false. @@ -2742,28 +2744,29 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()* {buffer} Buffer to display, or 0 for current buffer {enter} Enter the window (make it the current window) {config} Map defining the window configuration. Keys: - • `relative`: Sets the window layout to "floating", placed - at (row,col) coordinates relative to: + • relative: Sets the window layout to + "floating", placed at (row,col) coordinates + relative to: • "editor" The global editor grid • "win" Window given by the `win` field, or current window. • "cursor" Cursor position in current window. - • `win` : |window-ID| for relative="win". - • `anchor`: Decides which corner of the float to place - at (row,col): + • win: |window-ID| for relative="win". + • anchor: Decides which corner of the float to + place at (row,col): • "NW" northwest (default) • "NE" northeast • "SW" southwest • "SE" southeast - • `width` : Window width (in character cells). + • width: Window width (in character cells). Minimum of 1. - • `height` : Window height (in character cells). + • height: Window height (in character cells). Minimum of 1. - • `bufpos`: Places float relative to buffer text (only - when relative="win"). Takes a tuple of - zero-indexed [line, column].`row`and`col`if given are applied relative to this + • bufpos: Places float relative to buffer text + (only when relative="win"). Takes a tuple of + zero-indexed [line, column]. `row` and `col` if given are applied relative to this position, else they default to: • `row=1` and `col=0` if `anchor` is "NW" or "NE" @@ -2771,19 +2774,19 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()* "SE" (thus like a tooltip near the buffer text). - • `row` : Row position in units of "screen cell + • row: Row position in units of "screen cell height", may be fractional. - • `col` : Column position in units of "screen - cell width", may be fractional. - • `focusable` : Enable focus by user actions + • col: Column position in units of "screen cell + width", may be fractional. + • focusable: Enable focus by user actions (wincmds, mouse events). Defaults to true. Non-focusable windows can be entered by |nvim_set_current_win()|. - • `external` : GUI should display the window as - an external top-level window. Currently - accepts no other positioning configuration - together with this. - • `zindex`: Stacking order. floats with higher`zindex`go on top on floats with lower indices. Must + • external: GUI should display the window as an + external top-level window. Currently accepts + no other positioning configuration together + with this. + • zindex: Stacking order. floats with higher `zindex` go on top on floats with lower indices. Must be larger than zero. The following screen elements have hard-coded z-indices: • 100: insert completion popupmenu @@ -2794,7 +2797,7 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()* are recommended, unless there is a good reason to overshadow builtin elements. - • `style`: Configure the appearance of the window. + • style: Configure the appearance of the window. Currently only takes one non-empty value: • "minimal" Nvim will display the window with many UI options disabled. This is useful @@ -2809,9 +2812,9 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()* and clearing the |EndOfBuffer| region in 'winhighlight'. - • `border`: Style of (optional) window border. This can - either be a string or an array. The string - values are + • border: Style of (optional) window border. + This can either be a string or an array. The + string values are • "none": No border (default). • "single": A single line box. • "double": A double line box. @@ -2841,7 +2844,7 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()* It could also be specified by character: [ {"+", "MyCorner"}, {"x", "MyBorder"} ]. - • `noautocmd` : If true then no buffer-related + • noautocmd: If true then no buffer-related autocommand events such as |BufEnter|, |BufLeave| or |BufWinEnter| may fire from calling this function. diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index a7ce4135af..21a34178b3 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -85,6 +85,9 @@ For each of the functions below, use the corresponding function in *vim.lsp.diagnostic.save()* Use |vim.diagnostic.set()| instead. *vim.lsp.diagnostic.set_loclist()* Use |vim.diagnostic.setloclist()| instead. *vim.lsp.diagnostic.set_qflist()* Use |vim.diagnostic.setqflist()| instead. + +The following have been replaced by |vim.diagnostic.open_float()|. + *vim.lsp.diagnostic.show_line_diagnostics()* *vim.lsp.diagnostic.show_position_diagnostics()* diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt index 17d317522b..d53aae510e 100644 --- a/runtime/doc/diagnostic.txt +++ b/runtime/doc/diagnostic.txt @@ -75,6 +75,100 @@ Functions that take a severity as an optional parameter (e.g. The latter form allows users to specify a range of severities. ============================================================================== +HANDLERS *diagnostic-handlers* + +Diagnostics are shown to the user with |vim.diagnostic.show()|. The display of +diagnostics is managed through handlers. A handler is a table with a "show" +and (optionally) a "hide" function. The "show" function has the signature +> + function(namespace, bufnr, diagnostics, opts) +< +and is responsible for displaying or otherwise handling the given +diagnostics. The "hide" function takes care of "cleaning up" any actions taken +by the "show" function and has the signature +> + function(namespace, bufnr) +< +Handlers can be configured with |vim.diagnostic.config()| and added by +creating a new key in `vim.diagnostic.handlers` (see +|diagnostic-handlers-example|). + +The {opts} table passed to a handler is the full set of configuration options +(that is, it is not limited to just the options for the handler itself). The +values in the table are already resolved (i.e. if a user specifies a +function for a config option, the function has already been evaluated). + +Nvim provides these handlers by default: "virtual_text", "signs", and +"underline". + + *diagnostic-handlers-example* +The example below creates a new handler that notifies the user of diagnostics +with |vim.notify()|: > + + -- It's good practice to namespace custom handlers to avoid collisions + vim.diagnostic.handlers["my/notify"] = { + show = function(namespace, bufnr, diagnostics, opts) + -- In our example, the opts table has a "log_level" option + local level = opts["my/notify"].log_level + + local name = vim.diagnostic.get_namespace(namespace).name + local msg = string.format("%d diagnostics in buffer %d from %s", + #diagnostics, + bufnr, + name) + vim.notify(msg, level) + end, + } + + -- Users can configure the handler + vim.diagnostic.config({ + ["my/notify"] = { + log_level = vim.log.levels.INFO + } + }) +< +In this example, there is nothing to do when diagnostics are hidden, so we +omit the "hide" function. + +Existing handlers can be overriden. For example, use the following to only +show a sign for the highest severity diagnostic on a given line: > + + -- Create a custom namespace. This will aggregate signs from all other + -- namespaces and only show the one with the highest severity on a + -- given line + local ns = vim.api.nvim_create_namespace("my_namespace") + + -- Get a reference to the original signs handler + local orig_signs_handler = vim.diagnostic.handlers.signs + + -- Override the built-in signs handler + vim.diagnostic.handlers.signs = { + show = function(_, bufnr, _, opts) + -- Get all diagnostics from the whole buffer rather than just the + -- diagnostics passed to the handler + local diagnostics = vim.diagnostic.get(bufnr) + + -- Find the "worst" diagnostic per line + local max_severity_per_line = {} + for _, d in pairs(diagnostics) do + local m = max_severity_per_line[d.lnum] + if not m or d.severity < m.severity then + max_severity_per_line[d.lnum] = d + end + end + + -- Pass the filtered diagnostics (with our custom namespace) to + -- the original handler + local filtered_diagnostics = vim.tbl_values(max_severity_per_line) + orig_signs_handler.show(ns, bufnr, filtered_diagnostics, opts) + end, + hide = function(_, bufnr) + orig_signs_handler.hide(ns, bufnr) + end, + } +< + +============================================================================== HIGHLIGHTS *diagnostic-highlights* All highlights defined for diagnostics begin with `Diagnostic` followed by @@ -202,51 +296,6 @@ Example: > autocmd User DiagnosticsChanged lua vim.diagnostic.setqflist({open = false }) < ============================================================================== -CUSTOMIZATION *diagnostic-config* - -If you need more customization over the way diagnostics are displayed than the -built-in configuration options provide, you can override the display handler -explicitly. For example, use the following to only show a sign for the highest -severity diagnostic on a given line: > - - -- Disable the default signs handler - vim.diagnostic.config({signs = false}) - - -- Create a namespace. This won't be used to add any diagnostics, - -- only to display them. - local ns = vim.api.nvim_create_namespace("my_namespace") - - -- Create a reference to the original function - local orig_show = vim.diagnostic.show - - local function set_signs(bufnr) - -- Get all diagnostics from the current buffer - local diagnostics = vim.diagnostic.get(bufnr) - - -- Find the "worst" diagnostic per line - local max_severity_per_line = {} - for _, d in pairs(diagnostics) do - local m = max_severity_per_line[d.lnum] - if not m or d.severity < m.severity then - max_severity_per_line[d.lnum] = d - end - end - - -- Show the filtered diagnostics using the custom namespace. Use the - -- reference to the original function to avoid a loop. - local filtered_diagnostics = vim.tbl_values(max_severity_per_line) - orig_show(ns, bufnr, filtered_diagnostics, { - virtual_text=false, - underline=false, - signs=true - }) - end - - function vim.diagnostic.show(namespace, bufnr, ...) - orig_show(namespace, bufnr, ...) - set_signs(bufnr) - end -< ============================================================================== Lua module: vim.diagnostic *diagnostic-api* @@ -262,12 +311,12 @@ config({opts}, {namespace}) *vim.diagnostic.config()* For example, if a user enables virtual text globally with > - vim.diagnostic.config({virt_text = true}) + vim.diagnostic.config({virtual_text = true}) < and a diagnostic producer sets diagnostics with > - vim.diagnostic.set(ns, 0, diagnostics, {virt_text = false}) + vim.diagnostic.set(ns, 0, diagnostics, {virtual_text = false}) < then virtual text will not be enabled for those diagnostics. @@ -302,7 +351,7 @@ config({opts}, {namespace}) *vim.diagnostic.config()* • format: (function) A function that takes a diagnostic as input and returns a string. The return value is the text used - to display the diagnostic. Example:> + to display the diagnostic. Example: > function(diagnostic) if diagnostic.severity == vim.diagnostic.severity.ERROR then @@ -324,6 +373,29 @@ config({opts}, {namespace}) *vim.diagnostic.config()* Otherwise, all signs use the same priority. + • float: Options for floating windows: + • severity: See |diagnostic-severity|. + • show_header: (boolean, default true) Show + "Diagnostics:" header + • source: (string) Include the diagnostic + source in the message. One of "always" or + "if_many". + • format: (function) A function that takes + a diagnostic as input and returns a + string. The return value is the text used + to display the diagnostic. + • prefix: (function or string) Prefix each + diagnostic in the floating window. If a + function, it must have the signature + (diagnostic, i, total) -> string, where + {i} is the index of the diagnostic being + evaluated and {total} is the total number + of diagnostics displayed in the window. + The returned string is prepended to each + diagnostic in the window. Otherwise, if + {prefix} is a string, it is prepended to + each diagnostic. + • update_in_insert: (default false) Update diagnostics in Insert mode (if false, diagnostics are updated on InsertLeave) @@ -382,6 +454,15 @@ get({bufnr}, {opts}) *vim.diagnostic.get()* Return: ~ table A list of diagnostic items |diagnostic-structure|. +get_namespace({namespace}) *vim.diagnostic.get_namespace()* + Get namespace metadata. + + Parameters: ~ + {ns} number Diagnostic namespace + + Return: ~ + table Namespace metadata + get_namespaces() *vim.diagnostic.get_namespaces()* Get current diagnostic namespaces. @@ -442,12 +523,10 @@ goto_next({opts}) *vim.diagnostic.goto_next()* • wrap: (boolean, default true) Whether to loop around file or not. Similar to 'wrapscan'. • severity: See |diagnostic-severity|. - • enable_popup: (boolean, default true) Call - |vim.diagnostic.show_line_diagnostics()| on - jump. - • popup_opts: (table) Table to pass as {opts} - parameter to - |vim.diagnostic.show_line_diagnostics()| + • float: (boolean or table, default true) If + "true", call |vim.diagnostic.open_float()| after + moving. If a table, pass the table as the {opts} + parameter to |vim.diagnostic.open_float()|. • win_id: (number, default 0) Window ID goto_prev({opts}) *vim.diagnostic.goto_prev()* @@ -468,7 +547,9 @@ hide({namespace}, {bufnr}) *vim.diagnostic.hide()* |vim.diagnostic.disable()|. Parameters: ~ - {namespace} number The diagnostic namespace + {namespace} number|nil Diagnostic namespace. When + omitted, hide diagnostics from all + namespaces. {bufnr} number|nil Buffer number. Defaults to the current buffer. @@ -508,6 +589,49 @@ match({str}, {pat}, {groups}, {severity_map}, {defaults}) diagnostic |diagnostic-structure| or `nil` if {pat} fails to match {str}. +open_float({bufnr}, {opts}) *vim.diagnostic.open_float()* + Show diagnostics in a floating window. + + Parameters: ~ + {bufnr} number|nil Buffer number. Defaults to the current + buffer. + {opts} table|nil Configuration table with the same keys + as |vim.lsp.util.open_floating_preview()| in + addition to the following: + • namespace: (number) Limit diagnostics to the + given namespace + • scope: (string, default "buffer") Show + diagnostics from the whole buffer ("buffer"), + the current cursor line ("line"), or the + current cursor position ("cursor"). + • pos: (number or table) If {scope} is "line" or + "cursor", use this position rather than the + cursor position. If a number, interpreted as a + line number; otherwise, a (row, col) tuple. + • severity_sort: (default false) Sort diagnostics + by severity. Overrides the setting from + |vim.diagnostic.config()|. + • severity: See |diagnostic-severity|. Overrides + the setting from |vim.diagnostic.config()|. + • show_header: (boolean, default true) Show + "Diagnostics:" header. Overrides the setting + from |vim.diagnostic.config()|. + • source: (string) Include the diagnostic source + in the message. One of "always" or "if_many". + Overrides the setting from + |vim.diagnostic.config()|. + • format: (function) A function that takes a + diagnostic as input and returns a string. The + return value is the text used to display the + diagnostic. Overrides the setting from + |vim.diagnostic.config()|. + • prefix: (function or string) Prefix each + diagnostic in the floating window. Overrides + the setting from |vim.diagnostic.config()|. + + Return: ~ + tuple ({float_bufnr}, {win_id}) + reset({namespace}, {bufnr}) *vim.diagnostic.reset()* Remove all diagnostics from the given namespace. @@ -518,7 +642,9 @@ reset({namespace}, {bufnr}) *vim.diagnostic.reset()* |vim.diagnostic.hide()|. Parameters: ~ - {namespace} number + {namespace} number|nil Diagnostic namespace. When + omitted, remove diagnostics from all + namespaces. {bufnr} number|nil Remove diagnostics for the given buffer. When omitted, diagnostics are removed for all buffers. @@ -569,7 +695,9 @@ show({namespace}, {bufnr}, {diagnostics}, {opts}) Display diagnostics for the given namespace and buffer. Parameters: ~ - {namespace} number Diagnostic namespace + {namespace} number|nil Diagnostic namespace. When + omitted, show diagnostics from all + namespaces. {bufnr} number|nil Buffer number. Defaults to the current buffer. {diagnostics} table|nil The diagnostics to display. When @@ -577,55 +705,11 @@ show({namespace}, {bufnr}, {diagnostics}, {opts}) given namespace and buffer. This can be used to display a list of diagnostics without saving them or to display only a - subset of diagnostics. + subset of diagnostics. May not be used when + {namespace} is nil. {opts} table|nil Display options. See |vim.diagnostic.config()|. - *vim.diagnostic.show_line_diagnostics()* -show_line_diagnostics({opts}, {bufnr}, {lnum}) - Open a floating window with the diagnostics from the given - line. - - Parameters: ~ - {opts} table Configuration table. See - |vim.diagnostic.show_position_diagnostics()|. - {bufnr} number|nil Buffer number. Defaults to the current - buffer. - {lnum} number|nil Line number. Defaults to line number - of cursor. - - Return: ~ - tuple ({popup_bufnr}, {win_id}) - - *vim.diagnostic.show_position_diagnostics()* -show_position_diagnostics({opts}, {bufnr}, {position}) - Open a floating window with the diagnostics at the given - position. - - Parameters: ~ - {opts} table|nil Configuration table with the same - keys as |vim.lsp.util.open_floating_preview()| - in addition to the following: - • namespace: (number) Limit diagnostics to the - given namespace - • severity: See |diagnostic-severity|. - • show_header: (boolean, default true) Show - "Diagnostics:" header - • source: (string) Include the diagnostic - source in the message. One of "always" or - "if_many". - • format: (function) A function that takes a - diagnostic as input and returns a string. - The return value is the text used to display - the diagnostic. - {bufnr} number|nil Buffer number. Defaults to the - current buffer. - {position} table|nil The (0,0)-indexed position. Defaults - to the current cursor position. - - Return: ~ - tuple ({popup_bufnr}, {win_id}) - toqflist({diagnostics}) *vim.diagnostic.toqflist()* Convert a list of diagnostics to a list of quickfix items that can be passed to |setqflist()| or |setloclist()|. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 6549d0b5f3..1b949d749c 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -4933,7 +4933,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()* behave :behave suboptions cmdline |cmdline-completion| result color color schemes - command Ex command (and arguments) + command Ex command compiler compilers cscope |:cscope| suboptions diff_buffer |:diffget| and |:diffput| completion @@ -6833,6 +6833,7 @@ match({expr}, {pat} [, {start} [, {count}]]) *match()* further down in the text. Can also be used as a |method|: > + GetText()->match('word') GetList()->match('word') < *matchadd()* *E798* *E799* *E801* *E957* @@ -6992,8 +6993,10 @@ matchlist({expr}, {pat} [, {start} [, {count}]]) *matchlist()* < Results in: ['acd', 'a', '', 'c', 'd', '', '', '', '', ''] When there is no match an empty list is returned. + You can pass in a List, but that is not very useful. + Can also be used as a |method|: > - GetList()->matchlist('word') + GetText()->matchlist('word') matchstr({expr}, {pat} [, {start} [, {count}]]) *matchstr()* Same as |match()|, but return the matched string. Example: > diff --git a/runtime/doc/indent.txt b/runtime/doc/indent.txt index dfd81d7170..1b42092616 100644 --- a/runtime/doc/indent.txt +++ b/runtime/doc/indent.txt @@ -604,26 +604,22 @@ CLOJURE *ft-clojure-indent* *clojure-indent* Clojure indentation differs somewhat from traditional Lisps, due in part to the use of square and curly brackets, and otherwise by community convention. These conventions are not universally followed, so the Clojure indent script -offers a few configurable options, listed below. +offers a few configuration options. -If the current vim does not include searchpairpos(), the indent script falls -back to normal 'lisp' indenting, and the following options are ignored. *g:clojure_maxlines* -Set maximum scan distance of searchpairpos(). Larger values trade performance -for correctness when dealing with very long forms. A value of 0 will scan -without limits. -> - " Default - let g:clojure_maxlines = 100 -< +Sets maximum scan distance of `searchpairpos()`. Larger values trade +performance for correctness when dealing with very long forms. A value of +0 will scan without limits. The default is 300. + + *g:clojure_fuzzy_indent* *g:clojure_fuzzy_indent_patterns* *g:clojure_fuzzy_indent_blacklist* The 'lispwords' option is a list of comma-separated words that mark special -forms whose subforms must be indented with two spaces. +forms whose subforms should be indented with two spaces. For example: > @@ -641,15 +637,11 @@ the fuzzy indent feature: let g:clojure_fuzzy_indent_patterns = ['^with', '^def', '^let'] let g:clojure_fuzzy_indent_blacklist = \ ['-fn$', '\v^with-%(meta|out-str|loading-context)$'] - - " Legacy comma-delimited string version; the list format above is - " recommended. Note that patterns are implicitly anchored with ^ and $ - let g:clojure_fuzzy_indent_patterns = 'with.*,def.*,let.*' < |g:clojure_fuzzy_indent_patterns| and |g:clojure_fuzzy_indent_blacklist| are -|Lists| of patterns that will be matched against the unquoted, unqualified -symbol at the head of a list. This means that a pattern like "^foo" will match -all these candidates: "foobar", "my.ns/foobar", and "#'foobar". +lists of patterns that will be matched against the unqualified symbol at the +head of a list. This means that a pattern like `"^foo"` will match all these +candidates: `foobar`, `my.ns/foobar`, and `#'foobar`. Each candidate word is tested for special treatment in this order: @@ -660,20 +652,22 @@ Each candidate word is tested for special treatment in this order: |g:clojure_fuzzy_indent_patterns| 4. Return false and indent normally otherwise + *g:clojure_special_indent_words* -Some forms in Clojure are indented so that every subform is indented only two -spaces, regardless of 'lispwords'. If you have a custom construct that should -be indented in this idiosyncratic fashion, you can add your symbols to the -default list below. +Some forms in Clojure are indented such that every subform is indented by only +two spaces, regardless of 'lispwords'. If you have a custom construct that +should be indented in this idiosyncratic fashion, you can add your symbols to +the default list below. > " Default let g:clojure_special_indent_words = \ 'deftype,defrecord,reify,proxy,extend-type,extend-protocol,letfn' < + *g:clojure_align_multiline_strings* -Align subsequent lines in multiline strings to the column after the opening +Align subsequent lines in multi-line strings to the column after the opening quote, instead of the same column. For example: @@ -690,11 +684,7 @@ For example: enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.") < -This option is off by default. -> - " Default - let g:clojure_align_multiline_strings = 0 -< + *g:clojure_align_subforms* By default, parenthesized compound forms that look like function calls and @@ -705,18 +695,14 @@ two spaces relative to the opening paren: bar baz) < -Setting this option changes this behavior so that all subforms are aligned to -the same column, emulating the default behavior of clojure-mode.el: +Setting this option to `1` changes this behaviour so that all subforms are +aligned to the same column, emulating the default behaviour of +clojure-mode.el: > (foo bar baz) < -This option is off by default. -> - " Default - let g:clojure_align_subforms = 0 -< FORTRAN *ft-fortran-indent* diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index c3421e6c82..83d201c23a 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -61,6 +61,10 @@ Example config (in init.vim): > -- See `:help omnifunc` and `:help ins-completion` for more information. vim.api.nvim_buf_set_option(0, 'omnifunc', 'v:lua.vim.lsp.omnifunc') + -- Use LSP as the handler for formatexpr. + -- See `:help formatexpr` for more information. + vim.api.nvim_buf_set_option(0, 'formatexpr', 'v:lua.vim.lsp.formatexpr()') + -- For plugins with an `on_attach` callback, call them here. For example: -- require('completion').on_attach() end @@ -452,6 +456,22 @@ LspSignatureActiveParameter |vim.lsp.handlers.signature_help()|. ============================================================================== +EVENTS *lsp-events* + +LspProgressUpdate *LspProgressUpdate* + Upon receipt of a progress notification from the server. See + |vim.lsp.util.get_progress_messages()|. + +LspRequest *LspRequest* + After a change to the active set of pending LSP requests. See {requests} + in |vim.lsp.client|. + +Example: > + autocmd User LspProgressUpdate redrawstatus + autocmd User LspRequest redrawstatus +< + +============================================================================== Lua module: vim.lsp *lsp-core* buf_attach_client({bufnr}, {client_id}) *vim.lsp.buf_attach_client()* @@ -608,6 +628,11 @@ client() *vim.lsp.client* server. • {handlers} (table): The handlers used by the client as described in |lsp-handler|. + • {requests} (table): The current pending requests in flight + to the server. Entries are key-value pairs with the key + being the request ID while the value is a table with `type`, + `bufnr`, and `method` key-value pairs. `type` is either "pending" + for an active request, or "cancel" for a cancel request. • {config} (table): copy of the table that was passed by the user to |vim.lsp.start_client()|. • {server_capabilities} (table): Response from the server @@ -670,7 +695,7 @@ omnifunc({findstart}, {base}) *vim.lsp.omnifunc()* {base} If findstart=0, text to match against Return: ~ - (number) Decided by`findstart`: + (number) Decided by {findstart}: • findstart=0: column where the completion starts, or -2 or -3 • findstart=1: list of matches (actually just calls @@ -1075,7 +1100,8 @@ rename({new_name}) *vim.lsp.buf.rename()* Parameters: ~ {new_name} (string) If not provided, the user will be - prompted for a new name using |input()|. + prompted for a new name using + |vim.ui.input()|. server_ready() *vim.lsp.buf.server_ready()* Checks whether the language servers attached to the current diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index a6ccf9f35c..ef2d87949d 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -393,6 +393,14 @@ where the args are converted to Lua values. The expression > is equivalent to the Lua chunk > return somemod.func(...) +In addition, functions of packages can be accessed like > + v:lua.require'mypack'.func(arg1, arg2) + v:lua.require'mypack.submod'.func(arg1, arg2) +Note: only single quote form without parens is allowed. Using +`require"mypack"` or `require('mypack')` as prefixes do NOT work (the latter +is still valid as a function call of itself, in case require returns a useful +value). + The `v:lua` prefix may be used to call Lua functions as |method|s. For example: > arg1->v:lua.somemod.func(arg2) @@ -409,7 +417,8 @@ For example consider the following Lua omnifunc handler: > end vim.api.nvim_buf_set_option(0, 'omnifunc', 'v:lua.mymod.omnifunc') -Note: the module ("mymod" in the above example) must be a Lua global. +Note: the module ("mymod" in the above example) must either be a Lua global, +or use the require syntax as specified above to access it from a package. Note: `v:lua` without a call is not allowed in a Vimscript expression: |Funcref|s cannot represent Lua functions. The following are errors: > @@ -689,15 +698,14 @@ vim.diff({a}, {b}, {opts}) *vim.diff()* ------------------------------------------------------------------------------ VIM.MPACK *lua-mpack* -The *vim.mpack* module provides packing and unpacking of lua objects to -msgpack encoded strings. |vim.NIL| and |vim.empty_dict()| are supported. +The *vim.mpack* module provides encoding and decoding of Lua objects to and +from msgpack-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|. -vim.mpack.pack({obj}) *vim.mpack.pack* - Packs a lua object {obj} and returns the msgpack representation as - a string +vim.mpack.encode({obj}) *vim.mpack.encode* + Encodes (or "packs") Lua object {obj} as msgpack in a Lua string. -vim.mpack.unpack({str}) *vim.mpack.unpack* - Unpacks the msgpack encoded {str} and returns a lua object +vim.mpack.decode({str}) *vim.mpack.decode* + Decodes (or "unpacks") the msgpack-encoded {str} to a Lua object. ------------------------------------------------------------------------------ VIM *lua-builtin* @@ -928,6 +936,7 @@ Example: > vim.g.foo = 5 -- Set the g:foo Vimscript variable. print(vim.g.foo) -- Get and print the g:foo Vimscript variable. vim.g.foo = nil -- Delete (:unlet) the Vimscript variable. + vim.b[2].foo = 6 -- Set b:foo for buffer 2 vim.g *vim.g* Global (|g:|) editor variables. @@ -935,15 +944,18 @@ vim.g *vim.g* vim.b *vim.b* Buffer-scoped (|b:|) variables for the current buffer. - Invalid or unset key returns `nil`. + Invalid or unset key returns `nil`. Can be indexed with + an integer to access variables for a specific buffer. vim.w *vim.w* Window-scoped (|w:|) variables for the current window. - Invalid or unset key returns `nil`. + Invalid or unset key returns `nil`. Can be indexed with + an integer to access variables for a specific window. vim.t *vim.t* Tabpage-scoped (|t:|) variables for the current tabpage. - Invalid or unset key returns `nil`. + Invalid or unset key returns `nil`. Can be indexed with + an integer to access variables for a specific tabpage. vim.v *vim.v* |v:| variables. @@ -1518,7 +1530,7 @@ tbl_flatten({t}) *vim.tbl_flatten()* Flattened copy of the given list-like table. See also: ~ - Fromhttps://github.com/premake/premake-core/blob/master/src/base/table.lua + From https://github.com/premake/premake-core/blob/master/src/base/table.lua tbl_isempty({t}) *vim.tbl_isempty()* Checks if a table is empty. @@ -1554,7 +1566,7 @@ tbl_keys({t}) *vim.tbl_keys()* list of keys See also: ~ - Fromhttps://github.com/premake/premake-core/blob/master/src/base/table.lua + From https://github.com/premake/premake-core/blob/master/src/base/table.lua tbl_map({func}, {t}) *vim.tbl_map()* Apply a function to all values of a table. @@ -1685,6 +1697,28 @@ uri_to_fname({uri}) *vim.uri_to_fname()* ============================================================================== Lua module: ui *lua-ui* +input({opts}, {on_confirm}) *vim.ui.input()* + Prompts the user for input + + Parameters: ~ + {opts} table Additional options. See |input()| + • prompt (string|nil) Text of the prompt. + Defaults to `Input:` . + • default (string|nil) Default reply to the + input + • completion (string|nil) Specifies type of + completion supported for input. Supported + types are the same that can be supplied to + a user-defined command using the + "-complete=" argument. See + |:command-completion| + • highlight (function) Function that will be + used for highlighting user inputs. + {on_confirm} function ((input|nil) -> ()) Called once the + user confirms or abort the input. `input` is + what the user typed. `nil` if the user + aborted the dialog. + select({items}, {opts}, {on_choice}) *vim.ui.select()* Prompts the user to pick a single item from a collection of entries diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 64c0d96aed..90d4c4de93 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -877,6 +877,9 @@ Also note that the 'clipboard' option is temporarily emptied to avoid clobbering the `"*` or `"+` registers, if its value contains the item `unnamed` or `unnamedplus`. +The `mode()` function will return the state as it will be after applying the +operator. + ============================================================================== 2. Abbreviations *abbreviations* *Abbreviations* diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index d25d505728..399a59251a 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1115,6 +1115,8 @@ A jump table for the options with a short description can be found at |Q_op|. Also see |win_gettype()|, which returns the type of the window. Be careful with changing this option, it can have many side effects! + One such effect is that Vim will not check the timestamp of the file, + if the file is changed by another program this will not be noticed. A "quickfix" buffer is only used for the error list and the location list. This value is set by the |:cwindow| and |:lwindow| commands and @@ -3703,9 +3705,10 @@ A jump table for the options with a short description can be found at |Q_op|. *'list'* *'nolist'* 'list' boolean (default off) local to window - List mode: Show tabs as CTRL-I is displayed, display $ after end of - line. Useful to see the difference between tabs and spaces and for - trailing blanks. Further changed by the 'listchars' option. + List mode: By default, show tabs as ">", trailing spaces as "-", and + non-breakable space characters as "+". Useful to see the difference + between tabs and spaces and for trailing blanks. Further changed by + the 'listchars' option. The cursor is displayed at the start of the space a Tab character occupies, not at the end as usual in Normal mode. To get this cursor diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index ebc7ff6b80..e423c59efe 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -1045,33 +1045,47 @@ This works immediately. CLOJURE *ft-clojure-syntax* -The default syntax groups can be augmented through the -*g:clojure_syntax_keywords* and *b:clojure_syntax_keywords* variables. The -value should be a |Dictionary| of syntax group names to a |List| of custom -identifiers: + *g:clojure_syntax_keywords* + +Syntax highlighting of public vars in "clojure.core" is provided by default, +but additional symbols can be highlighted by adding them to the +|g:clojure_syntax_keywords| variable. The value should be a |Dictionary| of +syntax group names, each containing a |List| of identifiers. > let g:clojure_syntax_keywords = { - \ 'clojureMacro': ["defproject", "defcustom"], - \ 'clojureFunc': ["string/join", "string/replace"] + \ 'clojureMacro': ["defproject", "defcustom"], + \ 'clojureFunc': ["string/join", "string/replace"] \ } < Refer to the Clojure syntax script for valid syntax group names. -If the |buffer-variable| *b:clojure_syntax_without_core_keywords* is set, only -language constants and special forms are matched. +There is also *b:clojure_syntax_keywords* which is a buffer-local variant of +this variable intended for use by plugin authors to highlight symbols +dynamically. + +By setting the *b:clojure_syntax_without_core_keywords* variable, vars from +"clojure.core" will not be highlighted by default. This is useful for +namespaces that have set `(:refer-clojure :only [])` + -Setting *g:clojure_fold* enables folding Clojure code via the syntax engine. -Any list, vector, or map that extends over more than one line can be folded -using the standard Vim |fold-commands|. + *g:clojure_fold* -Please note that this option does not work with scripts that redefine the -bracket syntax regions, such as rainbow-parentheses plugins. +Setting |g:clojure_fold| to `1` will enable the folding of Clojure code. Any +list, vector or map that extends over more than one line can be folded using +the standard Vim |fold-commands|. -This option is off by default. + + *g:clojure_discard_macro* + +Set this variable to `1` to enable basic highlighting of Clojure's "discard +reader macro". > - " Default - let g:clojure_fold = 0 + #_(defn foo [x] + (println x)) < +Note that this option will not correctly highlight stacked discard macros +(e.g. `#_#_`). + COBOL *cobol.vim* *ft-cobol-syntax* @@ -4768,7 +4782,7 @@ in their own color. Doesn't work recursively, thus you can't use ":colorscheme" in a color scheme script. - To customize a colorscheme use another name, e.g. + To customize a color scheme use another name, e.g. "~/.config/nvim/colors/mine.vim", and use `:runtime` to load the original colorscheme: > runtime colors/evening.vim diff --git a/runtime/doc/tips.txt b/runtime/doc/tips.txt index 27b6ca2885..b77c7d9a6d 100644 --- a/runtime/doc/tips.txt +++ b/runtime/doc/tips.txt @@ -464,6 +464,7 @@ the current window, try this custom `:HelpCurwin` command: endif if !empty(getcompletion(a:subject, 'help')) execute mods .. ' edit ' .. &helpfile + set buftype=help endif return 'help ' .. a:subject endfunction diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index 5484e27797..b0e0bdcb84 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -116,9 +116,9 @@ g8 Print the hex values of the bytes used in the *:l* *:list* :[range]l[ist] [count] [flags] - Same as :print, but display unprintable characters - with '^' and put $ after the line. This can be - further changed with the 'listchars' option. + Same as :print, but show tabs as ">", trailing spaces + as "-", and non-breakable space characters as "+" by + default. Further changed by the 'listchars' option. See |ex-flags| for [flags]. *:nu* *:number* diff --git a/runtime/ftplugin/changelog.vim b/runtime/ftplugin/changelog.vim index 257e9cd9d4..e9df63f8c9 100644 --- a/runtime/ftplugin/changelog.vim +++ b/runtime/ftplugin/changelog.vim @@ -2,7 +2,7 @@ " Language: generic Changelog file " Maintainer: Martin Florian <marfl@posteo.de> " Previous Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2015-10-25 +" Latest Revision: 2021-10-17 " Variables: " g:changelog_timeformat (deprecated: use g:changelog_dateformat instead) - " description: the timeformat used in ChangeLog entries. @@ -55,7 +55,7 @@ if &filetype == 'changelog' elseif $EMAIL_ADDRESS != "" return $EMAIL_ADDRESS endif - + let login = s:login() return printf('%s <%s@%s>', s:name(login), login, s:hostname()) endfunction @@ -223,12 +223,6 @@ if &filetype == 'changelog' let &paste = save_paste endfunction - if exists(":NewChangelogEntry") != 2 - nnoremap <buffer> <silent> <Leader>o :<C-u>call <SID>new_changelog_entry('')<CR> - xnoremap <buffer> <silent> <Leader>o :<C-u>call <SID>new_changelog_entry('')<CR> - command! -nargs=0 NewChangelogEntry call s:new_changelog_entry('') - endif - let b:undo_ftplugin = "setl com< fo< et< ai<" setlocal comments= @@ -241,14 +235,26 @@ if &filetype == 'changelog' let b:undo_ftplugin .= " tw<" endif + if !exists("no_plugin_maps") && !exists("no_changelog_maps") && exists(":NewChangelogEntry") != 2 + nnoremap <buffer> <silent> <Leader>o :<C-u>call <SID>new_changelog_entry('')<CR> + xnoremap <buffer> <silent> <Leader>o :<C-u>call <SID>new_changelog_entry('')<CR> + command! -buffer -nargs=0 NewChangelogEntry call s:new_changelog_entry('') + let b:undo_ftplugin .= " | sil! exe 'nunmap <buffer> <Leader>o'" . + \ " | sil! exe 'vunmap <buffer> <Leader>o'" . + \ " | sil! delc NewChangelogEntry" + endif + let &cpo = s:cpo_save unlet s:cpo_save else let s:cpo_save = &cpo set cpo&vim - " Add the Changelog opening mapping - nnoremap <silent> <Leader>o :call <SID>open_changelog()<CR> + if !exists("no_plugin_maps") && !exists("no_changelog_maps") + " Add the Changelog opening mapping + nnoremap <silent> <Leader>o :call <SID>open_changelog()<CR> + let b:undo_ftplugin .= " | silent! exe 'nunmap <buffer> <Leader>o" + endif function! s:open_changelog() let path = expand('%:p:h') diff --git a/runtime/ftplugin/clojure.vim b/runtime/ftplugin/clojure.vim index cb75506dbb..81d53b1227 100644 --- a/runtime/ftplugin/clojure.vim +++ b/runtime/ftplugin/clojure.vim @@ -1,11 +1,11 @@ " Vim filetype plugin file " Language: Clojure -" Maintainer: Alex Vear <av@axvr.io> +" Maintainer: Alex Vear <alex@vear.uk> " Former Maintainers: Sung Pae <self@sungpae.com> " Meikel Brandmeyer <mb@kotka.de> " URL: https://github.com/clojure-vim/clojure.vim " License: Vim (see :h license) -" Last Change: 2021-02-13 +" Last Change: 2021-10-26 if exists("b:did_ftplugin") finish @@ -17,7 +17,7 @@ set cpo&vim let b:undo_ftplugin = 'setlocal iskeyword< define< formatoptions< comments< commentstring< lispwords<' -setlocal iskeyword+=?,-,*,!,+,/,=,<,>,.,:,$ +setlocal iskeyword+=?,-,*,!,+,/,=,<,>,.,:,$,%,&,\| " There will be false positives, but this is better than missing the whole set " of user-defined def* definitions. @@ -43,7 +43,7 @@ setlocal commentstring=;\ %s " specially and hence are not indented specially. " " -*- LISPWORDS -*- -" Generated from https://github.com/clojure-vim/clojure.vim/blob/f8594e7030cdfb0b7990ac92953c77a08a7220f0/clj/src/vim_clojure_static/generate.clj +" Generated from https://github.com/clojure-vim/clojure.vim/blob/62b215f079ce0f3834fd295c7a7f6bd8cc54bcc3/clj/src/vim_clojure_static/generate.clj setlocal lispwords=as->,binding,bound-fn,case,catch,cond->,cond->>,condp,def,definline,definterface,defmacro,defmethod,defmulti,defn,defn-,defonce,defprotocol,defrecord,defstruct,deftest,deftest-,deftype,doseq,dotimes,doto,extend,extend-protocol,extend-type,fn,for,if,if-let,if-not,if-some,let,letfn,locking,loop,ns,proxy,reify,set-test,testing,when,when-first,when-let,when-not,when-some,while,with-bindings,with-in-str,with-local-vars,with-open,with-precision,with-redefs,with-redefs-fn,with-test " Provide insert mode completions for special forms and clojure.core. As @@ -64,8 +64,8 @@ if exists('loaded_matchit') let b:undo_ftplugin .= ' | unlet! b:match_words b:match_skip' endif -" Win32 can filter files in the browse dialog -if has("gui_win32") && !exists("b:browsefilter") +" Filter files in the browse dialog +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") let b:browsefilter = "Clojure Source Files (*.clj)\t*.clj\n" . \ "ClojureScript Source Files (*.cljs)\t*.cljs\n" . \ "Java Source Files (*.java)\t*.java\n" . diff --git a/runtime/ftplugin/mail.vim b/runtime/ftplugin/mail.vim index 2a6bf4c046..f12022305f 100644 --- a/runtime/ftplugin/mail.vim +++ b/runtime/ftplugin/mail.vim @@ -1,7 +1,7 @@ " Vim filetype plugin file " Language: Mail " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2012 Nov 20 +" Last Change: 2021 Oct 23 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -26,6 +26,14 @@ setlocal fo+=tcql " Add n:> to 'comments, in case it was removed elsewhere setlocal comments+=n:> +" .eml files are universally formatted with DOS line-endings, per RFC5322. +" If the file was not DOS the it will be marked as changed, which is probably +" a good thing. +if expand('%:e') ==? 'eml' + let b:undo_ftplugin ..= " fileformat=" .. &fileformat + setlocal fileformat=dos +endif + " Add mappings, unless the user doesn't want this. if !exists("no_plugin_maps") && !exists("no_mail_maps") " Quote text by inserting "> " diff --git a/runtime/ftplugin/meson.vim b/runtime/ftplugin/meson.vim index d48fa1dfd1..1ce9a03037 100644 --- a/runtime/ftplugin/meson.vim +++ b/runtime/ftplugin/meson.vim @@ -12,9 +12,28 @@ set cpo&vim setlocal commentstring=#\ %s setlocal comments=:# +setlocal formatoptions+=croql formatoptions-=t -setlocal shiftwidth=2 -setlocal softtabstop=2 +let b:undo_ftplugin = "setl com< cms< fo<" + +if get(g:, "meson_recommended_style", 1) + setlocal expandtab + setlocal shiftwidth=2 + setlocal softtabstop=2 + let b:undo_ftplugin .= " | setl et< sts< sw<" +endif + +if exists("loaded_matchit") && !exists("b:match_words") + let b:match_words = '\<if\>:\<elif\>:\<else\>:\<endif\>,' . + \ '\<foreach\>:\<break\>:\<continue\>:\<endforeach\>' + let b:undo_ftplugin .= " | unlet! b:match_words" +endif + +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "Meson Build Files (meson.build)\tmeson.build\n" . + \ "All Files (*.*)\t*.*\n" + let b:undo_ftplugin .= " | unlet! b:browsefilter" +endif let &cpo = s:keepcpo unlet s:keepcpo diff --git a/runtime/ftplugin/nsis.vim b/runtime/ftplugin/nsis.vim index 1a35127c86..3dc0d6318a 100644 --- a/runtime/ftplugin/nsis.vim +++ b/runtime/ftplugin/nsis.vim @@ -3,7 +3,7 @@ " Maintainer: Ken Takata " URL: https://github.com/k-takata/vim-nsis " Previous Maintainer: Nikolai Weibull <now@bitwi.se> -" Last Change: 2018-01-26 +" Last Change: 2021-10-18 if exists("b:did_ftplugin") finish @@ -15,7 +15,6 @@ set cpo&vim let b:did_ftplugin = 1 let b:undo_ftplugin = "setl com< cms< fo< def< inc<" - \ " | unlet! b:match_ignorecase b:match_words" setlocal comments=s1:/*,mb:*,ex:*/,b:#,:; commentstring=;\ %s setlocal formatoptions-=t formatoptions+=croql @@ -37,6 +36,7 @@ if exists("loaded_matchit") \ '\${MementoSection}:\${MementoSectionEnd},' . \ '!if\%(\%(macro\)\?n\?def\)\?\>:!else\>:!endif\>,' . \ '!macro\>:!macroend\>' + let b:undo_ftplugin .= " | unlet! b:match_ignorecase b:match_words" endif let &cpo = s:cpo_save diff --git a/runtime/ftplugin/spec.vim b/runtime/ftplugin/spec.vim index 75eebec56a..ce00021a69 100644 --- a/runtime/ftplugin/spec.vim +++ b/runtime/ftplugin/spec.vim @@ -18,8 +18,8 @@ if !exists("no_plugin_maps") && !exists("no_spec_maps") endif endif -if !hasmapto("call SpecChangelog(\"\")<CR>") - noremap <buffer> <unique> <script> <Plug>SpecChangelog :call SpecChangelog("")<CR> +if !hasmapto("call <SID>SpecChangelog(\"\")<CR>") + noremap <buffer> <unique> <script> <Plug>SpecChangelog :call <SID>SpecChangelog("")<CR> endif if !exists("*s:GetRelVer") diff --git a/runtime/indent/clojure.vim b/runtime/indent/clojure.vim index 30a0b478e2..fadcaf4b4a 100644 --- a/runtime/indent/clojure.vim +++ b/runtime/indent/clojure.vim @@ -1,11 +1,11 @@ " Vim indent file " Language: Clojure -" Maintainer: Alex Vear <av@axvr.io> +" Maintainer: Alex Vear <alex@vear.uk> " Former Maintainers: Sung Pae <self@sungpae.com> " Meikel Brandmeyer <mb@kotka.de> " URL: https://github.com/clojure-vim/clojure.vim " License: Vim (see :h license) -" Last Change: 2021-02-13 +" Last Change: 2021-10-26 if exists("b:did_indent") finish @@ -24,7 +24,7 @@ setlocal indentkeys=!,o,O if exists("*searchpairpos") if !exists('g:clojure_maxlines') - let g:clojure_maxlines = 100 + let g:clojure_maxlines = 300 endif if !exists('g:clojure_fuzzy_indent') @@ -71,14 +71,10 @@ if exists("*searchpairpos") return s:current_char() =~# '\v[\(\)\[\]\{\}]' && !s:ignored_region() endfunction - " Returns 1 if string matches a pattern in 'patterns', which may be a - " list of patterns, or a comma-delimited string of implicitly anchored - " patterns. + " Returns 1 if string matches a pattern in 'patterns', which should be + " a list of patterns. function! s:match_one(patterns, string) - let list = type(a:patterns) == type([]) - \ ? a:patterns - \ : map(split(a:patterns, ','), '"^" . v:val . "$"') - for pat in list + for pat in a:patterns if a:string =~# pat | return 1 | endif endfor endfunction @@ -215,9 +211,10 @@ if exists("*searchpairpos") endfunction " Check if form is a reader conditional, that is, it is prefixed by #? - " or @#? + " or #?@ function! s:is_reader_conditional_special_case(position) return getline(a:position[0])[a:position[1] - 3 : a:position[1] - 2] == "#?" + \|| getline(a:position[0])[a:position[1] - 4 : a:position[1] - 2] == "#?@" endfunction " Returns 1 for opening brackets, -1 for _anything else_. diff --git a/runtime/indent/dosbatch.vim b/runtime/indent/dosbatch.vim index aea2a184d4..d24b139242 100644 --- a/runtime/indent/dosbatch.vim +++ b/runtime/indent/dosbatch.vim @@ -2,7 +2,7 @@ " Language: MSDOS batch file (with NT command extensions) " Maintainer: Ken Takata " URL: https://github.com/k-takata/vim-dosbatch-indent -" Last Change: 2017 May 10 +" Last Change: 2021-10-18 " Filenames: *.bat " License: VIM License @@ -17,6 +17,8 @@ setlocal indentexpr=GetDosBatchIndent(v:lnum) setlocal indentkeys=!^F,o,O setlocal indentkeys+=0=) +let b:undo_indent = "setl ai< inde< indk< si<" + if exists("*GetDosBatchIndent") finish endif diff --git a/runtime/indent/meson.vim b/runtime/indent/meson.vim index 549209ca33..09131f5723 100644 --- a/runtime/indent/meson.vim +++ b/runtime/indent/meson.vim @@ -20,6 +20,8 @@ setlocal autoindent " indentexpr isn't much help otherwise setlocal indentexpr=GetMesonIndent(v:lnum) setlocal indentkeys+==elif,=else,=endforeach,=endif,0) +let b:undo_indent = "setl ai< inde< indk< lisp<" + " Only define the function once. if exists("*GetMesonIndent") finish diff --git a/runtime/indent/nsis.vim b/runtime/indent/nsis.vim index 223f4fa28e..5d3decca37 100644 --- a/runtime/indent/nsis.vim +++ b/runtime/indent/nsis.vim @@ -2,7 +2,7 @@ " Language: NSIS script " Maintainer: Ken Takata " URL: https://github.com/k-takata/vim-nsis -" Last Change: 2018-01-21 +" Last Change: 2021-10-18 " Filenames: *.nsi " License: VIM License @@ -17,6 +17,8 @@ setlocal indentexpr=GetNsisIndent(v:lnum) setlocal indentkeys=!^F,o,O setlocal indentkeys+==~${Else,=~${EndIf,=~${EndUnless,=~${AndIf,=~${AndUnless,=~${OrIf,=~${OrUnless,=~${Case,=~${Default,=~${EndSelect,=~${EndSwith,=~${Loop,=~${Next,=~${MementoSectionEnd,=~FunctionEnd,=~SectionEnd,=~SectionGroupEnd,=~PageExEnd,0=~!macroend,0=~!if,0=~!else,0=~!endif +let b:undo_indent = "setl ai< inde< indk< si<" + if exists("*GetNsisIndent") finish endif diff --git a/runtime/indent/teraterm.vim b/runtime/indent/teraterm.vim index 35d7354290..181c9a343f 100644 --- a/runtime/indent/teraterm.vim +++ b/runtime/indent/teraterm.vim @@ -3,7 +3,7 @@ " Based on Tera Term Version 4.100 " Maintainer: Ken Takata " URL: https://github.com/k-takata/vim-teraterm -" Last Change: 2018-08-31 +" Last Change: 2021-10-18 " Filenames: *.ttl " License: VIM License @@ -18,6 +18,8 @@ setlocal indentexpr=GetTeraTermIndent(v:lnum) setlocal indentkeys=!^F,o,O,e setlocal indentkeys+==elseif,=endif,=loop,=next,=enduntil,=endwhile +let b:undo_indent = "setl ai< inde< indk< si<" + if exists("*GetTeraTermIndent") finish endif diff --git a/runtime/indent/vim.vim b/runtime/indent/vim.vim index ee3d39490d..a98c75e541 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: 2021 Apr 18 +" Last Change: 2021 Nov 03 " Only load this indent file when no other was loaded. if exists("b:did_indent") @@ -107,7 +107,7 @@ function GetVimIndentIntern() if i >= 0 let ind += shiftwidth() if strpart(prev_text, i, 1) == '|' && has('syntax_items') - \ && synIDattr(synID(lnum, i, 1), "name") =~ '\(Comment\|String\)$' + \ && synIDattr(synID(lnum, i, 1), "name") =~ '\(Comment\|String\|PatSep\)$' let ind -= shiftwidth() endif endif diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 326932d982..b30a678eeb 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -1,3 +1,5 @@ +local if_nil = vim.F.if_nil + local M = {} M.severity = { @@ -19,10 +21,21 @@ local global_diagnostic_options = { signs = true, underline = true, virtual_text = true, + float = true, update_in_insert = false, severity_sort = false, } +M.handlers = setmetatable({}, { + __newindex = function(t, name, handler) + vim.validate { handler = {handler, "t" } } + rawset(t, name, handler) + if not global_diagnostic_options[name] then + global_diagnostic_options[name] = true + end + end, +}) + -- Local functions {{{ ---@private @@ -54,7 +67,7 @@ end local function prefix_source(source, diagnostics) vim.validate { source = {source, function(v) return v == "always" or v == "if_many" - end, "Invalid value for option 'source'" } } + end, "'always' or 'if_many'" } } if source == "if_many" then local sources = {} @@ -96,31 +109,9 @@ end local all_namespaces = {} ---@private -local function get_namespace(ns) - if not all_namespaces[ns] then - local name - for k, v in pairs(vim.api.nvim_get_namespaces()) do - if ns == v then - name = k - break - end - end - - assert(name, "namespace does not exist or is anonymous") - - all_namespaces[ns] = { - name = name, - sign_group = string.format("vim.diagnostic.%s", name), - opts = {} - } - end - return all_namespaces[ns] -end - ----@private local function enabled_value(option, namespace) - local ns = get_namespace(namespace) - if type(ns.opts[option]) == "table" then + local ns = namespace and M.get_namespace(namespace) or {} + if ns.opts and type(ns.opts[option]) == "table" then return ns.opts[option] end @@ -153,8 +144,9 @@ end ---@private local function get_resolved_options(opts, namespace, bufnr) - local ns = get_namespace(namespace) - local resolved = vim.tbl_extend('keep', opts or {}, ns.opts, global_diagnostic_options) + local ns = namespace and M.get_namespace(namespace) or {} + -- Do not use tbl_deep_extend so that an empty table can be used to reset to default values + local resolved = vim.tbl_extend('keep', opts or {}, ns.opts or {}, global_diagnostic_options) for k in pairs(global_diagnostic_options) do if resolved[k] ~= nil then resolved[k] = resolve_optional_value(k, resolved[k], namespace, bufnr) @@ -323,7 +315,7 @@ end ---@private local function save_extmarks(namespace, bufnr) - bufnr = bufnr == 0 and vim.api.nvim_get_current_buf() or bufnr + bufnr = get_bufnr(bufnr) if not diagnostic_attached_buffers[bufnr] then vim.api.nvim_buf_attach(bufnr, false, { on_lines = function(_, _, _, _, _, last) @@ -341,7 +333,7 @@ local registered_autocmds = {} ---@private local function make_augroup_key(namespace, bufnr) - local ns = get_namespace(namespace) + local ns = M.get_namespace(namespace) return string.format("DiagnosticInsertLeave:%s:%s", bufnr, ns.name) end @@ -354,19 +346,15 @@ local function schedule_display(namespace, bufnr, args) local key = make_augroup_key(namespace, bufnr) if not registered_autocmds[key] then - vim.cmd(string.format("augroup %s", key)) - vim.cmd(" au!") - vim.cmd( - string.format( - [[autocmd %s <buffer=%s> lua vim.diagnostic._execute_scheduled_display(%s, %s)]], - table.concat(insert_leave_auto_cmds, ","), - bufnr, - namespace, - bufnr - ) - ) - vim.cmd("augroup END") - + vim.cmd(string.format([[augroup %s + au! + autocmd %s <buffer=%s> lua vim.diagnostic._execute_scheduled_display(%s, %s) + augroup END]], + key, + table.concat(insert_leave_auto_cmds, ","), + bufnr, + namespace, + bufnr)) registered_autocmds[key] = true end end @@ -376,77 +364,14 @@ local function clear_scheduled_display(namespace, bufnr) local key = make_augroup_key(namespace, bufnr) if registered_autocmds[key] then - vim.cmd(string.format("augroup %s", key)) - vim.cmd(" au!") - vim.cmd("augroup END") - + vim.cmd(string.format([[augroup %s + au! + augroup END]], key)) registered_autocmds[key] = nil end end ---@private ---- Open a floating window with the provided diagnostics ----@param opts table Configuration table ---- - show_header (boolean, default true): Show "Diagnostics:" header ---- - all opts for |vim.util.open_floating_preview()| can be used here ----@param diagnostics table: The diagnostics to display ----@return table {popup_bufnr, win_id} -local function show_diagnostics(opts, diagnostics) - if not diagnostics or vim.tbl_isempty(diagnostics) then - return - end - local lines = {} - local highlights = {} - local show_header = vim.F.if_nil(opts.show_header, true) - if show_header then - table.insert(lines, "Diagnostics:") - table.insert(highlights, {0, "Bold"}) - end - - if opts.format then - diagnostics = reformat_diagnostics(opts.format, diagnostics) - end - - if opts.source then - diagnostics = prefix_source(opts.source, diagnostics) - end - - -- Use global setting for severity_sort since 'show_diagnostics' is namespace - -- independent - local severity_sort = global_diagnostic_options.severity_sort - if severity_sort then - if type(severity_sort) == "table" and severity_sort.reverse then - table.sort(diagnostics, function(a, b) return a.severity > b.severity end) - else - table.sort(diagnostics, function(a, b) return a.severity < b.severity end) - end - end - - for i, diagnostic in ipairs(diagnostics) do - local prefix = string.format("%d. ", i) - local hiname = floating_highlight_map[diagnostic.severity] - assert(hiname, 'unknown severity: ' .. tostring(diagnostic.severity)) - - local message_lines = vim.split(diagnostic.message, '\n', true) - table.insert(lines, prefix..message_lines[1]) - table.insert(highlights, {#prefix, hiname}) - for j = 2, #message_lines do - table.insert(lines, string.rep(' ', #prefix) .. message_lines[j]) - table.insert(highlights, {0, hiname}) - end - end - - local popup_bufnr, winnr = require('vim.lsp.util').open_floating_preview(lines, 'plaintext', opts) - for i, hi in ipairs(highlights) do - local prefixlen, hiname = unpack(hi) - -- Start highlight after the prefix - vim.api.nvim_buf_add_highlight(popup_bufnr, -1, hiname, i-1, prefixlen, -1) - end - - return popup_bufnr, winnr -end - ----@private local function set_list(loclist, opts) opts = opts or {} local open = vim.F.if_nil(opts.open, true) @@ -469,6 +394,7 @@ local function set_list(loclist, opts) end ---@private +--- To (slightly) improve performance, modifies diagnostics in place. local function clamp_line_numbers(bufnr, diagnostics) local buf_line_count = vim.api.nvim_buf_line_count(bufnr) if buf_line_count == 0 then @@ -526,7 +452,7 @@ end local function diagnostic_move_pos(opts, pos) opts = opts or {} - local enable_popup = vim.F.if_nil(opts.enable_popup, true) + local float = vim.F.if_nil(opts.float, true) local win_id = opts.win_id or vim.api.nvim_get_current_win() if not pos then @@ -539,10 +465,13 @@ local function diagnostic_move_pos(opts, pos) vim.api.nvim_win_set_cursor(win_id, {pos[1] + 1, pos[2]}) - if enable_popup then - -- This is a bit weird... I'm surprised that we need to wait til the next tick to do this. + if float then + local float_opts = type(float) == "table" and float or {} vim.schedule(function() - M.show_position_diagnostics(opts.popup_opts, vim.api.nvim_win_get_buf(win_id)) + M.open_float( + vim.api.nvim_win_get_buf(win_id), + vim.tbl_extend("keep", float_opts, {scope="cursor"}) + ) end) end end @@ -561,12 +490,12 @@ end --- --- For example, if a user enables virtual text globally with --- <pre> ---- vim.diagnostic.config({virt_text = true}) +--- vim.diagnostic.config({virtual_text = true}) --- </pre> --- --- and a diagnostic producer sets diagnostics with --- <pre> ---- vim.diagnostic.set(ns, 0, diagnostics, {virt_text = false}) +--- vim.diagnostic.set(ns, 0, diagnostics, {virtual_text = false}) --- </pre> --- --- then virtual text will not be enabled for those diagnostics. @@ -603,6 +532,19 @@ end --- * priority: (number, default 10) Base priority to use for signs. When --- {severity_sort} is used, the priority of a sign is adjusted based on --- its severity. Otherwise, all signs use the same priority. +--- - float: Options for floating windows: +--- * severity: See |diagnostic-severity|. +--- * show_header: (boolean, default true) Show "Diagnostics:" header +--- * source: (string) Include the diagnostic source in +--- the message. One of "always" or "if_many". +--- * format: (function) A function that takes a diagnostic as input and returns a +--- string. The return value is the text used to display the diagnostic. +--- * prefix: (function or string) Prefix each diagnostic in the floating window. If +--- a function, it must have the signature (diagnostic, i, total) -> string, +--- where {i} is the index of the diagnostic being evaluated and {total} is +--- the total number of diagnostics displayed in the window. The returned +--- string is prepended to each diagnostic in the window. Otherwise, +--- if {prefix} is a string, it is prepended to each diagnostic. --- - update_in_insert: (default false) Update diagnostics in Insert mode (if false, --- diagnostics are updated on InsertLeave) --- - severity_sort: (default false) Sort diagnostics by severity. This affects the order in @@ -620,7 +562,7 @@ function M.config(opts, namespace) local t if namespace then - local ns = get_namespace(namespace) + local ns = M.get_namespace(namespace) t = ns.opts else t = global_diagnostic_options @@ -672,7 +614,7 @@ function M.set(namespace, bufnr, diagnostics, opts) -- Clean up our data when the buffer unloads. vim.api.nvim_buf_attach(bufnr, false, { on_detach = function(_, b) - clear_diagnostic_cache(b, namespace) + clear_diagnostic_cache(namespace, b) diagnostic_cleanup[b][namespace] = nil end }) @@ -687,6 +629,32 @@ function M.set(namespace, bufnr, diagnostics, opts) vim.api.nvim_command("doautocmd <nomodeline> User DiagnosticsChanged") end +--- Get namespace metadata. +--- +---@param ns number Diagnostic namespace +---@return table Namespace metadata +function M.get_namespace(namespace) + vim.validate { namespace = { namespace, 'n' } } + if not all_namespaces[namespace] then + local name + for k, v in pairs(vim.api.nvim_get_namespaces()) do + if namespace == v then + name = k + break + end + end + + assert(name, "namespace does not exist or is anonymous") + + all_namespaces[namespace] = { + name = name, + opts = {}, + user_data = {}, + } + end + return all_namespaces[namespace] +end + --- Get current diagnostic namespaces. --- ---@return table A list of active diagnostic namespaces |vim.diagnostic|. @@ -825,10 +793,9 @@ end --- |nvim_win_get_cursor()|. Defaults to the current cursor position. --- - wrap: (boolean, default true) Whether to loop around file or not. Similar to 'wrapscan'. --- - severity: See |diagnostic-severity|. ---- - enable_popup: (boolean, default true) Call |vim.diagnostic.show_line_diagnostics()| ---- on jump. ---- - popup_opts: (table) Table to pass as {opts} parameter to ---- |vim.diagnostic.show_line_diagnostics()| +--- - float: (boolean or table, default true) If "true", call |vim.diagnostic.open_float()| +--- after moving. If a table, pass the table as the {opts} parameter to +--- |vim.diagnostic.open_float()|. --- - win_id: (number, default 0) Window ID function M.goto_next(opts) return diagnostic_move_pos( @@ -837,156 +804,171 @@ function M.goto_next(opts) ) end --- Diagnostic Setters {{{ - ---- Set signs for given diagnostics. ---- ----@param namespace number The diagnostic namespace ----@param bufnr number Buffer number ----@param diagnostics table A list of diagnostic items |diagnostic-structure|. When omitted the ---- current diagnostics in the given buffer are used. ----@param opts table Configuration table with the following keys: ---- - priority: Set the priority of the signs |sign-priority|. ----@private -function M._set_signs(namespace, bufnr, diagnostics, opts) - vim.validate { - namespace = {namespace, 'n'}, - bufnr = {bufnr, 'n'}, - diagnostics = {diagnostics, 't'}, - opts = {opts, 't', true}, - } +M.handlers.signs = { + show = function(namespace, bufnr, diagnostics, opts) + vim.validate { + namespace = {namespace, 'n'}, + bufnr = {bufnr, 'n'}, + diagnostics = {diagnostics, 't'}, + opts = {opts, 't', true}, + } - bufnr = get_bufnr(bufnr) - opts = get_resolved_options({ signs = opts }, namespace, bufnr) + bufnr = get_bufnr(bufnr) - if opts.signs and opts.signs.severity then - diagnostics = filter_by_severity(opts.signs.severity, diagnostics) - end - - local ns = get_namespace(namespace) + if opts.signs and opts.signs.severity then + diagnostics = filter_by_severity(opts.signs.severity, diagnostics) + end - define_default_signs() + define_default_signs() - -- 10 is the default sign priority when none is explicitly specified - local priority = opts.signs and opts.signs.priority or 10 - local get_priority - if opts.severity_sort then - if type(opts.severity_sort) == "table" and opts.severity_sort.reverse then - get_priority = function(severity) - return priority + (severity - vim.diagnostic.severity.ERROR) + -- 10 is the default sign priority when none is explicitly specified + local priority = opts.signs and opts.signs.priority or 10 + local get_priority + if opts.severity_sort then + if type(opts.severity_sort) == "table" and opts.severity_sort.reverse then + get_priority = function(severity) + return priority + (severity - vim.diagnostic.severity.ERROR) + end + else + get_priority = function(severity) + return priority + (vim.diagnostic.severity.HINT - severity) + end end else - get_priority = function(severity) - return priority + (vim.diagnostic.severity.HINT - severity) + get_priority = function() + return priority end end - else - get_priority = function() - return priority - end - end - - for _, diagnostic in ipairs(diagnostics) do - vim.fn.sign_place( - 0, - ns.sign_group, - sign_highlight_map[diagnostic.severity], - bufnr, - { - priority = get_priority(diagnostic.severity), - lnum = diagnostic.lnum + 1 - } - ) - end -end ---- Set underline for given diagnostics. ---- ----@param namespace number The diagnostic namespace ----@param bufnr number Buffer number ----@param diagnostics table A list of diagnostic items |diagnostic-structure|. When omitted the ---- current diagnostics in the given buffer are used. ----@param opts table Configuration table. Currently unused. ----@private -function M._set_underline(namespace, bufnr, diagnostics, opts) - vim.validate { - namespace = {namespace, 'n'}, - bufnr = {bufnr, 'n'}, - diagnostics = {diagnostics, 't'}, - opts = {opts, 't', true}, - } + local ns = M.get_namespace(namespace) + if not ns.user_data.sign_group then + ns.user_data.sign_group = string.format("vim.diagnostic.%s", ns.name) + end - bufnr = get_bufnr(bufnr) - opts = get_resolved_options({ underline = opts }, namespace, bufnr).underline + local sign_group = ns.user_data.sign_group + for _, diagnostic in ipairs(diagnostics) do + vim.fn.sign_place( + 0, + sign_group, + sign_highlight_map[diagnostic.severity], + bufnr, + { + priority = get_priority(diagnostic.severity), + lnum = diagnostic.lnum + 1 + } + ) + end + end, + hide = function(namespace, bufnr) + local ns = M.get_namespace(namespace) + if ns.user_data.sign_group then + vim.fn.sign_unplace(ns.user_data.sign_group, {buffer=bufnr}) + end + end, +} - if opts and opts.severity then - diagnostics = filter_by_severity(opts.severity, diagnostics) - end +M.handlers.underline = { + show = function(namespace, bufnr, diagnostics, opts) + vim.validate { + namespace = {namespace, 'n'}, + bufnr = {bufnr, 'n'}, + diagnostics = {diagnostics, 't'}, + opts = {opts, 't', true}, + } - for _, diagnostic in ipairs(diagnostics) do - local higroup = underline_highlight_map[diagnostic.severity] + bufnr = get_bufnr(bufnr) - if higroup == nil then - -- Default to error if we don't have a highlight associated - higroup = underline_highlight_map.Error + if opts.underline and opts.underline.severity then + diagnostics = filter_by_severity(opts.underline.severity, diagnostics) end - vim.highlight.range( - bufnr, - namespace, - higroup, - { diagnostic.lnum, diagnostic.col }, - { diagnostic.end_lnum, diagnostic.end_col } - ) - end -end + local ns = M.get_namespace(namespace) + if not ns.user_data.underline_ns then + ns.user_data.underline_ns = vim.api.nvim_create_namespace("") + end ---- Set virtual text for given diagnostics. ---- ----@param namespace number The diagnostic namespace ----@param bufnr number Buffer number ----@param diagnostics table A list of diagnostic items |diagnostic-structure|. When omitted the ---- current diagnostics in the given buffer are used. ----@param opts table|nil Configuration table with the following keys: ---- - prefix: (string) Prefix to display before virtual text on line. ---- - spacing: (number) Number of spaces to insert before virtual text. ---- - source: (string) Include the diagnostic source in virtual text. One of "always" or ---- "if_many". ----@private -function M._set_virtual_text(namespace, bufnr, diagnostics, opts) - vim.validate { - namespace = {namespace, 'n'}, - bufnr = {bufnr, 'n'}, - diagnostics = {diagnostics, 't'}, - opts = {opts, 't', true}, - } + local underline_ns = ns.user_data.underline_ns + for _, diagnostic in ipairs(diagnostics) do + local higroup = underline_highlight_map[diagnostic.severity] - bufnr = get_bufnr(bufnr) - opts = get_resolved_options({ virtual_text = opts }, namespace, bufnr).virtual_text + if higroup == nil then + -- Default to error if we don't have a highlight associated + higroup = underline_highlight_map.Error + end - if opts and opts.format then - diagnostics = reformat_diagnostics(opts.format, diagnostics) + vim.highlight.range( + bufnr, + underline_ns, + higroup, + { diagnostic.lnum, diagnostic.col }, + { diagnostic.end_lnum, diagnostic.end_col } + ) + end + save_extmarks(underline_ns, bufnr) + end, + hide = function(namespace, bufnr) + local ns = M.get_namespace(namespace) + if ns.user_data.underline_ns then + diagnostic_cache_extmarks[bufnr][ns.user_data.underline_ns] = {} + vim.api.nvim_buf_clear_namespace(bufnr, ns.user_data.underline_ns, 0, -1) + end end +} - if opts and opts.source then - diagnostics = prefix_source(opts.source, diagnostics) - end +M.handlers.virtual_text = { + show = function(namespace, bufnr, diagnostics, opts) + vim.validate { + namespace = {namespace, 'n'}, + bufnr = {bufnr, 'n'}, + diagnostics = {diagnostics, 't'}, + opts = {opts, 't', true}, + } - local buffer_line_diagnostics = diagnostic_lines(diagnostics) - for line, line_diagnostics in pairs(buffer_line_diagnostics) do - if opts and opts.severity then - line_diagnostics = filter_by_severity(opts.severity, line_diagnostics) + bufnr = get_bufnr(bufnr) + + local severity + if opts.virtual_text then + if opts.virtual_text.format then + diagnostics = reformat_diagnostics(opts.virtual_text.format, diagnostics) + end + if opts.virtual_text.source then + diagnostics = prefix_source(opts.virtual_text.source, diagnostics) + end + if opts.virtual_text.severity then + severity = opts.virtual_text.severity + end end - local virt_texts = M._get_virt_text_chunks(line_diagnostics, opts) - if virt_texts then - vim.api.nvim_buf_set_extmark(bufnr, namespace, line, 0, { - hl_mode = "combine", - virt_text = virt_texts, - }) + local ns = M.get_namespace(namespace) + if not ns.user_data.virt_text_ns then + ns.user_data.virt_text_ns = vim.api.nvim_create_namespace("") end - end -end + + local virt_text_ns = ns.user_data.virt_text_ns + local buffer_line_diagnostics = diagnostic_lines(diagnostics) + for line, line_diagnostics in pairs(buffer_line_diagnostics) do + if severity then + line_diagnostics = filter_by_severity(severity, line_diagnostics) + end + local virt_texts = M._get_virt_text_chunks(line_diagnostics, opts.virtual_text) + + if virt_texts then + vim.api.nvim_buf_set_extmark(bufnr, virt_text_ns, line, 0, { + hl_mode = "combine", + virt_text = virt_texts, + }) + end + end + save_extmarks(virt_text_ns, bufnr) + end, + hide = function(namespace, bufnr) + local ns = M.get_namespace(namespace) + if ns.user_data.virt_text_ns then + diagnostic_cache_extmarks[bufnr][ns.user_data.virt_text_ns] = {} + vim.api.nvim_buf_clear_namespace(bufnr, ns.user_data.virt_text_ns, 0, -1) + end + end, +} --- Get virtual text chunks to display using |nvim_buf_set_extmark()|. --- @@ -1055,46 +1037,54 @@ end --- To hide diagnostics and prevent them from re-displaying, use --- |vim.diagnostic.disable()|. --- ----@param namespace number The diagnostic namespace +---@param namespace number|nil Diagnostic namespace. When omitted, hide +--- diagnostics from all namespaces. ---@param bufnr number|nil Buffer number. Defaults to the current buffer. function M.hide(namespace, bufnr) vim.validate { - namespace = { namespace, 'n' }, + namespace = { namespace, 'n', true }, bufnr = { bufnr, 'n', true }, } bufnr = get_bufnr(bufnr) - diagnostic_cache_extmarks[bufnr][namespace] = {} - - local ns = get_namespace(namespace) - - -- clear sign group - vim.fn.sign_unplace(ns.sign_group, {buffer=bufnr}) - - -- clear virtual text namespace - vim.api.nvim_buf_clear_namespace(bufnr, namespace, 0, -1) + local namespaces = namespace and {namespace} or vim.tbl_keys(diagnostic_cache[bufnr]) + for _, iter_namespace in ipairs(namespaces) do + for _, handler in pairs(M.handlers) do + if handler.hide then + handler.hide(iter_namespace, bufnr) + end + end + end end - --- Display diagnostics for the given namespace and buffer. --- ----@param namespace number Diagnostic namespace +---@param namespace number|nil Diagnostic namespace. When omitted, show +--- diagnostics from all namespaces. ---@param bufnr number|nil Buffer number. Defaults to the current buffer. ---@param diagnostics table|nil The diagnostics to display. When omitted, use the --- saved diagnostics for the given namespace and --- buffer. This can be used to display a list of diagnostics --- without saving them or to display only a subset of ---- diagnostics. +--- diagnostics. May not be used when {namespace} is nil. ---@param opts table|nil Display options. See |vim.diagnostic.config()|. function M.show(namespace, bufnr, diagnostics, opts) vim.validate { - namespace = { namespace, 'n' }, + namespace = { namespace, 'n', true }, bufnr = { bufnr, 'n', true }, diagnostics = { diagnostics, 't', true }, opts = { opts, 't', true }, } bufnr = get_bufnr(bufnr) + if not namespace then + assert(not diagnostics, "Cannot show diagnostics without a namespace") + for iter_namespace in pairs(diagnostic_cache[bufnr]) do + M.show(iter_namespace, bufnr, nil, opts) + end + return + end + if is_disabled(namespace, bufnr) then return end @@ -1129,83 +1119,154 @@ function M.show(namespace, bufnr, diagnostics, opts) clamp_line_numbers(bufnr, diagnostics) - if opts.underline then - M._set_underline(namespace, bufnr, diagnostics, opts.underline) - end - - if opts.virtual_text then - M._set_virtual_text(namespace, bufnr, diagnostics, opts.virtual_text) - end - - if opts.signs then - M._set_signs(namespace, bufnr, diagnostics, opts.signs) + for handler_name, handler in pairs(M.handlers) do + if handler.show and opts[handler_name] then + handler.show(namespace, bufnr, diagnostics, opts) + end end - - save_extmarks(namespace, bufnr) end ---- Open a floating window with the diagnostics at the given position. +--- Show diagnostics in a floating window. --- +---@param bufnr number|nil Buffer number. Defaults to the current buffer. ---@param opts table|nil Configuration table with the same keys as --- |vim.lsp.util.open_floating_preview()| in addition to the following: --- - namespace: (number) Limit diagnostics to the given namespace ---- - severity: See |diagnostic-severity|. ---- - show_header: (boolean, default true) Show "Diagnostics:" header ---- - source: (string) Include the diagnostic source in ---- the message. One of "always" or "if_many". +--- - scope: (string, default "buffer") Show diagnostics from the whole buffer ("buffer"), +--- the current cursor line ("line"), or the current cursor position ("cursor"). +--- - pos: (number or table) If {scope} is "line" or "cursor", use this position rather +--- than the cursor position. If a number, interpreted as a line number; +--- otherwise, a (row, col) tuple. +--- - severity_sort: (default false) Sort diagnostics by severity. Overrides the setting +--- from |vim.diagnostic.config()|. +--- - severity: See |diagnostic-severity|. Overrides the setting from +--- |vim.diagnostic.config()|. +--- - show_header: (boolean, default true) Show "Diagnostics:" header. Overrides the +--- setting from |vim.diagnostic.config()|. +--- - source: (string) Include the diagnostic source in the message. One of "always" or +--- "if_many". Overrides the setting from |vim.diagnostic.config()|. --- - format: (function) A function that takes a diagnostic as input and returns a --- string. The return value is the text used to display the diagnostic. ----@param bufnr number|nil Buffer number. Defaults to the current buffer. ----@param position table|nil The (0,0)-indexed position. Defaults to the current cursor position. ----@return tuple ({popup_bufnr}, {win_id}) -function M.show_position_diagnostics(opts, bufnr, position) +--- Overrides the setting from |vim.diagnostic.config()|. +--- - prefix: (function or string) Prefix each diagnostic in the floating window. +--- Overrides the setting from |vim.diagnostic.config()|. +---@return tuple ({float_bufnr}, {win_id}) +function M.open_float(bufnr, opts) vim.validate { - opts = { opts, 't', true }, bufnr = { bufnr, 'n', true }, - position = { position, 't', true }, + opts = { opts, 't', true }, } opts = opts or {} - - opts.focus_id = "position_diagnostics" bufnr = get_bufnr(bufnr) - if not position then - local curr_position = vim.api.nvim_win_get_cursor(0) - curr_position[1] = curr_position[1] - 1 - position = curr_position + local scope = opts.scope or "buffer" + local lnum, col + if scope == "line" or scope == "cursor" then + if not opts.pos then + local pos = vim.api.nvim_win_get_cursor(0) + lnum = pos[1] - 1 + col = pos[2] + elseif type(opts.pos) == "number" then + lnum = opts.pos + elseif type(opts.pos) == "table" then + lnum, col = unpack(opts.pos) + else + error("Invalid value for option 'pos'") + end + elseif scope ~= "buffer" then + error("Invalid value for option 'scope'") end - local match_position_predicate = function(diag) - return position[1] == diag.lnum and - position[2] >= diag.col and - (position[2] <= diag.end_col or position[1] < diag.end_lnum) + + do + -- Resolve options with user settings from vim.diagnostic.config + -- Unlike the other decoration functions (e.g. set_virtual_text, set_signs, etc.) `open_float` + -- does not have a dedicated table for configuration options; instead, the options are mixed in + -- with its `opts` table which also includes "keyword" parameters. So we create a dedicated + -- options table that inherits missing keys from the global configuration before resolving. + local t = global_diagnostic_options.float + local float_opts = vim.tbl_extend("keep", opts, type(t) == "table" and t or {}) + opts = get_resolved_options({ float = float_opts }, nil, bufnr).float end + local diagnostics = M.get(bufnr, opts) clamp_line_numbers(bufnr, diagnostics) - local position_diagnostics = vim.tbl_filter(match_position_predicate, diagnostics) - return show_diagnostics(opts, position_diagnostics) -end ---- Open a floating window with the diagnostics from the given line. ---- ----@param opts table Configuration table. See |vim.diagnostic.show_position_diagnostics()|. ----@param bufnr number|nil Buffer number. Defaults to the current buffer. ----@param lnum number|nil Line number. Defaults to line number of cursor. ----@return tuple ({popup_bufnr}, {win_id}) -function M.show_line_diagnostics(opts, bufnr, lnum) - vim.validate { - opts = { opts, 't', true }, - bufnr = { bufnr, 'n', true }, - lnum = { lnum, 'n', true }, - } + if scope == "line" then + diagnostics = vim.tbl_filter(function(d) + return d.lnum == lnum + end, diagnostics) + elseif scope == "cursor" then + -- LSP servers can send diagnostics with `end_col` past the length of the line + local line_length = #vim.api.nvim_buf_get_lines(bufnr, lnum, lnum + 1, true)[1] + diagnostics = vim.tbl_filter(function(d) + return d.lnum == lnum + and math.min(d.col, line_length - 1) <= col + and (d.end_col >= col or d.end_lnum > lnum) + end, diagnostics) + end - opts = opts or {} - opts.focus_id = "line_diagnostics" - bufnr = get_bufnr(bufnr) - local diagnostics = M.get(bufnr, opts) - clamp_line_numbers(bufnr, diagnostics) - lnum = lnum or (vim.api.nvim_win_get_cursor(0)[1] - 1) - local line_diagnostics = diagnostic_lines(diagnostics)[lnum] - return show_diagnostics(opts, line_diagnostics) + if vim.tbl_isempty(diagnostics) then + return + end + + local severity_sort = vim.F.if_nil(opts.severity_sort, global_diagnostic_options.severity_sort) + if severity_sort then + if type(severity_sort) == "table" and severity_sort.reverse then + table.sort(diagnostics, function(a, b) return a.severity > b.severity end) + else + table.sort(diagnostics, function(a, b) return a.severity < b.severity end) + end + end + + local lines = {} + local highlights = {} + local show_header = vim.F.if_nil(opts.show_header, true) + if show_header then + table.insert(lines, "Diagnostics:") + table.insert(highlights, {0, "Bold"}) + end + + if opts.format then + diagnostics = reformat_diagnostics(opts.format, diagnostics) + end + + if opts.source then + diagnostics = prefix_source(opts.source, diagnostics) + end + + local prefix_opt = if_nil(opts.prefix, (scope == "cursor" and #diagnostics <= 1) and "" or function(_, i) + return string.format("%d. ", i) + end) + if prefix_opt then + vim.validate { prefix = { prefix_opt, function(v) + return type(v) == "string" or type(v) == "function" + end, "'string' or 'function'" } } + end + + for i, diagnostic in ipairs(diagnostics) do + local prefix = type(prefix_opt) == "string" and prefix_opt or prefix_opt(diagnostic, i, #diagnostics) + local hiname = floating_highlight_map[diagnostic.severity] + local message_lines = vim.split(diagnostic.message, '\n') + table.insert(lines, prefix..message_lines[1]) + table.insert(highlights, {#prefix, hiname}) + for j = 2, #message_lines do + table.insert(lines, string.rep(' ', #prefix) .. message_lines[j]) + table.insert(highlights, {0, hiname}) + end + end + + -- Used by open_floating_preview to allow the float to be focused + if not opts.focus_id then + opts.focus_id = scope + end + local float_bufnr, winnr = require('vim.lsp.util').open_floating_preview(lines, 'plaintext', opts) + for i, hi in ipairs(highlights) do + local prefixlen, hiname = unpack(hi) + -- Start highlight after the prefix + vim.api.nvim_buf_add_highlight(float_bufnr, -1, hiname, i-1, prefixlen, -1) + end + + return float_bufnr, winnr end --- Remove all diagnostics from the given namespace. @@ -1215,19 +1276,23 @@ end --- simply remove diagnostic decorations in a way that they can be --- re-displayed, use |vim.diagnostic.hide()|. --- ----@param namespace number +---@param namespace number|nil Diagnostic namespace. When omitted, remove +--- diagnostics from all namespaces. ---@param bufnr number|nil Remove diagnostics for the given buffer. When omitted, --- diagnostics are removed for all buffers. function M.reset(namespace, bufnr) - if bufnr == nil then - for iter_bufnr, namespaces in pairs(diagnostic_cache) do - if namespaces[namespace] then - M.reset(namespace, iter_bufnr) - end + vim.validate { + namespace = {namespace, 'n', true}, + bufnr = {bufnr, 'n', true}, + } + + local buffers = bufnr and {bufnr} or vim.tbl_keys(diagnostic_cache) + for _, iter_bufnr in ipairs(buffers) do + local namespaces = namespace and {namespace} or vim.tbl_keys(diagnostic_cache[iter_bufnr]) + for _, iter_namespace in ipairs(namespaces) do + clear_diagnostic_cache(iter_namespace, iter_bufnr) + M.hide(iter_namespace, iter_bufnr) end - else - clear_diagnostic_cache(namespace, bufnr) - M.hide(namespace, bufnr) end vim.api.nvim_command("doautocmd <nomodeline> User DiagnosticsChanged") diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 9c35351608..0fc0a7a7aa 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -5,6 +5,7 @@ local log = require 'vim.lsp.log' local lsp_rpc = require 'vim.lsp.rpc' local protocol = require 'vim.lsp.protocol' local util = require 'vim.lsp.util' +local sync = require 'vim.lsp.sync' local vim = vim local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_buf_get_option @@ -108,6 +109,12 @@ local valid_encodings = { UTF8 = 'utf-8'; UTF16 = 'utf-16'; UTF32 = 'utf-32'; } +local format_line_ending = { + ["unix"] = '\n', + ["dos"] = '\r\n', + ["mac"] = '\r', +} + local client_index = 0 ---@private --- Returns a new, unused client id. @@ -122,9 +129,6 @@ local active_clients = {} local all_buffer_active_clients = {} local uninitialized_clients = {} --- Tracks all buffers attached to a client. -local all_client_active_buffers = {} - ---@private --- Invokes a function for each LSP client attached to the buffer {bufnr}. --- @@ -242,6 +246,7 @@ local function validate_client_config(config) on_exit = { config.on_exit, "f", true }; on_init = { config.on_init, "f", true }; settings = { config.settings, "t", true }; + commands = { config.commands, 't', true }; before_init = { config.before_init, "f", true }; offset_encoding = { config.offset_encoding, "s", true }; flags = { config.flags, "t", true }; @@ -353,15 +358,14 @@ do end end - function changetracking.prepare(bufnr, firstline, new_lastline, changedtick) + function changetracking.prepare(bufnr, firstline, lastline, new_lastline, changedtick) local incremental_changes = function(client) local cached_buffers = state_by_client[client.id].buffers - local lines = nvim_buf_get_lines(bufnr, 0, -1, true) - local startline = math.min(firstline + 1, math.min(#cached_buffers[bufnr], #lines)) - local endline = math.min(-(#lines - new_lastline), -1) - local incremental_change = vim.lsp.util.compute_diff( - cached_buffers[bufnr], lines, startline, endline, client.offset_encoding or 'utf-16') - cached_buffers[bufnr] = lines + local curr_lines = nvim_buf_get_lines(bufnr, 0, -1, true) + local line_ending = format_line_ending[vim.api.nvim_buf_get_option(0, 'fileformat')] + local incremental_change = sync.compute_diff( + cached_buffers[bufnr], curr_lines, firstline, lastline, new_lastline, client.offset_encoding or 'utf-16', line_ending or '\n') + cached_buffers[bufnr] = curr_lines return incremental_change end local full_changes = once(function() @@ -468,7 +472,11 @@ local function text_document_did_open_handler(bufnr, client) -- Next chance we get, we should re-do the diagnostics vim.schedule(function() - vim.lsp.diagnostic.redraw(bufnr, client.id) + -- Protect against a race where the buffer disappears + -- between `did_open_handler` and the scheduled function firing. + if vim.api.nvim_buf_is_valid(bufnr) then + vim.lsp.diagnostic.redraw(bufnr, client.id) + end end) end @@ -593,6 +601,11 @@ end --- returned to the language server if requested via `workspace/configuration`. --- Keys are case-sensitive. --- +---@param commands table Table that maps string of clientside commands to user-defined functions. +--- Commands passed to start_client take precedence over the global command registry. Each key +--- must be a unique comand name, and the value is a function which is called if any LSP action +--- (code action, code lenses, ...) triggers the command. +--- ---@param init_options Values to pass in the initialization request --- as `initializationOptions`. See `initialize` in the LSP spec. --- @@ -647,7 +660,9 @@ end --- - debounce_text_changes (number, default nil): Debounce didChange --- notifications to the server by the given number in milliseconds. No debounce --- occurs if nil ---- +--- - exit_timeout (number, default 500): Milliseconds to wait for server to +-- exit cleanly after sending the 'shutdown' request before sending kill -15. +-- If set to false, nvim exits immediately after sending the 'shutdown' request to the server. ---@returns Client id. |vim.lsp.get_client_by_id()| Note: client may not be --- fully initialized. Use `on_init` to do any actions once --- the client has been initialized. @@ -742,7 +757,6 @@ function lsp.start_client(config) lsp.diagnostic.reset(client_id, all_buffer_active_clients) changetracking.reset(client_id) - all_client_active_buffers[client_id] = nil for _, client_ids in pairs(all_buffer_active_clients) do client_ids[client_id] = nil end @@ -771,10 +785,14 @@ function lsp.start_client(config) rpc = rpc; offset_encoding = offset_encoding; config = config; + attached_buffers = {}; handlers = handlers; + commands = config.commands or {}; + + requests = {}; -- for $/progress report - messages = { name = name, messages = {}, progress = {}, status = {} } + messages = { name = name, messages = {}, progress = {}, status = {} }; } -- Store the uninitialized_clients for cleanup in case we exit before initialize finishes. @@ -907,11 +925,21 @@ function lsp.start_client(config) end -- Ensure pending didChange notifications are sent so that the server doesn't operate on a stale state changetracking.flush(client) - + bufnr = resolve_bufnr(bufnr) local _ = log.debug() and log.debug(log_prefix, "client.request", client_id, method, params, handler, bufnr) - return rpc.request(method, params, function(err, result) + local success, request_id = rpc.request(method, params, function(err, result) handler(err, result, {method=method, client_id=client_id, bufnr=bufnr, params=params}) + end, function(request_id) + client.requests[request_id] = nil + nvim_command("doautocmd <nomodeline> User LspRequest") end) + + if success then + client.requests[request_id] = { type='pending', bufnr=bufnr, method=method } + nvim_command("doautocmd <nomodeline> User LspRequest") + end + + return success, request_id end ---@private @@ -971,6 +999,11 @@ function lsp.start_client(config) ---@see |vim.lsp.client.notify()| function client.cancel_request(id) validate{id = {id, 'n'}} + local request = client.requests[id] + if request and request.type == 'pending' then + request.type = 'cancel' + nvim_command("doautocmd <nomodeline> User LspRequest") + end return rpc.notify("$/cancelRequest", { id = id }) end @@ -989,7 +1022,6 @@ function lsp.start_client(config) lsp.diagnostic.reset(client_id, all_buffer_active_clients) changetracking.reset(client_id) - all_client_active_buffers[client_id] = nil for _, client_ids in pairs(all_buffer_active_clients) do client_ids[client_id] = nil end @@ -1032,6 +1064,7 @@ function lsp.start_client(config) -- TODO(ashkan) handle errors. pcall(config.on_attach, client, bufnr) end + client.attached_buffers[bufnr] = true end initialize() @@ -1044,22 +1077,14 @@ end --- Notify all attached clients that a buffer has changed. local text_document_did_change_handler do - text_document_did_change_handler = function(_, bufnr, changedtick, - firstline, lastline, new_lastline, old_byte_size, old_utf32_size, - old_utf16_size) - - local _ = log.debug() and log.debug( - string.format("on_lines bufnr: %s, changedtick: %s, firstline: %s, lastline: %s, new_lastline: %s, old_byte_size: %s, old_utf32_size: %s, old_utf16_size: %s", - bufnr, changedtick, firstline, lastline, new_lastline, old_byte_size, old_utf32_size, old_utf16_size), - nvim_buf_get_lines(bufnr, firstline, new_lastline, true) - ) + text_document_did_change_handler = function(_, bufnr, changedtick, firstline, lastline, new_lastline) -- Don't do anything if there are no clients attached. if tbl_isempty(all_buffer_active_clients[bufnr] or {}) then return end util.buf_versions[bufnr] = changedtick - local compute_change_and_notify = changetracking.prepare(bufnr, firstline, new_lastline, changedtick) + local compute_change_and_notify = changetracking.prepare(bufnr, firstline, lastline, new_lastline, changedtick) for_each_buffer_client(bufnr, compute_change_and_notify) end end @@ -1142,12 +1167,6 @@ function lsp.buf_attach_client(bufnr, client_id) }) end - if not all_client_active_buffers[client_id] then - all_client_active_buffers[client_id] = {} - end - - table.insert(all_client_active_buffers[client_id], bufnr) - if buffer_client_ids[client_id] then return end -- This is our first time attaching this client to this buffer. buffer_client_ids[client_id] = true @@ -1172,7 +1191,7 @@ end --- Gets a client by id, or nil if the id is invalid. --- The returned client may not yet be fully initialized. -- ----@param client_id client id number +---@param client_id number client id --- ---@returns |vim.lsp.client| object, or nil function lsp.get_client_by_id(client_id) @@ -1181,15 +1200,11 @@ end --- Returns list of buffers attached to client_id. -- ----@param client_id client id +---@param client_id number client id ---@returns list of buffer ids function lsp.get_buffers_by_client_id(client_id) - local active_client_buffers = all_client_active_buffers[client_id] - if active_client_buffers then - return active_client_buffers - else - return {} - end + local client = lsp.get_client_by_id(client_id) + return client and vim.tbl_keys(client.attached_buffers) or {} end --- Stops a client(s). @@ -1239,9 +1254,41 @@ function lsp._vim_exit_handler() client.stop() end - if not vim.wait(500, function() return tbl_isempty(active_clients) end, 50) then - for _, client in pairs(active_clients) do - client.stop(true) + local timeouts = {} + local max_timeout = 0 + local send_kill = false + + for client_id, client in pairs(active_clients) do + local timeout = if_nil(client.config.flags.exit_timeout, 500) + if timeout then + send_kill = true + timeouts[client_id] = timeout + max_timeout = math.max(timeout, max_timeout) + end + end + + local poll_time = 50 + + local function check_clients_closed() + for client_id, timeout in pairs(timeouts) do + timeouts[client_id] = timeout - poll_time + end + + for client_id, _ in pairs(active_clients) do + if timeouts[client_id] ~= nil and timeouts[client_id] > 0 then + return false + end + end + return true + end + + if send_kill then + if not vim.wait(max_timeout, check_clients_closed, poll_time) then + for client_id, client in pairs(active_clients) do + if timeouts[client_id] ~= nil then + client.stop(true) + end + end end end end @@ -1282,7 +1329,7 @@ function lsp.buf_request(bufnr, method, params, handler) if not tbl_isempty(all_buffer_active_clients[resolve_bufnr(bufnr)] or {}) and not method_supported then vim.notify(lsp._unsupported_method(method), vim.log.levels.ERROR) vim.api.nvim_command("redraw") - return + return {}, function() end end local client_request_ids = {} @@ -1430,7 +1477,7 @@ end ---@param findstart 0 or 1, decides behavior ---@param base If findstart=0, text to match against --- ----@returns (number) Decided by `findstart`: +---@returns (number) Decided by {findstart}: --- - findstart=0: column where the completion starts, or -2 or -3 --- - findstart=1: list of matches (actually just calls |complete()|) function lsp.omnifunc(findstart, base) @@ -1494,6 +1541,52 @@ function lsp.omnifunc(findstart, base) return -2 end +--- Provides an interface between the built-in client and a `formatexpr` function. +--- +--- Currently only supports a single client. This can be set via +--- `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` but will typically or in `on_attach` +--- via `vim.api.nvim_buf_set_option(bufnr, 'formatexpr', 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})')`. +--- +---@param opts table options for customizing the formatting expression which takes the +--- following optional keys: +--- * timeout_ms (default 500ms). The timeout period for the formatting request. +function lsp.formatexpr(opts) + opts = opts or {} + local timeout_ms = opts.timeout_ms or 500 + + if vim.tbl_contains({'i', 'R', 'ic', 'ix'}, vim.fn.mode()) then + -- `formatexpr` is also called when exceeding `textwidth` in insert mode + -- fall back to internal formatting + return 1 + end + + local start_line = vim.v.lnum + local end_line = start_line + vim.v.count - 1 + + if start_line > 0 and end_line > 0 then + local params = { + textDocument = util.make_text_document_params(); + range = { + start = { line = start_line - 1; character = 0; }; + ["end"] = { line = end_line - 1; character = 0; }; + }; + }; + params.options = util.make_formatting_params().options + local client_results = vim.lsp.buf_request_sync(0, "textDocument/rangeFormatting", params, timeout_ms) + + -- Apply the text edits from one and only one of the clients. + for _, response in pairs(client_results) do + if response.result then + vim.lsp.util.apply_text_edits(response.result, 0) + return 0 + end + end + end + + -- do not run builtin formatter. + return 0 +end + ---Checks whether a client is stopped. --- ---@param client_id (Number) diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 245f29943e..747d761730 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -247,22 +247,35 @@ end --- Renames all references to the symbol under the cursor. --- ---@param new_name (string) If not provided, the user will be prompted for a new ----name using |input()|. +---name using |vim.ui.input()|. function M.rename(new_name) - local params = util.make_position_params() + local opts = { + prompt = "New Name: " + } + + ---@private + local function on_confirm(input) + if not (input and #input > 0) then return end + local params = util.make_position_params() + params.newName = input + request('textDocument/rename', params) + end + local function prepare_rename(err, result) if err == nil and result == nil then vim.notify('nothing to rename', vim.log.levels.INFO) return end if result and result.placeholder then - new_name = new_name or npcall(vfn.input, "New Name: ", result.placeholder) + opts.default = result.placeholder + if not new_name then npcall(vim.ui.input, opts, on_confirm) end elseif result and result.start and result['end'] and result.start.line == result['end'].line then local line = vfn.getline(result.start.line+1) local start_char = result.start.character+1 local end_char = result['end'].character - new_name = new_name or npcall(vfn.input, "New Name: ", string.sub(line, start_char, end_char)) + opts.default = string.sub(line, start_char, end_char) + if not new_name then npcall(vim.ui.input, opts, on_confirm) end else -- fallback to guessing symbol using <cword> -- @@ -270,13 +283,12 @@ function M.rename(new_name) -- returns an unexpected response, or requests for "default behavior" -- -- see https://microsoft.github.io/language-server-protocol/specification#textDocument_prepareRename - new_name = new_name or npcall(vfn.input, "New Name: ", vfn.expand('<cword>')) + opts.default = vfn.expand('<cword>') + if not new_name then npcall(vim.ui.input, opts, on_confirm) end end - if not (new_name and #new_name > 0) then return end - params.newName = new_name - request('textDocument/rename', params) + if new_name then on_confirm(new_name) end end - request('textDocument/prepareRename', params, prepare_rename) + request('textDocument/prepareRename', util.make_position_params(), prepare_rename) end --- Lists all the references to the symbol under the cursor in the quickfix window. @@ -357,7 +369,7 @@ end function M.list_workspace_folders() local workspace_folders = {} for _, client in pairs(vim.lsp.buf_get_clients()) do - for _, folder in pairs(client.workspaceFolders) do + for _, folder in pairs(client.workspaceFolders or {}) do table.insert(workspace_folders, folder.name) end end @@ -377,7 +389,7 @@ function M.add_workspace_folder(workspace_folder) local params = util.make_workspace_params({{uri = vim.uri_from_fname(workspace_folder); name = workspace_folder}}, {{}}) for _, client in pairs(vim.lsp.buf_get_clients()) do local found = false - for _, folder in pairs(client.workspaceFolders) do + for _, folder in pairs(client.workspaceFolders or {}) do if folder.name == workspace_folder then found = true print(workspace_folder, "is already part of this workspace") @@ -386,6 +398,9 @@ function M.add_workspace_folder(workspace_folder) end if not found then vim.lsp.buf_notify(0, 'workspace/didChangeWorkspaceFolders', params) + if not client.workspaceFolders then + client.workspaceFolders = {} + end table.insert(client.workspaceFolders, params.event.added[1]) end end @@ -480,11 +495,11 @@ local function on_code_action_results(results, ctx) end if action.command then local command = type(action.command) == 'table' and action.command or action - local fn = vim.lsp.commands[command.command] + local fn = client.commands[command.command] or vim.lsp.commands[command.command] if fn then local enriched_ctx = vim.deepcopy(ctx) enriched_ctx.client_id = client.id - fn(command, ctx) + fn(command, enriched_ctx) else M.execute_command(command) end @@ -529,6 +544,7 @@ local function on_code_action_results(results, ctx) vim.ui.select(action_tuples, { prompt = 'Code actions:', + kind = 'codeaction', format_item = function(action_tuple) local title = action_tuple[2].title:gsub('\r\n', '\\r\\n') return title:gsub('\n', '\\n') diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index 63fcbe430b..9eb64c9a2e 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -31,15 +31,15 @@ local function execute_lens(lens, bufnr, client_id) local line = lens.range.start.line api.nvim_buf_clear_namespace(bufnr, namespaces[client_id], line, line + 1) + local client = vim.lsp.get_client_by_id(client_id) + assert(client, 'Client is required to execute lens, client_id=' .. client_id) local command = lens.command - local fn = vim.lsp.commands[command.command] + local fn = client.commands[command.command] or vim.lsp.commands[command.command] if fn then fn(command, { bufnr = bufnr, client_id = client_id }) return end -- Need to use the client that returned the lens → must not use buf_request - local client = vim.lsp.get_client_by_id(client_id) - assert(client, 'Client is required to execute lens, client_id=' .. client_id) local command_provider = client.server_capabilities.executeCommandProvider local commands = type(command_provider) == 'table' and command_provider.commands or {} if not vim.tbl_contains(commands, command.command) then diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index 0e63c0dd29..1e6f83c1ba 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -146,7 +146,8 @@ local _client_namespaces = {} function M.get_namespace(client_id) vim.validate { client_id = { client_id, 'n' } } if not _client_namespaces[client_id] then - local name = string.format("vim.lsp.client-%d", client_id) + local client = vim.lsp.get_client_by_id(client_id) + local name = string.format("vim.lsp.%s.%d", client and client.name or "unknown", client_id) _client_namespaces[client_id] = vim.api.nvim_create_namespace(name) end return _client_namespaces[client_id] @@ -551,14 +552,15 @@ end ---@param position table|nil The (0,0)-indexed position ---@return table {popup_bufnr, win_id} function M.show_position_diagnostics(opts, buf_nr, position) - if opts then - if opts.severity then - opts.severity = severity_lsp_to_vim(opts.severity) - elseif opts.severity_limit then - opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)} - end + opts = opts or {} + opts.scope = "cursor" + opts.pos = position + if opts.severity then + opts.severity = severity_lsp_to_vim(opts.severity) + elseif opts.severity_limit then + opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)} end - return vim.diagnostic.show_position_diagnostics(opts, buf_nr, position) + return vim.diagnostic.open_float(buf_nr, opts) end --- Open a floating window with the diagnostics from {line_nr} @@ -573,11 +575,13 @@ end ---@param client_id number|nil the client id ---@return table {popup_bufnr, win_id} function M.show_line_diagnostics(opts, buf_nr, line_nr, client_id) + opts = opts or {} + opts.scope = "line" + opts.pos = line_nr if client_id then - opts = opts or {} opts.namespace = M.get_namespace(client_id) end - return vim.diagnostic.show_line_diagnostics(opts, buf_nr, line_nr) + return vim.diagnostic.open_float(buf_nr, opts) end --- Redraw diagnostics for the given buffer and client diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index eff27807be..a561630c2b 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -28,6 +28,7 @@ local function progress_handler(_, result, ctx, _) local client_name = client and client.name or string.format("id=%d", client_id) if not client then err_message("LSP[", client_name, "] client has shut down after sending the message") + return end local val = result.value -- unspecified yet local token = result.token -- string or number @@ -185,7 +186,7 @@ local function response_to_list(map_result, entity) title = 'Language Server'; items = map_result(result, ctx.bufnr); }) - api.nvim_command("copen") + api.nvim_command("botright copen") end end end @@ -349,7 +350,7 @@ M['textDocument/signatureHelp'] = M.signature_help --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight M['textDocument/documentHighlight'] = function(_, result, ctx, _) if not result then return end - util.buf_highlight_references(ctx.bufnr, result) + util.buf_highlight_references(ctx.bufnr, result, ctx.client_id) end ---@private diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index d9a684a738..bce1e9f35d 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -297,6 +297,7 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params) local message_index = 0 local message_callbacks = {} + local notify_reply_callbacks = {} local handle, pid do @@ -309,8 +310,9 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params) stdout:close() stderr:close() handle:close() - -- Make sure that message_callbacks can be gc'd. + -- Make sure that message_callbacks/notify_reply_callbacks can be gc'd. message_callbacks = nil + notify_reply_callbacks = nil dispatchers.on_exit(code, signal) end local spawn_params = { @@ -375,10 +377,12 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params) ---@param method (string) The invoked LSP method ---@param params (table) Parameters for the invoked LSP method ---@param callback (function) Callback to invoke + ---@param notify_reply_callback (function) Callback to invoke as soon as a request is no longer pending ---@returns (bool, number) `(true, message_id)` if request could be sent, `false` if not - local function request(method, params, callback) + local function request(method, params, callback, notify_reply_callback) validate { callback = { callback, 'f' }; + notify_reply_callback = { notify_reply_callback, 'f', true }; } message_index = message_index + 1 local message_id = message_index @@ -388,8 +392,15 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params) method = method; params = params; } - if result and message_callbacks then - message_callbacks[message_id] = schedule_wrap(callback) + if result then + if message_callbacks then + message_callbacks[message_id] = schedule_wrap(callback) + else + return false + end + if notify_reply_callback and notify_reply_callbacks then + notify_reply_callbacks[message_id] = schedule_wrap(notify_reply_callback) + end return result, message_id else return false @@ -466,6 +477,16 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params) -- We sent a number, so we expect a number. local result_id = tonumber(decoded.id) + -- Notify the user that a response was received for the request + local notify_reply_callback = notify_reply_callbacks and notify_reply_callbacks[result_id] + if notify_reply_callback then + validate { + notify_reply_callback = { notify_reply_callback, 'f' }; + } + notify_reply_callback(result_id) + notify_reply_callbacks[result_id] = nil + end + -- Do not surface RequestCancelled to users, it is RPC-internal. if decoded.error then local mute_error = false diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua new file mode 100644 index 0000000000..37247c61b9 --- /dev/null +++ b/runtime/lua/vim/lsp/sync.lua @@ -0,0 +1,381 @@ +-- Notes on incremental sync: +-- Per the protocol, the text range should be: +-- +-- A position inside a document (see Position definition below) is expressed as +-- a zero-based line and character offset. The offsets are based on a UTF-16 +-- string representation. So a string of the form a𐐀b the character offset +-- of the character a is 0, the character offset of 𐐀 is 1 and the character +-- offset of b is 3 since 𐐀 is represented using two code units in UTF-16. +-- +-- To ensure that both client and server split the string into the same line +-- representation the protocol specifies the following end-of-line sequences: ‘\n’, ‘\r\n’ and ‘\r’. +-- +-- Positions are line end character agnostic. So you can not specify a position that +-- denotes \r|\n or \n| where | represents the character offset. This means *no* defining +-- a range than ends on the same line after a terminating character +-- +-- Generic warnings about byte level changes in neovim. Many apparently "single" +-- operations in on_lines callbacks are actually multiple operations. +-- +-- Join operation (2 operations): +-- * extends line 1 with the contents of line 2 +-- * deletes line 2 +-- +-- test 1 test 1 test 2 test 1 test 2 +-- test 2 -> test 2 -> test 3 +-- test 3 test 3 +-- +-- Deleting (and undoing) two middle lines (1 operation): +-- +-- test 1 test 1 +-- test 2 -> test 4 +-- test 3 +-- test 4 +-- +-- Deleting partial lines (5 operations) deleting between asterisks below: +-- +-- test *1 test * test * test * test *4 test *4* +-- test 2 -> test 2 -> test *4 -> *4 -> *4 -> +-- test 3 test 3 +-- test *4 test 4 + +local M = {} + +-- local string.byte, unclear if this is necessary for JIT compilation +local str_byte = string.byte +local min = math.min +local str_utfindex = vim.str_utfindex +local str_utf_start = vim.str_utf_start +local str_utf_end = vim.str_utf_end + +---@private +-- Given a line, byte idx, and offset_encoding convert to the +-- utf-8, utf-16, or utf-32 index. +---@param line string the line to index into +---@param byte integer the byte idx +---@param offset_encoding string utf-8|utf-16|utf-32|nil (default: utf-8) +--@returns integer the utf idx for the given encoding +local function byte_to_utf(line, byte, offset_encoding) + -- convert to 0 based indexing for str_utfindex + byte = byte - 1 + + local utf_idx + local _ + -- Convert the byte range to utf-{8,16,32} and convert 1-based (lua) indexing to 0-based + if offset_encoding == 'utf-16' then + _, utf_idx = str_utfindex(line, byte) + elseif offset_encoding == 'utf-32' then + utf_idx, _ = str_utfindex(line, byte) + else + utf_idx = byte + end + + -- convert to 1 based indexing + return utf_idx + 1 +end + +---@private +-- Given a line, byte idx, alignment, and offset_encoding convert to the aligned +-- utf-8 index and either the utf-16, or utf-32 index. +---@param line string the line to index into +---@param byte integer the byte idx +---@param align string when dealing with multibyte characters, +-- to choose the start of the current character or the beginning of the next. +-- Used for incremental sync for start/end range respectively +---@param offset_encoding string utf-8|utf-16|utf-32|nil (default: utf-8) +---@returns table<string, int> byte_idx and char_idx of first change position +local function align_position(line, byte, align, offset_encoding) + local char + -- If on the first byte, or an empty string: the trivial case + if byte == 1 or #line == 0 then + char = byte + -- Called in the case of extending an empty line "" -> "a" + elseif byte == #line + 1 then + byte = byte + str_utf_end(line, #line) + char = byte_to_utf(line, byte, offset_encoding) + else + -- Modifying line, find the nearest utf codepoint + if align == 'start' then + byte = byte + str_utf_start(line, byte) + char = byte_to_utf(line, byte, offset_encoding) + elseif align == 'end' then + local offset = str_utf_end(line, byte) + -- If the byte does not fall on the start of the character, then + -- align to the start of the next character. + if offset > 0 then + char = byte_to_utf(line, byte, offset_encoding) + 1 + byte = byte + offset + else + char = byte_to_utf(line, byte, offset_encoding) + byte = byte + offset + end + else + error('`align` must be start or end.') + end + -- Extending line, find the nearest utf codepoint for the last valid character + end + return byte, char +end + +---@private +--- Finds the first line, byte, and char index of the difference between the previous and current lines buffer normalized to the previous codepoint. +---@param prev_lines table list of lines from previous buffer +---@param curr_lines table list of lines from current buffer +---@param firstline integer firstline from on_lines, adjusted to 1-index +---@param lastline integer lastline from on_lines, adjusted to 1-index +---@param new_lastline integer new_lastline from on_lines, adjusted to 1-index +---@param offset_encoding string utf-8|utf-16|utf-32|nil (fallback to utf-8) +---@returns table<int, int> line_idx, byte_idx, and char_idx of first change position +local function compute_start_range(prev_lines, curr_lines, firstline, lastline, new_lastline, offset_encoding) + -- If firstline == lastline, no existing text is changed. All edit operations + -- occur on a new line pointed to by lastline. This occurs during insertion of + -- new lines(O), the new newline is inserted at the line indicated by + -- new_lastline. + -- If firstline == new_lastline, the first change occured on a line that was deleted. + -- In this case, the first byte change is also at the first byte of firstline + if firstline == new_lastline or firstline == lastline then + return { line_idx = firstline, byte_idx = 1, char_idx = 1 } + end + + local prev_line = prev_lines[firstline] + local curr_line = curr_lines[firstline] + + -- Iterate across previous and current line containing first change + -- to find the first different byte. + -- Note: *about -> a*about will register the second a as the first + -- difference, regardless of edit since we do not receive the first + -- column of the edit from on_lines. + local start_byte_idx = 1 + for idx = 1, #prev_line + 1 do + start_byte_idx = idx + if str_byte(prev_line, idx) ~= str_byte(curr_line, idx) then + break + end + end + + -- Convert byte to codepoint if applicable + local byte_idx, char_idx = align_position(prev_line, start_byte_idx, 'start', offset_encoding) + + -- Return the start difference (shared for new and prev lines) + return { line_idx = firstline, byte_idx = byte_idx, char_idx = char_idx } +end + +---@private +--- Finds the last line and byte index of the differences between prev and current buffer. +--- Normalized to the next codepoint. +--- prev_end_range is the text range sent to the server representing the changed region. +--- curr_end_range is the text that should be collected and sent to the server. +-- +---@param prev_lines table list of lines +---@param curr_lines table list of lines +---@param start_range table +---@param lastline integer +---@param new_lastline integer +---@param offset_encoding string +---@returns (int, int) end_line_idx and end_col_idx of range +local function compute_end_range(prev_lines, curr_lines, start_range, firstline, lastline, new_lastline, offset_encoding) + -- If firstline == new_lastline, the first change occured on a line that was deleted. + -- In this case, the last_byte... + if firstline == new_lastline then + return { line_idx = (lastline - new_lastline + firstline), byte_idx = 1, char_idx = 1 }, { line_idx = firstline, byte_idx = 1, char_idx = 1 } + end + if firstline == lastline then + return { line_idx = firstline, byte_idx = 1, char_idx = 1 }, { line_idx = new_lastline - lastline + firstline, byte_idx = 1, char_idx = 1 } + end + -- Compare on last line, at minimum will be the start range + local start_line_idx = start_range.line_idx + + -- lastline and new_lastline were last lines that were *not* replaced, compare previous lines + local prev_line_idx = lastline - 1 + local curr_line_idx = new_lastline - 1 + + local prev_line = prev_lines[lastline - 1] + local curr_line = curr_lines[new_lastline - 1] + + local prev_line_length = #prev_line + local curr_line_length = #curr_line + + local byte_offset = 0 + + -- Editing the same line + -- If the byte offset is zero, that means there is a difference on the last byte (not newline) + if prev_line_idx == curr_line_idx then + local max_length + if start_line_idx == prev_line_idx then + -- Search until beginning of difference + max_length = min(prev_line_length - start_range.byte_idx, curr_line_length - start_range.byte_idx) + 1 + else + max_length = min(prev_line_length, curr_line_length) + 1 + end + for idx = 0, max_length do + byte_offset = idx + if + str_byte(prev_line, prev_line_length - byte_offset) ~= str_byte(curr_line, curr_line_length - byte_offset) + then + break + end + end + end + + -- Iterate from end to beginning of shortest line + local prev_end_byte_idx = prev_line_length - byte_offset + 1 + local prev_byte_idx, prev_char_idx = align_position(prev_line, prev_end_byte_idx, 'start', offset_encoding) + local prev_end_range = { line_idx = prev_line_idx, byte_idx = prev_byte_idx, char_idx = prev_char_idx } + + local curr_end_range + -- Deletion event, new_range cannot be before start + if curr_line_idx < start_line_idx then + curr_end_range = { line_idx = start_line_idx, byte_idx = 1, char_idx = 1 } + else + local curr_end_byte_idx = curr_line_length - byte_offset + 1 + local curr_byte_idx, curr_char_idx = align_position(curr_line, curr_end_byte_idx, 'start', offset_encoding) + curr_end_range = { line_idx = curr_line_idx, byte_idx = curr_byte_idx, char_idx = curr_char_idx } + end + + return prev_end_range, curr_end_range +end + +---@private +--- Get the text of the range defined by start and end line/column +---@param lines table list of lines +---@param start_range table table returned by first_difference +---@param end_range table new_end_range returned by last_difference +---@returns string text extracted from defined region +local function extract_text(lines, start_range, end_range, line_ending) + if not lines[start_range.line_idx] then + return "" + end + -- Trivial case: start and end range are the same line, directly grab changed text + if start_range.line_idx == end_range.line_idx then + -- string.sub is inclusive, end_range is not + return string.sub(lines[start_range.line_idx], start_range.byte_idx, end_range.byte_idx - 1) + + else + -- Handle deletion case + -- Collect the changed portion of the first changed line + local result = { string.sub(lines[start_range.line_idx], start_range.byte_idx) } + + -- Collect the full line for intermediate lines + for idx = start_range.line_idx + 1, end_range.line_idx - 1 do + table.insert(result, lines[idx]) + end + + if lines[end_range.line_idx] then + -- Collect the changed portion of the last changed line. + table.insert(result, string.sub(lines[end_range.line_idx], 1, end_range.byte_idx - 1)) + else + table.insert(result, "") + end + + -- Add line ending between all lines + return table.concat(result, line_ending) + end +end + +local function compute_line_length(line, offset_encoding) + local length + local _ + if offset_encoding == 'utf-16' then + _, length = str_utfindex(line) + elseif offset_encoding == 'utf-32' then + length, _ = str_utfindex(line) + else + length = #line + end + return length +end +---@private +-- rangelength depends on the offset encoding +-- bytes for utf-8 (clangd with extenion) +-- codepoints for utf-16 +-- codeunits for utf-32 +-- Line endings count here as 2 chars for \r\n (dos), 1 char for \n (unix), and 1 char for \r (mac) +-- These correspond to Windows, Linux/macOS (OSX and newer), and macOS (version 9 and prior) +local function compute_range_length(lines, start_range, end_range, offset_encoding, line_ending) + local line_ending_length = #line_ending + -- Single line case + if start_range.line_idx == end_range.line_idx then + return end_range.char_idx - start_range.char_idx + end + + local start_line = lines[start_range.line_idx] + local range_length + if start_line and #start_line > 0 then + range_length = compute_line_length(start_line, offset_encoding) - start_range.char_idx + 1 + line_ending_length + else + -- Length of newline character + range_length = line_ending_length + end + + -- The first and last range of the line idx may be partial lines + for idx = start_range.line_idx + 1, end_range.line_idx - 1 do + -- Length full line plus newline character + if #lines[idx] > 0 then + range_length = range_length + compute_line_length(lines[idx], offset_encoding) + #line_ending + else + range_length = range_length + line_ending_length + end + end + + local end_line = lines[end_range.line_idx] + if end_line and #end_line > 0 then + range_length = range_length + end_range.char_idx - 1 + end + + return range_length +end + +--- Returns the range table for the difference between prev and curr lines +---@param prev_lines table list of lines +---@param curr_lines table list of lines +---@param firstline number line to begin search for first difference +---@param lastline number line to begin search in old_lines for last difference +---@param new_lastline number line to begin search in new_lines for last difference +---@param offset_encoding string encoding requested by language server +---@returns table TextDocumentContentChangeEvent see https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#textDocumentContentChangeEvent +function M.compute_diff(prev_lines, curr_lines, firstline, lastline, new_lastline, offset_encoding, line_ending) + -- Find the start of changes between the previous and current buffer. Common between both. + -- Sent to the server as the start of the changed range. + -- Used to grab the changed text from the latest buffer. + local start_range = compute_start_range( + prev_lines, + curr_lines, + firstline + 1, + lastline + 1, + new_lastline + 1, + offset_encoding + ) + -- Find the last position changed in the previous and current buffer. + -- prev_end_range is sent to the server as as the end of the changed range. + -- curr_end_range is used to grab the changed text from the latest buffer. + local prev_end_range, curr_end_range = compute_end_range( + prev_lines, + curr_lines, + start_range, + firstline + 1, + lastline + 1, + new_lastline + 1, + offset_encoding + ) + + -- Grab the changed text of from start_range to curr_end_range in the current buffer. + -- The text range is "" if entire range is deleted. + local text = extract_text(curr_lines, start_range, curr_end_range, line_ending) + + -- Compute the range of the replaced text. Deprecated but still required for certain language servers + local range_length = compute_range_length(prev_lines, start_range, prev_end_range, offset_encoding, line_ending) + + -- convert to 0 based indexing + local result = { + range = { + ['start'] = { line = start_range.line_idx - 1, character = start_range.char_idx - 1 }, + ['end'] = { line = prev_end_range.line_idx - 1, character = prev_end_range.char_idx - 1 }, + }, + text = text, + rangeLength = range_length, + } + + return result +end + +return M diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 952926b67e..a4b7b9922b 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -151,7 +151,7 @@ end --- Position is a https://microsoft.github.io/language-server-protocol/specifications/specification-current/#position --- Returns a zero-indexed column, since set_lines() does the conversion to --- 1-indexed -local function get_line_byte_from_position(bufnr, position) +local function get_line_byte_from_position(bufnr, position, offset_encoding) -- LSP's line and characters are 0-indexed -- Vim's line and columns are 1-indexed local col = position.character @@ -165,7 +165,13 @@ local function get_line_byte_from_position(bufnr, position) local line = position.line local lines = api.nvim_buf_get_lines(bufnr, line, line + 1, false) if #lines > 0 then - local ok, result = pcall(vim.str_byteindex, lines[1], col) + local ok, result + + if offset_encoding == "utf-16" or not offset_encoding then + ok, result = pcall(vim.str_byteindex, lines[1], col, true) + elseif offset_encoding == "utf-32" then + ok, result = pcall(vim.str_byteindex, lines[1], col, false) + end if ok then return result @@ -226,9 +232,10 @@ function M.get_progress_messages() table.remove(client.messages, item.idx) end - for _, item in ipairs(progress_remove) do - client.messages.progress[item.token] = nil - end + end + + for _, item in ipairs(progress_remove) do + item.client.messages.progress[item.token] = nil end return new_messages @@ -275,7 +282,8 @@ function M.apply_text_edits(text_edits, bufnr) -- Some LSP servers may return +1 range of the buffer content but nvim_buf_set_text can't accept it so we should fix it here. local has_eol_text_edit = false local max = vim.api.nvim_buf_line_count(bufnr) - local len = vim.str_utfindex(vim.api.nvim_buf_get_lines(bufnr, -2, -1, false)[1] or '') + -- TODO handle offset_encoding + local _, len = vim.str_utfindex(vim.api.nvim_buf_get_lines(bufnr, -2, -1, false)[1] or '') text_edits = vim.tbl_map(function(text_edit) if max <= text_edit.range.start.line then text_edit.range.start.line = max - 1 @@ -359,177 +367,6 @@ end -- function M.glob_to_regex(glob) -- end ----@private ---- Finds the first line and column of the difference between old and new lines ----@param old_lines table list of lines ----@param new_lines table list of lines ----@returns (int, int) start_line_idx and start_col_idx of range -local function first_difference(old_lines, new_lines, start_line_idx) - local line_count = math.min(#old_lines, #new_lines) - if line_count == 0 then return 1, 1 end - if not start_line_idx then - for i = 1, line_count do - start_line_idx = i - if old_lines[start_line_idx] ~= new_lines[start_line_idx] then - break - end - end - end - local old_line = old_lines[start_line_idx] - local new_line = new_lines[start_line_idx] - local length = math.min(#old_line, #new_line) - local start_col_idx = 1 - while start_col_idx <= length do - if string.sub(old_line, start_col_idx, start_col_idx) ~= string.sub(new_line, start_col_idx, start_col_idx) then - break - end - start_col_idx = start_col_idx + 1 - end - return start_line_idx, start_col_idx -end - - ----@private ---- Finds the last line and column of the differences between old and new lines ----@param old_lines table list of lines ----@param new_lines table list of lines ----@param start_char integer First different character idx of range ----@returns (int, int) end_line_idx and end_col_idx of range -local function last_difference(old_lines, new_lines, start_char, end_line_idx) - local line_count = math.min(#old_lines, #new_lines) - if line_count == 0 then return 0,0 end - if not end_line_idx then - end_line_idx = -1 - end - for i = end_line_idx, -line_count, -1 do - if old_lines[#old_lines + i + 1] ~= new_lines[#new_lines + i + 1] then - end_line_idx = i - break - end - end - local old_line - local new_line - if end_line_idx <= -line_count then - end_line_idx = -line_count - old_line = string.sub(old_lines[#old_lines + end_line_idx + 1], start_char) - new_line = string.sub(new_lines[#new_lines + end_line_idx + 1], start_char) - else - old_line = old_lines[#old_lines + end_line_idx + 1] - new_line = new_lines[#new_lines + end_line_idx + 1] - end - local old_line_length = #old_line - local new_line_length = #new_line - local length = math.min(old_line_length, new_line_length) - local end_col_idx = -1 - while end_col_idx >= -length do - local old_char = string.sub(old_line, old_line_length + end_col_idx + 1, old_line_length + end_col_idx + 1) - local new_char = string.sub(new_line, new_line_length + end_col_idx + 1, new_line_length + end_col_idx + 1) - if old_char ~= new_char then - break - end - end_col_idx = end_col_idx - 1 - end - return end_line_idx, end_col_idx - -end - ----@private ---- Get the text of the range defined by start and end line/column ----@param lines table list of lines ----@param start_char integer First different character idx of range ----@param end_char integer Last different character idx of range ----@param start_line integer First different line idx of range ----@param end_line integer Last different line idx of range ----@returns string text extracted from defined region -local function extract_text(lines, start_line, start_char, end_line, end_char) - if start_line == #lines + end_line + 1 then - if end_line == 0 then return '' end - local line = lines[start_line] - local length = #line + end_char - start_char - return string.sub(line, start_char, start_char + length + 1) - end - local result = string.sub(lines[start_line], start_char) .. '\n' - for line_idx = start_line + 1, #lines + end_line do - result = result .. lines[line_idx] .. '\n' - end - if end_line ~= 0 then - local line = lines[#lines + end_line + 1] - local length = #line + end_char + 1 - result = result .. string.sub(line, 1, length) - end - return result -end - ----@private ---- Compute the length of the substituted range ----@param lines table list of lines ----@param start_char integer First different character idx of range ----@param end_char integer Last different character idx of range ----@param start_line integer First different line idx of range ----@param end_line integer Last different line idx of range ----@returns (int, int) end_line_idx and end_col_idx of range -local function compute_length(lines, start_line, start_char, end_line, end_char) - local adj_end_line = #lines + end_line + 1 - local adj_end_char - if adj_end_line > #lines then - adj_end_char = end_char - 1 - else - adj_end_char = #lines[adj_end_line] + end_char - end - if start_line == adj_end_line then - return adj_end_char - start_char + 1 - end - local result = #lines[start_line] - start_char + 1 - for line = start_line + 1, adj_end_line -1 do - result = result + #lines[line] + 1 - end - result = result + adj_end_char + 1 - return result -end - ---- Returns the range table for the difference between old and new lines ----@param old_lines table list of lines ----@param new_lines table list of lines ----@param start_line_idx int line to begin search for first difference ----@param end_line_idx int line to begin search for last difference ----@param offset_encoding string encoding requested by language server ----@returns table start_line_idx and start_col_idx of range -function M.compute_diff(old_lines, new_lines, start_line_idx, end_line_idx, offset_encoding) - local start_line, start_char = first_difference(old_lines, new_lines, start_line_idx) - local end_line, end_char = last_difference(vim.list_slice(old_lines, start_line, #old_lines), - vim.list_slice(new_lines, start_line, #new_lines), start_char, end_line_idx) - local text = extract_text(new_lines, start_line, start_char, end_line, end_char) - local length = compute_length(old_lines, start_line, start_char, end_line, end_char) - - local adj_end_line = #old_lines + end_line - local adj_end_char - if end_line == 0 then - adj_end_char = 0 - else - adj_end_char = #old_lines[#old_lines + end_line + 1] + end_char + 1 - end - - local _ - if offset_encoding == "utf-16" then - _, start_char = vim.str_utfindex(old_lines[start_line], start_char - 1) - _, end_char = vim.str_utfindex(old_lines[#old_lines + end_line + 1], adj_end_char) - else - start_char = start_char - 1 - end_char = adj_end_char - end - - local result = { - range = { - start = { line = start_line - 1, character = start_char}, - ["end"] = { line = adj_end_line, character = end_char} - }, - text = text, - rangeLength = length + 1, - } - - return result -end - --- Can be used to extract the completion items from a --- `textDocument/completion` request, which may return one of --- `CompletionItem[]`, `CompletionList` or null. @@ -712,18 +549,29 @@ end -- ignoreIfExists? bool function M.rename(old_fname, new_fname, opts) opts = opts or {} - local bufnr = vim.fn.bufadd(old_fname) - vim.fn.bufload(bufnr) local target_exists = vim.loop.fs_stat(new_fname) ~= nil if target_exists and not opts.overwrite or opts.ignoreIfExists then vim.notify('Rename target already exists. Skipping rename.') return end + local oldbuf = vim.fn.bufadd(old_fname) + vim.fn.bufload(oldbuf) + + -- The there may be pending changes in the buffer + api.nvim_buf_call(oldbuf, function() + vim.cmd('w!') + end) + local ok, err = os.rename(old_fname, new_fname) assert(ok, err) - api.nvim_buf_call(bufnr, function() - vim.cmd('saveas! ' .. vim.fn.fnameescape(new_fname)) - end) + + local newbuf = vim.fn.bufadd(new_fname) + for _, win in pairs(api.nvim_list_wins()) do + if api.nvim_win_get_buf(win) == oldbuf then + api.nvim_win_set_buf(win, newbuf) + end + end + api.nvim_buf_delete(oldbuf, { force = true }) end @@ -1494,18 +1342,30 @@ do --[[ References ]] ---@param bufnr buffer id ---@param references List of `DocumentHighlight` objects to highlight ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#documentHighlight - function M.buf_highlight_references(bufnr, references) + function M.buf_highlight_references(bufnr, references, client_id) validate { bufnr = {bufnr, 'n', true} } + local client = vim.lsp.get_client_by_id(client_id) + if not client then + return + end for _, reference in ipairs(references) do - local start_pos = {reference["range"]["start"]["line"], reference["range"]["start"]["character"]} - local end_pos = {reference["range"]["end"]["line"], reference["range"]["end"]["character"]} + local start_line, start_char = reference["range"]["start"]["line"], reference["range"]["start"]["character"] + local end_line, end_char = reference["range"]["end"]["line"], reference["range"]["end"]["character"] + + local start_idx = get_line_byte_from_position(bufnr, { line = start_line, character = start_char }, client.offset_encoding) + local end_idx = get_line_byte_from_position(bufnr, { line = start_line, character = end_char }, client.offset_encoding) + local document_highlight_kind = { [protocol.DocumentHighlightKind.Text] = "LspReferenceText"; [protocol.DocumentHighlightKind.Read] = "LspReferenceRead"; [protocol.DocumentHighlightKind.Write] = "LspReferenceWrite"; } local kind = reference["kind"] or protocol.DocumentHighlightKind.Text - highlight.range(bufnr, reference_ns, document_highlight_kind[kind], start_pos, end_pos) + highlight.range(bufnr, + reference_ns, + document_highlight_kind[kind], + { start_line, start_idx }, + { end_line, end_idx }) end end end @@ -1719,7 +1579,9 @@ function M.symbols_to_items(symbols, bufnr) }) if symbol.children then for _, v in ipairs(_symbols_to_items(symbol.children, _items, _bufnr)) do - vim.list_extend(_items, v) + for _, s in ipairs(v) do + table.insert(_items, s) + end end end end @@ -1787,7 +1649,9 @@ local function make_position_param() if not line then return { line = 0; character = 0; } end - col = str_utfindex(line, col) + -- TODO handle offset_encoding + local _ + _, col = str_utfindex(line, col) return { line = row; character = col; } end @@ -1837,11 +1701,14 @@ function M.make_given_range_params(start_pos, end_pos) A[1] = A[1] - 1 B[1] = B[1] - 1 -- account for encoding. + -- TODO handle offset_encoding if A[2] > 0 then - A = {A[1], M.character_offset(0, A[1], A[2])} + local _, char = M.character_offset(0, A[1], A[2]) + A = {A[1], char} end if B[2] > 0 then - B = {B[1], M.character_offset(0, B[1], B[2])} + local _, char = M.character_offset(0, B[1], B[2]) + B = {B[1], char} end -- we need to offset the end character position otherwise we loose the last -- character of the selection, as LSP end position is exclusive diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index b57b7ad4ad..6e40b6ca52 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -605,7 +605,7 @@ do function vim.validate(opt) local ok, err_msg = is_valid(opt) if not ok then - error(debug.traceback(err_msg, 2), 2) + error(err_msg, 2) end end end diff --git a/runtime/lua/vim/ui.lua b/runtime/lua/vim/ui.lua index 5eab20fc54..9568b60fd0 100644 --- a/runtime/lua/vim/ui.lua +++ b/runtime/lua/vim/ui.lua @@ -9,6 +9,11 @@ local M = {} --- - format_item (function item -> text) --- Function to format an --- individual item from `items`. Defaults to `tostring`. +--- - kind (string|nil) +--- Arbitrary hint string indicating the item shape. +--- Plugins reimplementing `vim.ui.select` may wish to +--- use this to infer the structure or semantics of +--- `items`, or the context in which select() was called. ---@param on_choice function ((item|nil, idx|nil) -> ()) --- Called once the user made a choice. --- `idx` is the 1-based index of `item` within `item`. @@ -32,5 +37,38 @@ function M.select(items, opts, on_choice) end end +--- Prompts the user for input +--- +---@param opts table Additional options. See |input()| +--- - prompt (string|nil) +--- Text of the prompt. Defaults to `Input: `. +--- - default (string|nil) +--- Default reply to the input +--- - completion (string|nil) +--- Specifies type of completion supported +--- for input. Supported types are the same +--- that can be supplied to a user-defined +--- command using the "-complete=" argument. +--- See |:command-completion| +--- - highlight (function) +--- Function that will be used for highlighting +--- user inputs. +---@param on_confirm function ((input|nil) -> ()) +--- Called once the user confirms or abort the input. +--- `input` is what the user typed. +--- `nil` if the user aborted the dialog. +function M.input(opts, on_confirm) + vim.validate { + on_confirm = { on_confirm, 'function', false }, + } + + opts = opts or {} + local input = vim.fn.input(opts) + if #input > 0 then + on_confirm(input) + else + on_confirm(nil) + end +end return M diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index 8057d7f284..8de03dfab7 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -2,7 +2,7 @@ " " Author: Bram Moolenaar " Copyright: Vim license applies, see ":help license" -" Last Change: 2021 Aug 23 +" Last Change: 2021 Oct 26 " " WORK IN PROGRESS - Only the basics work " Note: On MS-Windows you need a recent version of gdb. The one included with @@ -550,7 +550,7 @@ func s:GdbOutCallback(job_id, msgs, event) let index = 0 for msg in a:msgs - if msg =~ '^^error,msg=' + if msg =~ '^\^error,msg=' if exists('s:evalexpr') \ && s:DecodeMessage(msg[11:]) \ =~ 'A syntax error in expression, near\|No symbol .* in current context' @@ -746,8 +746,8 @@ func s:HandleDisasmMsg(msg) else let value = substitute(a:msg, '^\~\"[ ]*', '', '') let value = substitute(value, '^=>[ ]*', '', '') - let value = substitute(value, '\\n\"
$', '', '') - let value = substitute(value, '
', '', '') + let value = substitute(value, '\\n\"\r$', '', '') + let value = substitute(value, '\r', '', '') let value = substitute(value, '\\t', ' ', 'g') if value != '' || !empty(s:asm_lines) @@ -965,8 +965,22 @@ func s:Run(args) endfunc func s:SendEval(expr) - call s:SendCommand('-data-evaluate-expression "' . a:expr . '"') - let s:evalexpr = a:expr + " clean up expression that may got in because of range + " (newlines and surrounding spaces) + let expr = a:expr + if &filetype ==# 'cobol' + " extra cleanup for COBOL: _every: expression ends with a period, + " a trailing comma is ignored as it commonly separates multiple expr. + let expr = substitute(expr, '\..*', '', '') + let expr = substitute(expr, '[;\n]', ' ', 'g') + let expr = substitute(expr, ',*$', '', '') + else + let expr = substitute(expr, '\n', ' ', 'g') + endif + let expr = substitute(expr, '^ *\(.*\) *', '\1', '') + + call s:SendCommand('-data-evaluate-expression "' . expr . '"') + let s:evalexpr = expr endfunc " :Evaluate - evaluate what is under the cursor @@ -1151,7 +1165,8 @@ func s:HandleError(msg) let s:evalFromBalloonExpr = 0 return endif - echoerr substitute(a:msg, '.*msg="\(.*\)"', '\1', '') + let msgVal = substitute(a:msg, '.*msg="\(.*\)"', '\1', '') + echoerr substitute(msgVal, '\\"', '"', 'g') endfunc func s:GotoSourcewinOrCreateIt() diff --git a/runtime/syntax/arduino.vim b/runtime/syntax/arduino.vim index 4a4ef82072..2f06eb6e64 100644 --- a/runtime/syntax/arduino.vim +++ b/runtime/syntax/arduino.vim @@ -1,50 +1,79 @@ " Vim syntax file " Language: Arduino " Maintainer: Johannes Hoff <johannes@johanneshoff.com> -" Last Change: 2011 June 3 +" Last Change: 21 October 2021 " License: VIM license (:help license, replace vim by arduino.vim) " Syntax highlighting like in the Arduino IDE -" Keywords extracted from <arduino>/build/shared/lib/keywords.txt (arduino -" version 0021) +" Automatically generated by the script available at +" https://github.com/johshoff/arduino-vim-syntax +" Using keywords from <arduino>/build/shared/lib/keywords.txt +" From version: 1.8.16 -" Thanks to Rik, Erik Nomitch, Adam Obeng and Graeme Cross for helpful feedback! +" Thanks to Rik, Erik Nomitch, Adam Obeng, Graeme Cross and Niall Parker +" for helpful feedback! -" quit when a syntax file was already loaded -if exists("b:current_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") finish endif " Read the C syntax to start with -runtime! syntax/cpp.vim - -syn keyword arduinoConstant HIGH LOW INPUT OUTPUT -syn keyword arduinoConstant DEC BIN HEX OCT BYTE -syn keyword arduinoConstant PI HALF_PI TWO_PI -syn keyword arduinoConstant LSBFIRST MSBFIRST -syn keyword arduinoConstant CHANGE FALLING RISING -syn keyword arduinoConstant SERIAL DISPLAY -syn keyword arduinoConstant DEFAULT EXTERNAL INTERNAL INTERNAL1V1 INTERNAL2V56 - -syn keyword arduinoStdFunc abs acos asin atan atan2 ceil constrain -syn keyword arduinoStdFunc cos degrees exp floor log -syn keyword arduinoStdFunc map max min pow radians -syn keyword arduinoStdFunc round sin sq sqrt tan -syn keyword arduinoStdFunc randomSeed random - -syn keyword arduinoFunc analogReference analogRead analogWrite -syn keyword arduinoFunc attachInterrupt detachInterrupt interrupts noInterrupts -syn keyword arduinoFunc lowByte highByte bitRead bitWrite bitSet bitClear -syn keyword arduinoFunc millis micros delay delayMicroseconds -syn keyword arduinoFunc pinMode digitalWrite digitalRead -syn keyword arduinoFunc tone noTone pulseIn shiftOut - -syn keyword arduinoMethod setup loop -syn keyword arduinoMethod begin end available read flush print println write peek - -syn keyword arduinoType boolean byte word String - -syn keyword arduinoModule Serial Serial1 Serial2 Serial3 +if version < 600 + so <sfile>:p:h/cpp.vim +else + runtime! syntax/cpp.vim +endif + +syn keyword arduinoConstant BIN CHANGE DEC DEFAULT EXTERNAL FALLING HALF_PI HEX +syn keyword arduinoConstant HIGH INPUT INPUT_PULLUP INTERNAL INTERNAL1V1 +syn keyword arduinoConstant INTERNAL2V56 LED_BUILTIN LED_BUILTIN_RX +syn keyword arduinoConstant LED_BUILTIN_TX LOW LSBFIRST MSBFIRST OCT OUTPUT PI +syn keyword arduinoConstant RISING TWO_PI + +syn keyword arduinoFunc analogRead analogReadResolution analogReference +syn keyword arduinoFunc analogWrite analogWriteResolution attachInterrupt +syn keyword arduinoFunc bit bitClear bitRead bitSet bitWrite delay +syn keyword arduinoFunc delayMicroseconds detachInterrupt +syn keyword arduinoFunc digitalPinToInterrupt digitalRead digitalWrite +syn keyword arduinoFunc highByte interrupts lowByte micros millis +syn keyword arduinoFunc noInterrupts noTone pinMode pulseIn pulseInLong +syn keyword arduinoFunc shiftIn shiftOut tone yield + +syn keyword arduinoMethod available availableForWrite begin charAt compareTo +syn keyword arduinoMethod concat end endsWith equals equalsIgnoreCase export +syn keyword arduinoMethod final find findUntil flush getBytes indexOf +syn keyword arduinoMethod lastIndexOf length loop override parseFloat +syn keyword arduinoMethod parseInt peek print println read readBytes +syn keyword arduinoMethod readBytesUntil readString readStringUntil replace +syn keyword arduinoMethod setCharAt setTimeout setup startsWith Stream +syn keyword arduinoMethod substring toCharArray toInt toLowerCase toUpperCase +syn keyword arduinoMethod trim + +syn keyword arduinoModule Keyboard Mouse Serial Serial1 Serial2 Serial3 +syn keyword arduinoModule SerialUSB + +syn keyword arduinoStdFunc abs accept acos acosf asin asinf atan atan2 atan2f +syn keyword arduinoStdFunc atanf cbrt cbrtf ceil ceilf click constrain +syn keyword arduinoStdFunc copysign copysignf cos cosf cosh coshf degrees exp +syn keyword arduinoStdFunc expf fabs fabsf fdim fdimf floor floorf fma fmaf +syn keyword arduinoStdFunc fmax fmaxf fmin fminf fmod fmodf hypot hypotf +syn keyword arduinoStdFunc isfinite isinf isnan isPressed ldexp ldexpf log +syn keyword arduinoStdFunc log10 log10f logf lrint lrintf lround lroundf map +syn keyword arduinoStdFunc max min move pow powf press radians random +syn keyword arduinoStdFunc randomSeed release releaseAll round roundf signbit +syn keyword arduinoStdFunc sin sinf sinh sinhf sq sqrt sqrtf tan tanf tanh +syn keyword arduinoStdFunc tanhf trunc truncf + +syn keyword arduinoType _Bool _Complex _Imaginary array atomic_bool +syn keyword arduinoType atomic_char atomic_int atomic_llong atomic_long +syn keyword arduinoType atomic_schar atomic_short atomic_uchar atomic_uint +syn keyword arduinoType atomic_ullong atomic_ulong atomic_ushort boolean +syn keyword arduinoType byte char16_t char32_t complex NULL null PROGMEM +syn keyword arduinoType String word hi def link arduinoType Type hi def link arduinoConstant Constant diff --git a/runtime/syntax/clojure.vim b/runtime/syntax/clojure.vim index 1037967d1c..9782dc41ad 100644 --- a/runtime/syntax/clojure.vim +++ b/runtime/syntax/clojure.vim @@ -1,13 +1,13 @@ " Vim indent file " Language: Clojure -" Maintainer: Alex Vear <av@axvr.io> +" Maintainer: Alex Vear <alex@vear.uk> " Former Maintainers: Sung Pae <self@sungpae.com> " Meikel Brandmeyer <mb@kotka.de> " Toralf Wittner <toralf.wittner@gmail.com> " Contributors: Joel Holdbrooks <cjholdbrooks@gmail.com> (Regexp support, bug fixes) " URL: https://github.com/clojure-vim/clojure.vim " License: Vim (see :h license) -" Last Change: 2021-02-13 +" Last Change: 2021-10-26 if exists("b:current_syntax") finish @@ -21,15 +21,15 @@ if has("folding") && exists("g:clojure_fold") && g:clojure_fold > 0 endif " -*- KEYWORDS -*- -" Generated from https://github.com/clojure-vim/clojure.vim/blob/f8594e7030cdfb0b7990ac92953c77a08a7220f0/clj/src/vim_clojure_static/generate.clj -" Clojure version 1.10.2 +" Generated from https://github.com/clojure-vim/clojure.vim/blob/62b215f079ce0f3834fd295c7a7f6bd8cc54bcc3/clj/src/vim_clojure_static/generate.clj +" Clojure version 1.10.3 let s:clojure_syntax_keywords = { \ 'clojureBoolean': ["false","true"] \ , 'clojureCond': ["case","clojure.core/case","clojure.core/cond","clojure.core/cond->","clojure.core/cond->>","clojure.core/condp","clojure.core/if-let","clojure.core/if-not","clojure.core/if-some","clojure.core/when","clojure.core/when-first","clojure.core/when-let","clojure.core/when-not","clojure.core/when-some","cond","cond->","cond->>","condp","if-let","if-not","if-some","when","when-first","when-let","when-not","when-some"] \ , 'clojureConstant': ["nil"] \ , 'clojureDefine': ["clojure.core/definline","clojure.core/definterface","clojure.core/defmacro","clojure.core/defmethod","clojure.core/defmulti","clojure.core/defn","clojure.core/defn-","clojure.core/defonce","clojure.core/defprotocol","clojure.core/defrecord","clojure.core/defstruct","clojure.core/deftype","definline","definterface","defmacro","defmethod","defmulti","defn","defn-","defonce","defprotocol","defrecord","defstruct","deftype"] \ , 'clojureException': ["catch","finally","throw","try"] - \ , 'clojureFunc': ["*","*'","+","+'","-","-'","->ArrayChunk","->Eduction","->Vec","->VecNode","->VecSeq","-cache-protocol-fn","-reset-methods","/","<","<=","=","==",">",">=","PrintWriter-on","StackTraceElement->vec","Throwable->map","accessor","aclone","add-classpath","add-tap","add-watch","agent","agent-error","agent-errors","aget","alength","alias","all-ns","alter","alter-meta!","alter-var-root","ancestors","any?","apply","array-map","aset","aset-boolean","aset-byte","aset-char","aset-double","aset-float","aset-int","aset-long","aset-short","assoc","assoc!","assoc-in","associative?","atom","await","await-for","await1","bases","bean","bigdec","bigint","biginteger","bit-and","bit-and-not","bit-clear","bit-flip","bit-not","bit-or","bit-set","bit-shift-left","bit-shift-right","bit-test","bit-xor","boolean","boolean-array","boolean?","booleans","bound-fn*","bound?","bounded-count","butlast","byte","byte-array","bytes","bytes?","case-fallthrough-err-impl","cast","cat","char","char-array","char?","chars","chunk","chunk-append","chunk-buffer","chunk-cons","chunk-first","chunk-next","chunk-rest","chunked-seq?","class","class?","clear-agent-errors","clojure-version","clojure.core/*","clojure.core/*'","clojure.core/+","clojure.core/+'","clojure.core/-","clojure.core/-'","clojure.core/->ArrayChunk","clojure.core/->Eduction","clojure.core/->Vec","clojure.core/->VecNode","clojure.core/->VecSeq","clojure.core/-cache-protocol-fn","clojure.core/-reset-methods","clojure.core//","clojure.core/<","clojure.core/<=","clojure.core/=","clojure.core/==","clojure.core/>","clojure.core/>=","clojure.core/PrintWriter-on","clojure.core/StackTraceElement->vec","clojure.core/Throwable->map","clojure.core/accessor","clojure.core/aclone","clojure.core/add-classpath","clojure.core/add-tap","clojure.core/add-watch","clojure.core/agent","clojure.core/agent-error","clojure.core/agent-errors","clojure.core/aget","clojure.core/alength","clojure.core/alias","clojure.core/all-ns","clojure.core/alter","clojure.core/alter-meta!","clojure.core/alter-var-root","clojure.core/ancestors","clojure.core/any?","clojure.core/apply","clojure.core/array-map","clojure.core/aset","clojure.core/aset-boolean","clojure.core/aset-byte","clojure.core/aset-char","clojure.core/aset-double","clojure.core/aset-float","clojure.core/aset-int","clojure.core/aset-long","clojure.core/aset-short","clojure.core/assoc","clojure.core/assoc!","clojure.core/assoc-in","clojure.core/associative?","clojure.core/atom","clojure.core/await","clojure.core/await-for","clojure.core/await1","clojure.core/bases","clojure.core/bean","clojure.core/bigdec","clojure.core/bigint","clojure.core/biginteger","clojure.core/bit-and","clojure.core/bit-and-not","clojure.core/bit-clear","clojure.core/bit-flip","clojure.core/bit-not","clojure.core/bit-or","clojure.core/bit-set","clojure.core/bit-shift-left","clojure.core/bit-shift-right","clojure.core/bit-test","clojure.core/bit-xor","clojure.core/boolean","clojure.core/boolean-array","clojure.core/boolean?","clojure.core/booleans","clojure.core/bound-fn*","clojure.core/bound?","clojure.core/bounded-count","clojure.core/butlast","clojure.core/byte","clojure.core/byte-array","clojure.core/bytes","clojure.core/bytes?","clojure.core/case-fallthrough-err-impl","clojure.core/cast","clojure.core/cat","clojure.core/char","clojure.core/char-array","clojure.core/char?","clojure.core/chars","clojure.core/chunk","clojure.core/chunk-append","clojure.core/chunk-buffer","clojure.core/chunk-cons","clojure.core/chunk-first","clojure.core/chunk-next","clojure.core/chunk-rest","clojure.core/chunked-seq?","clojure.core/class","clojure.core/class?","clojure.core/clear-agent-errors","clojure.core/clojure-version","clojure.core/coll?","clojure.core/commute","clojure.core/comp","clojure.core/comparator","clojure.core/compare","clojure.core/compare-and-set!","clojure.core/compile","clojure.core/complement","clojure.core/completing","clojure.core/concat","clojure.core/conj","clojure.core/conj!","clojure.core/cons","clojure.core/constantly","clojure.core/construct-proxy","clojure.core/contains?","clojure.core/count","clojure.core/counted?","clojure.core/create-ns","clojure.core/create-struct","clojure.core/cycle","clojure.core/dec","clojure.core/dec'","clojure.core/decimal?","clojure.core/dedupe","clojure.core/delay?","clojure.core/deliver","clojure.core/denominator","clojure.core/deref","clojure.core/derive","clojure.core/descendants","clojure.core/destructure","clojure.core/disj","clojure.core/disj!","clojure.core/dissoc","clojure.core/dissoc!","clojure.core/distinct","clojure.core/distinct?","clojure.core/doall","clojure.core/dorun","clojure.core/double","clojure.core/double-array","clojure.core/double?","clojure.core/doubles","clojure.core/drop","clojure.core/drop-last","clojure.core/drop-while","clojure.core/eduction","clojure.core/empty","clojure.core/empty?","clojure.core/ensure","clojure.core/ensure-reduced","clojure.core/enumeration-seq","clojure.core/error-handler","clojure.core/error-mode","clojure.core/eval","clojure.core/even?","clojure.core/every-pred","clojure.core/every?","clojure.core/ex-cause","clojure.core/ex-data","clojure.core/ex-info","clojure.core/ex-message","clojure.core/extend","clojure.core/extenders","clojure.core/extends?","clojure.core/false?","clojure.core/ffirst","clojure.core/file-seq","clojure.core/filter","clojure.core/filterv","clojure.core/find","clojure.core/find-keyword","clojure.core/find-ns","clojure.core/find-protocol-impl","clojure.core/find-protocol-method","clojure.core/find-var","clojure.core/first","clojure.core/flatten","clojure.core/float","clojure.core/float-array","clojure.core/float?","clojure.core/floats","clojure.core/flush","clojure.core/fn?","clojure.core/fnext","clojure.core/fnil","clojure.core/force","clojure.core/format","clojure.core/frequencies","clojure.core/future-call","clojure.core/future-cancel","clojure.core/future-cancelled?","clojure.core/future-done?","clojure.core/future?","clojure.core/gensym","clojure.core/get","clojure.core/get-in","clojure.core/get-method","clojure.core/get-proxy-class","clojure.core/get-thread-bindings","clojure.core/get-validator","clojure.core/group-by","clojure.core/halt-when","clojure.core/hash","clojure.core/hash-combine","clojure.core/hash-map","clojure.core/hash-ordered-coll","clojure.core/hash-set","clojure.core/hash-unordered-coll","clojure.core/ident?","clojure.core/identical?","clojure.core/identity","clojure.core/ifn?","clojure.core/in-ns","clojure.core/inc","clojure.core/inc'","clojure.core/indexed?","clojure.core/init-proxy","clojure.core/inst-ms","clojure.core/inst-ms*","clojure.core/inst?","clojure.core/instance?","clojure.core/int","clojure.core/int-array","clojure.core/int?","clojure.core/integer?","clojure.core/interleave","clojure.core/intern","clojure.core/interpose","clojure.core/into","clojure.core/into-array","clojure.core/ints","clojure.core/isa?","clojure.core/iterate","clojure.core/iterator-seq","clojure.core/juxt","clojure.core/keep","clojure.core/keep-indexed","clojure.core/key","clojure.core/keys","clojure.core/keyword","clojure.core/keyword?","clojure.core/last","clojure.core/line-seq","clojure.core/list","clojure.core/list*","clojure.core/list?","clojure.core/load","clojure.core/load-file","clojure.core/load-reader","clojure.core/load-string","clojure.core/loaded-libs","clojure.core/long","clojure.core/long-array","clojure.core/longs","clojure.core/macroexpand","clojure.core/macroexpand-1","clojure.core/make-array","clojure.core/make-hierarchy","clojure.core/map","clojure.core/map-entry?","clojure.core/map-indexed","clojure.core/map?","clojure.core/mapcat","clojure.core/mapv","clojure.core/max","clojure.core/max-key","clojure.core/memoize","clojure.core/merge","clojure.core/merge-with","clojure.core/meta","clojure.core/method-sig","clojure.core/methods","clojure.core/min","clojure.core/min-key","clojure.core/mix-collection-hash","clojure.core/mod","clojure.core/munge","clojure.core/name","clojure.core/namespace","clojure.core/namespace-munge","clojure.core/nat-int?","clojure.core/neg-int?","clojure.core/neg?","clojure.core/newline","clojure.core/next","clojure.core/nfirst","clojure.core/nil?","clojure.core/nnext","clojure.core/not","clojure.core/not-any?","clojure.core/not-empty","clojure.core/not-every?","clojure.core/not=","clojure.core/ns-aliases","clojure.core/ns-imports","clojure.core/ns-interns","clojure.core/ns-map","clojure.core/ns-name","clojure.core/ns-publics","clojure.core/ns-refers","clojure.core/ns-resolve","clojure.core/ns-unalias","clojure.core/ns-unmap","clojure.core/nth","clojure.core/nthnext","clojure.core/nthrest","clojure.core/num","clojure.core/number?","clojure.core/numerator","clojure.core/object-array","clojure.core/odd?","clojure.core/parents","clojure.core/partial","clojure.core/partition","clojure.core/partition-all","clojure.core/partition-by","clojure.core/pcalls","clojure.core/peek","clojure.core/persistent!","clojure.core/pmap","clojure.core/pop","clojure.core/pop!","clojure.core/pop-thread-bindings","clojure.core/pos-int?","clojure.core/pos?","clojure.core/pr","clojure.core/pr-str","clojure.core/prefer-method","clojure.core/prefers","clojure.core/print","clojure.core/print-ctor","clojure.core/print-dup","clojure.core/print-method","clojure.core/print-simple","clojure.core/print-str","clojure.core/printf","clojure.core/println","clojure.core/println-str","clojure.core/prn","clojure.core/prn-str","clojure.core/promise","clojure.core/proxy-call-with-super","clojure.core/proxy-mappings","clojure.core/proxy-name","clojure.core/push-thread-bindings","clojure.core/qualified-ident?","clojure.core/qualified-keyword?","clojure.core/qualified-symbol?","clojure.core/quot","clojure.core/rand","clojure.core/rand-int","clojure.core/rand-nth","clojure.core/random-sample","clojure.core/range","clojure.core/ratio?","clojure.core/rational?","clojure.core/rationalize","clojure.core/re-find","clojure.core/re-groups","clojure.core/re-matcher","clojure.core/re-matches","clojure.core/re-pattern","clojure.core/re-seq","clojure.core/read","clojure.core/read+string","clojure.core/read-line","clojure.core/read-string","clojure.core/reader-conditional","clojure.core/reader-conditional?","clojure.core/realized?","clojure.core/record?","clojure.core/reduce","clojure.core/reduce-kv","clojure.core/reduced","clojure.core/reduced?","clojure.core/reductions","clojure.core/ref","clojure.core/ref-history-count","clojure.core/ref-max-history","clojure.core/ref-min-history","clojure.core/ref-set","clojure.core/refer","clojure.core/release-pending-sends","clojure.core/rem","clojure.core/remove","clojure.core/remove-all-methods","clojure.core/remove-method","clojure.core/remove-ns","clojure.core/remove-tap","clojure.core/remove-watch","clojure.core/repeat","clojure.core/repeatedly","clojure.core/replace","clojure.core/replicate","clojure.core/require","clojure.core/requiring-resolve","clojure.core/reset!","clojure.core/reset-meta!","clojure.core/reset-vals!","clojure.core/resolve","clojure.core/rest","clojure.core/restart-agent","clojure.core/resultset-seq","clojure.core/reverse","clojure.core/reversible?","clojure.core/rseq","clojure.core/rsubseq","clojure.core/run!","clojure.core/satisfies?","clojure.core/second","clojure.core/select-keys","clojure.core/send","clojure.core/send-off","clojure.core/send-via","clojure.core/seq","clojure.core/seq?","clojure.core/seqable?","clojure.core/seque","clojure.core/sequence","clojure.core/sequential?","clojure.core/set","clojure.core/set-agent-send-executor!","clojure.core/set-agent-send-off-executor!","clojure.core/set-error-handler!","clojure.core/set-error-mode!","clojure.core/set-validator!","clojure.core/set?","clojure.core/short","clojure.core/short-array","clojure.core/shorts","clojure.core/shuffle","clojure.core/shutdown-agents","clojure.core/simple-ident?","clojure.core/simple-keyword?","clojure.core/simple-symbol?","clojure.core/slurp","clojure.core/some","clojure.core/some-fn","clojure.core/some?","clojure.core/sort","clojure.core/sort-by","clojure.core/sorted-map","clojure.core/sorted-map-by","clojure.core/sorted-set","clojure.core/sorted-set-by","clojure.core/sorted?","clojure.core/special-symbol?","clojure.core/spit","clojure.core/split-at","clojure.core/split-with","clojure.core/str","clojure.core/string?","clojure.core/struct","clojure.core/struct-map","clojure.core/subs","clojure.core/subseq","clojure.core/subvec","clojure.core/supers","clojure.core/swap!","clojure.core/swap-vals!","clojure.core/symbol","clojure.core/symbol?","clojure.core/tagged-literal","clojure.core/tagged-literal?","clojure.core/take","clojure.core/take-last","clojure.core/take-nth","clojure.core/take-while","clojure.core/tap>","clojure.core/test","clojure.core/the-ns","clojure.core/thread-bound?","clojure.core/to-array","clojure.core/to-array-2d","clojure.core/trampoline","clojure.core/transduce","clojure.core/transient","clojure.core/tree-seq","clojure.core/true?","clojure.core/type","clojure.core/unchecked-add","clojure.core/unchecked-add-int","clojure.core/unchecked-byte","clojure.core/unchecked-char","clojure.core/unchecked-dec","clojure.core/unchecked-dec-int","clojure.core/unchecked-divide-int","clojure.core/unchecked-double","clojure.core/unchecked-float","clojure.core/unchecked-inc","clojure.core/unchecked-inc-int","clojure.core/unchecked-int","clojure.core/unchecked-long","clojure.core/unchecked-multiply","clojure.core/unchecked-multiply-int","clojure.core/unchecked-negate","clojure.core/unchecked-negate-int","clojure.core/unchecked-remainder-int","clojure.core/unchecked-short","clojure.core/unchecked-subtract","clojure.core/unchecked-subtract-int","clojure.core/underive","clojure.core/unreduced","clojure.core/unsigned-bit-shift-right","clojure.core/update","clojure.core/update-in","clojure.core/update-proxy","clojure.core/uri?","clojure.core/use","clojure.core/uuid?","clojure.core/val","clojure.core/vals","clojure.core/var-get","clojure.core/var-set","clojure.core/var?","clojure.core/vary-meta","clojure.core/vec","clojure.core/vector","clojure.core/vector-of","clojure.core/vector?","clojure.core/volatile!","clojure.core/volatile?","clojure.core/vreset!","clojure.core/with-bindings*","clojure.core/with-meta","clojure.core/with-redefs-fn","clojure.core/xml-seq","clojure.core/zero?","clojure.core/zipmap","coll?","commute","comp","comparator","compare","compare-and-set!","compile","complement","completing","concat","conj","conj!","cons","constantly","construct-proxy","contains?","count","counted?","create-ns","create-struct","cycle","dec","dec'","decimal?","dedupe","delay?","deliver","denominator","deref","derive","descendants","destructure","disj","disj!","dissoc","dissoc!","distinct","distinct?","doall","dorun","double","double-array","double?","doubles","drop","drop-last","drop-while","eduction","empty","empty?","ensure","ensure-reduced","enumeration-seq","error-handler","error-mode","eval","even?","every-pred","every?","ex-cause","ex-data","ex-info","ex-message","extend","extenders","extends?","false?","ffirst","file-seq","filter","filterv","find","find-keyword","find-ns","find-protocol-impl","find-protocol-method","find-var","first","flatten","float","float-array","float?","floats","flush","fn?","fnext","fnil","force","format","frequencies","future-call","future-cancel","future-cancelled?","future-done?","future?","gensym","get","get-in","get-method","get-proxy-class","get-thread-bindings","get-validator","group-by","halt-when","hash","hash-combine","hash-map","hash-ordered-coll","hash-set","hash-unordered-coll","ident?","identical?","identity","ifn?","in-ns","inc","inc'","indexed?","init-proxy","inst-ms","inst-ms*","inst?","instance?","int","int-array","int?","integer?","interleave","intern","interpose","into","into-array","ints","isa?","iterate","iterator-seq","juxt","keep","keep-indexed","key","keys","keyword","keyword?","last","line-seq","list","list*","list?","load","load-file","load-reader","load-string","loaded-libs","long","long-array","longs","macroexpand","macroexpand-1","make-array","make-hierarchy","map","map-entry?","map-indexed","map?","mapcat","mapv","max","max-key","memoize","merge","merge-with","meta","method-sig","methods","min","min-key","mix-collection-hash","mod","munge","name","namespace","namespace-munge","nat-int?","neg-int?","neg?","newline","next","nfirst","nil?","nnext","not","not-any?","not-empty","not-every?","not=","ns-aliases","ns-imports","ns-interns","ns-map","ns-name","ns-publics","ns-refers","ns-resolve","ns-unalias","ns-unmap","nth","nthnext","nthrest","num","number?","numerator","object-array","odd?","parents","partial","partition","partition-all","partition-by","pcalls","peek","persistent!","pmap","pop","pop!","pop-thread-bindings","pos-int?","pos?","pr","pr-str","prefer-method","prefers","print","print-ctor","print-dup","print-method","print-simple","print-str","printf","println","println-str","prn","prn-str","promise","proxy-call-with-super","proxy-mappings","proxy-name","push-thread-bindings","qualified-ident?","qualified-keyword?","qualified-symbol?","quot","rand","rand-int","rand-nth","random-sample","range","ratio?","rational?","rationalize","re-find","re-groups","re-matcher","re-matches","re-pattern","re-seq","read","read+string","read-line","read-string","reader-conditional","reader-conditional?","realized?","record?","reduce","reduce-kv","reduced","reduced?","reductions","ref","ref-history-count","ref-max-history","ref-min-history","ref-set","refer","release-pending-sends","rem","remove","remove-all-methods","remove-method","remove-ns","remove-tap","remove-watch","repeat","repeatedly","replace","replicate","require","requiring-resolve","reset!","reset-meta!","reset-vals!","resolve","rest","restart-agent","resultset-seq","reverse","reversible?","rseq","rsubseq","run!","satisfies?","second","select-keys","send","send-off","send-via","seq","seq?","seqable?","seque","sequence","sequential?","set","set-agent-send-executor!","set-agent-send-off-executor!","set-error-handler!","set-error-mode!","set-validator!","set?","short","short-array","shorts","shuffle","shutdown-agents","simple-ident?","simple-keyword?","simple-symbol?","slurp","some","some-fn","some?","sort","sort-by","sorted-map","sorted-map-by","sorted-set","sorted-set-by","sorted?","special-symbol?","spit","split-at","split-with","str","string?","struct","struct-map","subs","subseq","subvec","supers","swap!","swap-vals!","symbol","symbol?","tagged-literal","tagged-literal?","take","take-last","take-nth","take-while","tap>","test","the-ns","thread-bound?","to-array","to-array-2d","trampoline","transduce","transient","tree-seq","true?","type","unchecked-add","unchecked-add-int","unchecked-byte","unchecked-char","unchecked-dec","unchecked-dec-int","unchecked-divide-int","unchecked-double","unchecked-float","unchecked-inc","unchecked-inc-int","unchecked-int","unchecked-long","unchecked-multiply","unchecked-multiply-int","unchecked-negate","unchecked-negate-int","unchecked-remainder-int","unchecked-short","unchecked-subtract","unchecked-subtract-int","underive","unreduced","unsigned-bit-shift-right","update","update-in","update-proxy","uri?","use","uuid?","val","vals","var-get","var-set","var?","vary-meta","vec","vector","vector-of","vector?","volatile!","volatile?","vreset!","with-bindings*","with-meta","with-redefs-fn","xml-seq","zero?","zipmap"] + \ , 'clojureFunc': ["*","*'","+","+'","-","-'","->ArrayChunk","->Eduction","->Vec","->VecNode","->VecSeq","-cache-protocol-fn","-reset-methods","/","<","<=","=","==",">",">=","PrintWriter-on","StackTraceElement->vec","Throwable->map","accessor","aclone","add-classpath","add-tap","add-watch","agent","agent-error","agent-errors","aget","alength","alias","all-ns","alter","alter-meta!","alter-var-root","ancestors","any?","apply","array-map","aset","aset-boolean","aset-byte","aset-char","aset-double","aset-float","aset-int","aset-long","aset-short","assoc","assoc!","assoc-in","associative?","atom","await","await-for","await1","bases","bean","bigdec","bigint","biginteger","bit-and","bit-and-not","bit-clear","bit-flip","bit-not","bit-or","bit-set","bit-shift-left","bit-shift-right","bit-test","bit-xor","boolean","boolean-array","boolean?","booleans","bound-fn*","bound?","bounded-count","butlast","byte","byte-array","bytes","bytes?","cast","cat","char","char-array","char?","chars","chunk","chunk-append","chunk-buffer","chunk-cons","chunk-first","chunk-next","chunk-rest","chunked-seq?","class","class?","clear-agent-errors","clojure-version","clojure.core/*","clojure.core/*'","clojure.core/+","clojure.core/+'","clojure.core/-","clojure.core/-'","clojure.core/->ArrayChunk","clojure.core/->Eduction","clojure.core/->Vec","clojure.core/->VecNode","clojure.core/->VecSeq","clojure.core/-cache-protocol-fn","clojure.core/-reset-methods","clojure.core//","clojure.core/<","clojure.core/<=","clojure.core/=","clojure.core/==","clojure.core/>","clojure.core/>=","clojure.core/PrintWriter-on","clojure.core/StackTraceElement->vec","clojure.core/Throwable->map","clojure.core/accessor","clojure.core/aclone","clojure.core/add-classpath","clojure.core/add-tap","clojure.core/add-watch","clojure.core/agent","clojure.core/agent-error","clojure.core/agent-errors","clojure.core/aget","clojure.core/alength","clojure.core/alias","clojure.core/all-ns","clojure.core/alter","clojure.core/alter-meta!","clojure.core/alter-var-root","clojure.core/ancestors","clojure.core/any?","clojure.core/apply","clojure.core/array-map","clojure.core/aset","clojure.core/aset-boolean","clojure.core/aset-byte","clojure.core/aset-char","clojure.core/aset-double","clojure.core/aset-float","clojure.core/aset-int","clojure.core/aset-long","clojure.core/aset-short","clojure.core/assoc","clojure.core/assoc!","clojure.core/assoc-in","clojure.core/associative?","clojure.core/atom","clojure.core/await","clojure.core/await-for","clojure.core/await1","clojure.core/bases","clojure.core/bean","clojure.core/bigdec","clojure.core/bigint","clojure.core/biginteger","clojure.core/bit-and","clojure.core/bit-and-not","clojure.core/bit-clear","clojure.core/bit-flip","clojure.core/bit-not","clojure.core/bit-or","clojure.core/bit-set","clojure.core/bit-shift-left","clojure.core/bit-shift-right","clojure.core/bit-test","clojure.core/bit-xor","clojure.core/boolean","clojure.core/boolean-array","clojure.core/boolean?","clojure.core/booleans","clojure.core/bound-fn*","clojure.core/bound?","clojure.core/bounded-count","clojure.core/butlast","clojure.core/byte","clojure.core/byte-array","clojure.core/bytes","clojure.core/bytes?","clojure.core/cast","clojure.core/cat","clojure.core/char","clojure.core/char-array","clojure.core/char?","clojure.core/chars","clojure.core/chunk","clojure.core/chunk-append","clojure.core/chunk-buffer","clojure.core/chunk-cons","clojure.core/chunk-first","clojure.core/chunk-next","clojure.core/chunk-rest","clojure.core/chunked-seq?","clojure.core/class","clojure.core/class?","clojure.core/clear-agent-errors","clojure.core/clojure-version","clojure.core/coll?","clojure.core/commute","clojure.core/comp","clojure.core/comparator","clojure.core/compare","clojure.core/compare-and-set!","clojure.core/compile","clojure.core/complement","clojure.core/completing","clojure.core/concat","clojure.core/conj","clojure.core/conj!","clojure.core/cons","clojure.core/constantly","clojure.core/construct-proxy","clojure.core/contains?","clojure.core/count","clojure.core/counted?","clojure.core/create-ns","clojure.core/create-struct","clojure.core/cycle","clojure.core/dec","clojure.core/dec'","clojure.core/decimal?","clojure.core/dedupe","clojure.core/delay?","clojure.core/deliver","clojure.core/denominator","clojure.core/deref","clojure.core/derive","clojure.core/descendants","clojure.core/destructure","clojure.core/disj","clojure.core/disj!","clojure.core/dissoc","clojure.core/dissoc!","clojure.core/distinct","clojure.core/distinct?","clojure.core/doall","clojure.core/dorun","clojure.core/double","clojure.core/double-array","clojure.core/double?","clojure.core/doubles","clojure.core/drop","clojure.core/drop-last","clojure.core/drop-while","clojure.core/eduction","clojure.core/empty","clojure.core/empty?","clojure.core/ensure","clojure.core/ensure-reduced","clojure.core/enumeration-seq","clojure.core/error-handler","clojure.core/error-mode","clojure.core/eval","clojure.core/even?","clojure.core/every-pred","clojure.core/every?","clojure.core/ex-cause","clojure.core/ex-data","clojure.core/ex-info","clojure.core/ex-message","clojure.core/extend","clojure.core/extenders","clojure.core/extends?","clojure.core/false?","clojure.core/ffirst","clojure.core/file-seq","clojure.core/filter","clojure.core/filterv","clojure.core/find","clojure.core/find-keyword","clojure.core/find-ns","clojure.core/find-protocol-impl","clojure.core/find-protocol-method","clojure.core/find-var","clojure.core/first","clojure.core/flatten","clojure.core/float","clojure.core/float-array","clojure.core/float?","clojure.core/floats","clojure.core/flush","clojure.core/fn?","clojure.core/fnext","clojure.core/fnil","clojure.core/force","clojure.core/format","clojure.core/frequencies","clojure.core/future-call","clojure.core/future-cancel","clojure.core/future-cancelled?","clojure.core/future-done?","clojure.core/future?","clojure.core/gensym","clojure.core/get","clojure.core/get-in","clojure.core/get-method","clojure.core/get-proxy-class","clojure.core/get-thread-bindings","clojure.core/get-validator","clojure.core/group-by","clojure.core/halt-when","clojure.core/hash","clojure.core/hash-combine","clojure.core/hash-map","clojure.core/hash-ordered-coll","clojure.core/hash-set","clojure.core/hash-unordered-coll","clojure.core/ident?","clojure.core/identical?","clojure.core/identity","clojure.core/ifn?","clojure.core/in-ns","clojure.core/inc","clojure.core/inc'","clojure.core/indexed?","clojure.core/init-proxy","clojure.core/inst-ms","clojure.core/inst-ms*","clojure.core/inst?","clojure.core/instance?","clojure.core/int","clojure.core/int-array","clojure.core/int?","clojure.core/integer?","clojure.core/interleave","clojure.core/intern","clojure.core/interpose","clojure.core/into","clojure.core/into-array","clojure.core/ints","clojure.core/isa?","clojure.core/iterate","clojure.core/iterator-seq","clojure.core/juxt","clojure.core/keep","clojure.core/keep-indexed","clojure.core/key","clojure.core/keys","clojure.core/keyword","clojure.core/keyword?","clojure.core/last","clojure.core/line-seq","clojure.core/list","clojure.core/list*","clojure.core/list?","clojure.core/load","clojure.core/load-file","clojure.core/load-reader","clojure.core/load-string","clojure.core/loaded-libs","clojure.core/long","clojure.core/long-array","clojure.core/longs","clojure.core/macroexpand","clojure.core/macroexpand-1","clojure.core/make-array","clojure.core/make-hierarchy","clojure.core/map","clojure.core/map-entry?","clojure.core/map-indexed","clojure.core/map?","clojure.core/mapcat","clojure.core/mapv","clojure.core/max","clojure.core/max-key","clojure.core/memoize","clojure.core/merge","clojure.core/merge-with","clojure.core/meta","clojure.core/method-sig","clojure.core/methods","clojure.core/min","clojure.core/min-key","clojure.core/mix-collection-hash","clojure.core/mod","clojure.core/munge","clojure.core/name","clojure.core/namespace","clojure.core/namespace-munge","clojure.core/nat-int?","clojure.core/neg-int?","clojure.core/neg?","clojure.core/newline","clojure.core/next","clojure.core/nfirst","clojure.core/nil?","clojure.core/nnext","clojure.core/not","clojure.core/not-any?","clojure.core/not-empty","clojure.core/not-every?","clojure.core/not=","clojure.core/ns-aliases","clojure.core/ns-imports","clojure.core/ns-interns","clojure.core/ns-map","clojure.core/ns-name","clojure.core/ns-publics","clojure.core/ns-refers","clojure.core/ns-resolve","clojure.core/ns-unalias","clojure.core/ns-unmap","clojure.core/nth","clojure.core/nthnext","clojure.core/nthrest","clojure.core/num","clojure.core/number?","clojure.core/numerator","clojure.core/object-array","clojure.core/odd?","clojure.core/parents","clojure.core/partial","clojure.core/partition","clojure.core/partition-all","clojure.core/partition-by","clojure.core/pcalls","clojure.core/peek","clojure.core/persistent!","clojure.core/pmap","clojure.core/pop","clojure.core/pop!","clojure.core/pop-thread-bindings","clojure.core/pos-int?","clojure.core/pos?","clojure.core/pr","clojure.core/pr-str","clojure.core/prefer-method","clojure.core/prefers","clojure.core/print","clojure.core/print-ctor","clojure.core/print-dup","clojure.core/print-method","clojure.core/print-simple","clojure.core/print-str","clojure.core/printf","clojure.core/println","clojure.core/println-str","clojure.core/prn","clojure.core/prn-str","clojure.core/promise","clojure.core/proxy-call-with-super","clojure.core/proxy-mappings","clojure.core/proxy-name","clojure.core/push-thread-bindings","clojure.core/qualified-ident?","clojure.core/qualified-keyword?","clojure.core/qualified-symbol?","clojure.core/quot","clojure.core/rand","clojure.core/rand-int","clojure.core/rand-nth","clojure.core/random-sample","clojure.core/range","clojure.core/ratio?","clojure.core/rational?","clojure.core/rationalize","clojure.core/re-find","clojure.core/re-groups","clojure.core/re-matcher","clojure.core/re-matches","clojure.core/re-pattern","clojure.core/re-seq","clojure.core/read","clojure.core/read+string","clojure.core/read-line","clojure.core/read-string","clojure.core/reader-conditional","clojure.core/reader-conditional?","clojure.core/realized?","clojure.core/record?","clojure.core/reduce","clojure.core/reduce-kv","clojure.core/reduced","clojure.core/reduced?","clojure.core/reductions","clojure.core/ref","clojure.core/ref-history-count","clojure.core/ref-max-history","clojure.core/ref-min-history","clojure.core/ref-set","clojure.core/refer","clojure.core/release-pending-sends","clojure.core/rem","clojure.core/remove","clojure.core/remove-all-methods","clojure.core/remove-method","clojure.core/remove-ns","clojure.core/remove-tap","clojure.core/remove-watch","clojure.core/repeat","clojure.core/repeatedly","clojure.core/replace","clojure.core/replicate","clojure.core/require","clojure.core/requiring-resolve","clojure.core/reset!","clojure.core/reset-meta!","clojure.core/reset-vals!","clojure.core/resolve","clojure.core/rest","clojure.core/restart-agent","clojure.core/resultset-seq","clojure.core/reverse","clojure.core/reversible?","clojure.core/rseq","clojure.core/rsubseq","clojure.core/run!","clojure.core/satisfies?","clojure.core/second","clojure.core/select-keys","clojure.core/send","clojure.core/send-off","clojure.core/send-via","clojure.core/seq","clojure.core/seq?","clojure.core/seqable?","clojure.core/seque","clojure.core/sequence","clojure.core/sequential?","clojure.core/set","clojure.core/set-agent-send-executor!","clojure.core/set-agent-send-off-executor!","clojure.core/set-error-handler!","clojure.core/set-error-mode!","clojure.core/set-validator!","clojure.core/set?","clojure.core/short","clojure.core/short-array","clojure.core/shorts","clojure.core/shuffle","clojure.core/shutdown-agents","clojure.core/simple-ident?","clojure.core/simple-keyword?","clojure.core/simple-symbol?","clojure.core/slurp","clojure.core/some","clojure.core/some-fn","clojure.core/some?","clojure.core/sort","clojure.core/sort-by","clojure.core/sorted-map","clojure.core/sorted-map-by","clojure.core/sorted-set","clojure.core/sorted-set-by","clojure.core/sorted?","clojure.core/special-symbol?","clojure.core/spit","clojure.core/split-at","clojure.core/split-with","clojure.core/str","clojure.core/string?","clojure.core/struct","clojure.core/struct-map","clojure.core/subs","clojure.core/subseq","clojure.core/subvec","clojure.core/supers","clojure.core/swap!","clojure.core/swap-vals!","clojure.core/symbol","clojure.core/symbol?","clojure.core/tagged-literal","clojure.core/tagged-literal?","clojure.core/take","clojure.core/take-last","clojure.core/take-nth","clojure.core/take-while","clojure.core/tap>","clojure.core/test","clojure.core/the-ns","clojure.core/thread-bound?","clojure.core/to-array","clojure.core/to-array-2d","clojure.core/trampoline","clojure.core/transduce","clojure.core/transient","clojure.core/tree-seq","clojure.core/true?","clojure.core/type","clojure.core/unchecked-add","clojure.core/unchecked-add-int","clojure.core/unchecked-byte","clojure.core/unchecked-char","clojure.core/unchecked-dec","clojure.core/unchecked-dec-int","clojure.core/unchecked-divide-int","clojure.core/unchecked-double","clojure.core/unchecked-float","clojure.core/unchecked-inc","clojure.core/unchecked-inc-int","clojure.core/unchecked-int","clojure.core/unchecked-long","clojure.core/unchecked-multiply","clojure.core/unchecked-multiply-int","clojure.core/unchecked-negate","clojure.core/unchecked-negate-int","clojure.core/unchecked-remainder-int","clojure.core/unchecked-short","clojure.core/unchecked-subtract","clojure.core/unchecked-subtract-int","clojure.core/underive","clojure.core/unreduced","clojure.core/unsigned-bit-shift-right","clojure.core/update","clojure.core/update-in","clojure.core/update-proxy","clojure.core/uri?","clojure.core/use","clojure.core/uuid?","clojure.core/val","clojure.core/vals","clojure.core/var-get","clojure.core/var-set","clojure.core/var?","clojure.core/vary-meta","clojure.core/vec","clojure.core/vector","clojure.core/vector-of","clojure.core/vector?","clojure.core/volatile!","clojure.core/volatile?","clojure.core/vreset!","clojure.core/with-bindings*","clojure.core/with-meta","clojure.core/with-redefs-fn","clojure.core/xml-seq","clojure.core/zero?","clojure.core/zipmap","coll?","commute","comp","comparator","compare","compare-and-set!","compile","complement","completing","concat","conj","conj!","cons","constantly","construct-proxy","contains?","count","counted?","create-ns","create-struct","cycle","dec","dec'","decimal?","dedupe","delay?","deliver","denominator","deref","derive","descendants","destructure","disj","disj!","dissoc","dissoc!","distinct","distinct?","doall","dorun","double","double-array","double?","doubles","drop","drop-last","drop-while","eduction","empty","empty?","ensure","ensure-reduced","enumeration-seq","error-handler","error-mode","eval","even?","every-pred","every?","ex-cause","ex-data","ex-info","ex-message","extend","extenders","extends?","false?","ffirst","file-seq","filter","filterv","find","find-keyword","find-ns","find-protocol-impl","find-protocol-method","find-var","first","flatten","float","float-array","float?","floats","flush","fn?","fnext","fnil","force","format","frequencies","future-call","future-cancel","future-cancelled?","future-done?","future?","gensym","get","get-in","get-method","get-proxy-class","get-thread-bindings","get-validator","group-by","halt-when","hash","hash-combine","hash-map","hash-ordered-coll","hash-set","hash-unordered-coll","ident?","identical?","identity","ifn?","in-ns","inc","inc'","indexed?","init-proxy","inst-ms","inst-ms*","inst?","instance?","int","int-array","int?","integer?","interleave","intern","interpose","into","into-array","ints","isa?","iterate","iterator-seq","juxt","keep","keep-indexed","key","keys","keyword","keyword?","last","line-seq","list","list*","list?","load","load-file","load-reader","load-string","loaded-libs","long","long-array","longs","macroexpand","macroexpand-1","make-array","make-hierarchy","map","map-entry?","map-indexed","map?","mapcat","mapv","max","max-key","memoize","merge","merge-with","meta","method-sig","methods","min","min-key","mix-collection-hash","mod","munge","name","namespace","namespace-munge","nat-int?","neg-int?","neg?","newline","next","nfirst","nil?","nnext","not","not-any?","not-empty","not-every?","not=","ns-aliases","ns-imports","ns-interns","ns-map","ns-name","ns-publics","ns-refers","ns-resolve","ns-unalias","ns-unmap","nth","nthnext","nthrest","num","number?","numerator","object-array","odd?","parents","partial","partition","partition-all","partition-by","pcalls","peek","persistent!","pmap","pop","pop!","pop-thread-bindings","pos-int?","pos?","pr","pr-str","prefer-method","prefers","print","print-ctor","print-dup","print-method","print-simple","print-str","printf","println","println-str","prn","prn-str","promise","proxy-call-with-super","proxy-mappings","proxy-name","push-thread-bindings","qualified-ident?","qualified-keyword?","qualified-symbol?","quot","rand","rand-int","rand-nth","random-sample","range","ratio?","rational?","rationalize","re-find","re-groups","re-matcher","re-matches","re-pattern","re-seq","read","read+string","read-line","read-string","reader-conditional","reader-conditional?","realized?","record?","reduce","reduce-kv","reduced","reduced?","reductions","ref","ref-history-count","ref-max-history","ref-min-history","ref-set","refer","release-pending-sends","rem","remove","remove-all-methods","remove-method","remove-ns","remove-tap","remove-watch","repeat","repeatedly","replace","replicate","require","requiring-resolve","reset!","reset-meta!","reset-vals!","resolve","rest","restart-agent","resultset-seq","reverse","reversible?","rseq","rsubseq","run!","satisfies?","second","select-keys","send","send-off","send-via","seq","seq?","seqable?","seque","sequence","sequential?","set","set-agent-send-executor!","set-agent-send-off-executor!","set-error-handler!","set-error-mode!","set-validator!","set?","short","short-array","shorts","shuffle","shutdown-agents","simple-ident?","simple-keyword?","simple-symbol?","slurp","some","some-fn","some?","sort","sort-by","sorted-map","sorted-map-by","sorted-set","sorted-set-by","sorted?","special-symbol?","spit","split-at","split-with","str","string?","struct","struct-map","subs","subseq","subvec","supers","swap!","swap-vals!","symbol","symbol?","tagged-literal","tagged-literal?","take","take-last","take-nth","take-while","tap>","test","the-ns","thread-bound?","to-array","to-array-2d","trampoline","transduce","transient","tree-seq","true?","type","unchecked-add","unchecked-add-int","unchecked-byte","unchecked-char","unchecked-dec","unchecked-dec-int","unchecked-divide-int","unchecked-double","unchecked-float","unchecked-inc","unchecked-inc-int","unchecked-int","unchecked-long","unchecked-multiply","unchecked-multiply-int","unchecked-negate","unchecked-negate-int","unchecked-remainder-int","unchecked-short","unchecked-subtract","unchecked-subtract-int","underive","unreduced","unsigned-bit-shift-right","update","update-in","update-proxy","uri?","use","uuid?","val","vals","var-get","var-set","var?","vary-meta","vec","vector","vector-of","vector?","volatile!","volatile?","vreset!","with-bindings*","with-meta","with-redefs-fn","xml-seq","zero?","zipmap"] \ , 'clojureMacro': ["->","->>","..","amap","and","areduce","as->","assert","binding","bound-fn","clojure.core/->","clojure.core/->>","clojure.core/..","clojure.core/amap","clojure.core/and","clojure.core/areduce","clojure.core/as->","clojure.core/assert","clojure.core/binding","clojure.core/bound-fn","clojure.core/comment","clojure.core/declare","clojure.core/delay","clojure.core/dosync","clojure.core/doto","clojure.core/extend-protocol","clojure.core/extend-type","clojure.core/for","clojure.core/future","clojure.core/gen-class","clojure.core/gen-interface","clojure.core/import","clojure.core/io!","clojure.core/lazy-cat","clojure.core/lazy-seq","clojure.core/letfn","clojure.core/locking","clojure.core/memfn","clojure.core/ns","clojure.core/or","clojure.core/proxy","clojure.core/proxy-super","clojure.core/pvalues","clojure.core/refer-clojure","clojure.core/reify","clojure.core/some->","clojure.core/some->>","clojure.core/sync","clojure.core/time","clojure.core/vswap!","clojure.core/with-bindings","clojure.core/with-in-str","clojure.core/with-loading-context","clojure.core/with-local-vars","clojure.core/with-open","clojure.core/with-out-str","clojure.core/with-precision","clojure.core/with-redefs","comment","declare","delay","dosync","doto","extend-protocol","extend-type","for","future","gen-class","gen-interface","import","io!","lazy-cat","lazy-seq","letfn","locking","memfn","ns","or","proxy","proxy-super","pvalues","refer-clojure","reify","some->","some->>","sync","time","vswap!","with-bindings","with-in-str","with-loading-context","with-local-vars","with-open","with-out-str","with-precision","with-redefs"] \ , 'clojureRepeat': ["clojure.core/doseq","clojure.core/dotimes","clojure.core/while","doseq","dotimes","while"] \ , 'clojureSpecial': [".","clojure.core/fn","clojure.core/let","clojure.core/loop","def","do","fn","if","let","loop","monitor-enter","monitor-exit","new","quote","recur","set!","var"] @@ -68,40 +68,23 @@ delfunction s:syntax_keyword " * Must not end in a : or / " * Must not have two adjacent colons except at the beginning " * Must not contain any reader metacharacters except for ' and # -syntax match clojureKeyword "\v<:{1,2}%([^ \n\r\t()\[\]{}";@^`~\\%/]+/)*[^ \n\r\t()\[\]{}";@^`~\\%/]+:@<!>" +syntax match clojureKeyword "\v<:{1,2}([^ \n\r\t()\[\]{}";@^`~\\/]+/)*[^ \n\r\t()\[\]{}";@^`~\\/]+:@1<!>" syntax match clojureStringEscape "\v\\%([\\btnfr"]|u\x{4}|[0-3]\o{2}|\o{1,2})" contained syntax region clojureString matchgroup=clojureStringDelimiter start=/"/ skip=/\\\\\|\\"/ end=/"/ contains=clojureStringEscape,@Spell -syntax match clojureCharacter "\\." -syntax match clojureCharacter "\\o\%([0-3]\o\{2\}\|\o\{1,2\}\)" -syntax match clojureCharacter "\\u\x\{4\}" -syntax match clojureCharacter "\\space" -syntax match clojureCharacter "\\tab" -syntax match clojureCharacter "\\newline" -syntax match clojureCharacter "\\return" -syntax match clojureCharacter "\\backspace" -syntax match clojureCharacter "\\formfeed" +syntax match clojureCharacter "\v\\%(o%([0-3]\o{2}|\o{1,2})|u\x{4}|newline|tab|space|return|backspace|formfeed|.)" -syntax match clojureSymbol "\v%([a-zA-Z!$&*_+=|<.>?-]|[^\x00-\x7F])+%(:?%([a-zA-Z0-9!#$%&*_+=|'<.>/?-]|[^\x00-\x7F]))*[#:]@<!" +syntax match clojureSymbol "\v%([a-zA-Z!$&*_+=|<.>?-]|[^\x00-\x7F])+%(:?%([a-zA-Z0-9!#$%&*_+=|'<.>/?-]|[^\x00-\x7F]))*[#:]@1<!" -let s:radix_chars = "0123456789abcdefghijklmnopqrstuvwxyz" -for s:radix in range(2, 36) - execute 'syntax match clojureNumber "\v\c<[-+]?' . s:radix . 'r[' . strpart(s:radix_chars, 0, s:radix) . ']+>"' -endfor -unlet! s:radix_chars s:radix - -syntax match clojureNumber "\v<[-+]?%(0\o*|0x\x+|[1-9]\d*)N?>" -syntax match clojureNumber "\v<[-+]?%(0|[1-9]\d*|%(0|[1-9]\d*)\.\d*)%(M|[eE][-+]?\d+)?>" -syntax match clojureNumber "\v<[-+]?%(0|[1-9]\d*)/%(0|[1-9]\d*)>" +" NB. Correct matching of radix literals was removed for better performance. +syntax match clojureNumber "\v<[-+]?%(%([2-9]|[12]\d|3[0-6])[rR][[:alnum:]]+|%(0\o*|0x\x+|[1-9]\d*)N?|%(0|[1-9]\d*|%(0|[1-9]\d*)\.\d*)%(M|[eE][-+]?\d+)?|%(0|[1-9]\d*)/%(0|[1-9]\d*))>" syntax match clojureVarArg "&" -syntax match clojureQuote "'" -syntax match clojureQuote "`" -syntax match clojureUnquote "\~" -syntax match clojureUnquote "\~@" +syntax match clojureQuote "\v['`]" +syntax match clojureUnquote "\v\~\@?" syntax match clojureMeta "\^" syntax match clojureDeref "@" syntax match clojureDispatch "\v#[\^'=<_]?" @@ -114,8 +97,8 @@ syntax region clojureRegexpQuoted start=/\\Q/ms=e+1 skip=/\\\\\|\\"/ end=/\\E/me syntax region clojureRegexpQuote start=/\\Q/ skip=/\\\\\|\\"/ end=/\\E/ end=/"/me=s-1 contains=clojureRegexpQuoted keepend contained " -*- CHARACTER PROPERTY CLASSES -*- -" Generated from https://github.com/clojure-vim/clojure.vim/blob/f8594e7030cdfb0b7990ac92953c77a08a7220f0/clj/src/vim_clojure_static/generate.clj -" Java version 15.0.2 +" Generated from https://github.com/clojure-vim/clojure.vim/blob/62b215f079ce0f3834fd295c7a7f6bd8cc54bcc3/clj/src/vim_clojure_static/generate.clj +" Java version 17 syntax match clojureRegexpPosixCharClass "\v\\[pP]\{%(Cntrl|A%(l%(pha|num)|SCII)|Space|Graph|Upper|P%(rint|unct)|Blank|XDigit|Digit|Lower)\}" contained display syntax match clojureRegexpJavaCharClass "\v\\[pP]\{java%(Whitespace|JavaIdentifier%(Part|Start)|SpaceChar|Mirrored|TitleCase|I%(SOControl|de%(ographic|ntifierIgnorable))|D%(efined|igit)|U%(pperCase|nicodeIdentifier%(Part|Start))|L%(etter%(OrDigit)?|owerCase)|Alphabetic)\}" contained display syntax match clojureRegexpUnicodeCharClass "\v\\[pP]\{\cIs%(l%(owercase|etter)|hex%(digit|_digit)|w%(hite%(_space|space)|ord)|noncharacter%(_code_point|codepoint)|p%(rint|unctuation)|ideographic|graph|a%(l%(num|phabetic)|ssigned)|uppercase|join%(control|_control)|titlecase|blank|digit|control)\}" contained display @@ -134,14 +117,14 @@ syntax match clojureRegexpBoundary "[$^]" contained display syntax match clojureRegexpQuantifier "[?*+][?+]\=" contained display syntax match clojureRegexpQuantifier "\v\{\d+%(,|,\d+)?}\??" contained display syntax match clojureRegexpOr "|" contained display -syntax match clojureRegexpBackRef "\v\\%([1-9]\d*|k\<[a-zA-z]+\>)" contained display +syntax match clojureRegexpBackRef "\v\\%([1-9]\d*|k\<[[:alpha:]]+\>)" contained display " Mode modifiers, mode-modified spans, lookaround, regular and atomic " grouping, and named-capturing. syntax match clojureRegexpMod "\v\(@<=\?:" contained display syntax match clojureRegexpMod "\v\(@<=\?[xdsmiuU]*-?[xdsmiuU]+:?" contained display syntax match clojureRegexpMod "\v\(@<=\?%(\<?[=!]|\>)" contained display -syntax match clojureRegexpMod "\v\(@<=\?\<[a-zA-Z]+\>" contained display +syntax match clojureRegexpMod "\v\(@<=\?\<[[:alpha:]]+\>" contained display syntax region clojureRegexpGroup start="(" skip=/\\\\\|\\)/ end=")" matchgroup=clojureRegexpGroup contained contains=clojureRegexpMod,clojureRegexpQuantifier,clojureRegexpBoundary,clojureRegexpEscape,@clojureRegexpCharClasses syntax region clojureRegexp start=/\#"/ skip=/\\\\\|\\"/ end=/"/ contains=@clojureRegexpCharClasses,clojureRegexpEscape,clojureRegexpQuote,clojureRegexpBoundary,clojureRegexpQuantifier,clojureRegexpOr,clojureRegexpBackRef,clojureRegexpGroup keepend @@ -150,10 +133,24 @@ syntax keyword clojureCommentTodo contained FIXME XXX TODO BUG NOTE HACK FIXME: syntax match clojureComment ";.*$" contains=clojureCommentTodo,@Spell syntax match clojureComment "#!.*$" +syntax match clojureComment "," + +" Comment out discarded forms. <https://clojure.org/guides/weird_characters#_discard> +if exists('g:clojure_discard_macro') && g:clojure_discard_macro + syntax region clojureDiscard matchgroup=clojureDiscard start=/#_[ ,\t\n`'~]*/ end=/[, \t\n()\[\]{}";]/me=e-1 + syntax region clojureDiscard matchgroup=clojureDiscard start=/#_[ ,\t\n`'~]*"/ skip=/\\[\\"]/ end=/"/ + syntax region clojureDiscard matchgroup=clojureDiscard start=/#_[ ,\t\n`'~]*(/ end=/)/ contains=clojureDiscardForm + syntax region clojureDiscard matchgroup=clojureDiscard start=/#_[ ,\t\n`'~]*\[/ end=/\]/ contains=clojureDiscardForm + syntax region clojureDiscard matchgroup=clojureDiscard start=/#_[ ,\t\n`'~]*{/ end=/}/ contains=clojureDiscardForm + + syntax region clojureDiscardForm start="(" end=")" contained contains=clojureDiscardForm + syntax region clojureDiscardForm start="{" end="}" contained contains=clojureDiscardForm + syntax region clojureDiscardForm start="\[" end="\]" contained contains=clojureDiscardForm +endif " -*- TOP CLUSTER -*- -" Generated from https://github.com/clojure-vim/clojure.vim/blob/f8594e7030cdfb0b7990ac92953c77a08a7220f0/clj/src/vim_clojure_static/generate.clj -syntax cluster clojureTop contains=@Spell,clojureAnonArg,clojureBoolean,clojureCharacter,clojureComment,clojureCond,clojureConstant,clojureDefine,clojureDeref,clojureDispatch,clojureError,clojureException,clojureFunc,clojureKeyword,clojureMacro,clojureMap,clojureMeta,clojureNumber,clojureQuote,clojureRegexp,clojureRepeat,clojureSexp,clojureSpecial,clojureString,clojureSymbol,clojureUnquote,clojureVarArg,clojureVariable,clojureVector +" Generated from https://github.com/clojure-vim/clojure.vim/blob/62b215f079ce0f3834fd295c7a7f6bd8cc54bcc3/clj/src/vim_clojure_static/generate.clj +syntax cluster clojureTop contains=@Spell,clojureAnonArg,clojureBoolean,clojureCharacter,clojureComment,clojureCond,clojureConstant,clojureDefine,clojureDeref,clojureDiscard,clojureDispatch,clojureError,clojureException,clojureFunc,clojureKeyword,clojureMacro,clojureMap,clojureMeta,clojureNumber,clojureQuote,clojureRegexp,clojureRepeat,clojureSexp,clojureSpecial,clojureString,clojureSymbol,clojureUnquote,clojureVarArg,clojureVariable,clojureVector syntax region clojureSexp matchgroup=clojureParen start="(" end=")" contains=@clojureTop fold syntax region clojureVector matchgroup=clojureParen start="\[" end="]" contains=@clojureTop fold @@ -208,6 +205,8 @@ highlight default link clojureDispatch SpecialChar highlight default link clojureComment Comment highlight default link clojureCommentTodo Todo +highlight default link clojureDiscard clojureComment +highlight default link clojureDiscardForm clojureDiscard highlight default link clojureError Error diff --git a/runtime/syntax/debchangelog.vim b/runtime/syntax/debchangelog.vim index 93b03ae06d..79352c0827 100644 --- a/runtime/syntax/debchangelog.vim +++ b/runtime/syntax/debchangelog.vim @@ -3,7 +3,7 @@ " Maintainer: Debian Vim Maintainers " Former Maintainers: Gerfried Fuchs <alfie@ist.org> " Wichert Akkerman <wakkerma@debian.org> -" Last Change: 2021 Aug 03 +" Last Change: 2021 Oct 19 " URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/syntax/debchangelog.vim " Standard syntax initialization @@ -24,7 +24,8 @@ let s:supported = [ \ 'jessie', 'stretch', 'buster', 'bullseye', 'bookworm', \ 'trixie', 'sid', 'rc-buggy', \ - \ 'trusty', 'xenial', 'bionic', 'focal', 'hirsute', 'impish', 'devel' + \ 'trusty', 'xenial', 'bionic', 'focal', 'hirsute', 'impish', 'jammy', + \ 'devel' \ ] let s:unsupported = [ \ 'frozen', 'buzz', 'rex', 'bo', 'hamm', 'slink', 'potato', diff --git a/runtime/syntax/debsources.vim b/runtime/syntax/debsources.vim index 8aa96fcb58..4b4c497f18 100644 --- a/runtime/syntax/debsources.vim +++ b/runtime/syntax/debsources.vim @@ -2,7 +2,7 @@ " Language: Debian sources.list " Maintainer: Debian Vim Maintainers " Former Maintainer: Matthijs Mohlmann <matthijs@cacholong.nl> -" Last Change: 2021 Aug 03 +" Last Change: 2021 Oct 19 " URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/syntax/debsources.vim " Standard syntax initialization @@ -26,7 +26,8 @@ let s:supported = [ \ 'jessie', 'stretch', 'buster', 'bullseye', 'bookworm', \ 'trixie', 'sid', 'rc-buggy', \ - \ 'trusty', 'xenial', 'bionic', 'focal', 'hirsute', 'impish', 'devel' + \ 'trusty', 'xenial', 'bionic', 'focal', 'hirsute', 'impish', 'jammy', + \ 'devel' \ ] let s:unsupported = [ \ 'buzz', 'rex', 'bo', 'hamm', 'slink', 'potato', diff --git a/runtime/syntax/help_ru.vim b/runtime/syntax/help_ru.vim index 8fcd63a917..67df7e1240 100644 --- a/runtime/syntax/help_ru.vim +++ b/runtime/syntax/help_ru.vim @@ -1,12 +1,12 @@ " Vim syntax file " Language: Russian Vim program help files *.rux -" Maintainer: Restorer (restorers@users.sourceforge.net) +" Maintainer: Restorer (restorers@users.sourceforge.net DEFUNCT) " Last Change: 04 Aprl 2017 " " Проверяем язык локали и установки опции 'helplang' " Если не русский, то выходим из скрипта. -if ('ru' !~? v:lang || 'russian' !~? v:lang) && 'ru' !~? &helplang +if (v:lang !~? 'ru' || v:lang !~? 'russian') && &helplang !~? 'ru' finish endif diff --git a/runtime/syntax/meson.vim b/runtime/syntax/meson.vim index 7e6b565f19..0af0d776f8 100644 --- a/runtime/syntax/meson.vim +++ b/runtime/syntax/meson.vim @@ -3,7 +3,7 @@ " License: VIM License " Maintainer: Nirbheek Chauhan <nirbheek.chauhan@gmail.com> " Liam Beguin <liambeguin@gmail.com> -" Last Change: 2019 Oct 18 +" Last Change: 2021 Aug 16 " Credits: Zvezdan Petkovic <zpetkovic@acm.org> " Neil Schemenauer <nas@meson.ca> " Dmitry Vasiliev @@ -56,9 +56,11 @@ syn match mesonEscape "\\$" " Meson only supports integer numbers " http://mesonbuild.com/Syntax.html#numbers syn match mesonNumber "\<\d\+\>" +syn match mesonNumber "\<0x\x\+\>" +syn match mesonNumber "\<0o\o\+\>" " booleans -syn keyword mesonConstant false true +syn keyword mesonBoolean false true " Built-in functions syn keyword mesonBuiltin @@ -97,6 +99,7 @@ syn keyword mesonBuiltin \ install_headers \ install_man \ install_subdir + \ install_emptydir \ is_disabler \ is_variable \ jar @@ -118,6 +121,7 @@ syn keyword mesonBuiltin \ summary \ target_machine \ test + \ unset_variable \ vcs_tag \ warning \ range @@ -133,15 +137,15 @@ endif " The default highlight links. Can be overridden later. hi def link mesonStatement Statement hi def link mesonConditional Conditional -hi def link mesonRepeat Repeat +hi def link mesonRepeat Repeat hi def link mesonOperator Operator hi def link mesonComment Comment hi def link mesonTodo Todo -hi def link mesonString String -hi def link mesonEscape Special -hi def link mesonNumber Number +hi def link mesonString String +hi def link mesonEscape Special +hi def link mesonNumber Number hi def link mesonBuiltin Function -hi def link mesonConstant Number +hi def link mesonBoolean Boolean if exists("meson_space_error_higlight") hi def link mesonSpaceError Error endif diff --git a/runtime/syntax/nsis.vim b/runtime/syntax/nsis.vim index 3389771b78..3a73fe0989 100644 --- a/runtime/syntax/nsis.vim +++ b/runtime/syntax/nsis.vim @@ -1,9 +1,9 @@ " Vim syntax file -" Language: NSIS script, for version of NSIS 3.03 and later +" Language: NSIS script, for version of NSIS 3.08 and later " Maintainer: Ken Takata " URL: https://github.com/k-takata/vim-nsis " Previous Maintainer: Alex Jakushev <Alex.Jakushev@kemek.lt> -" Last Change: 2018-10-02 +" Last Change: 2020-10-18 " quit when a syntax file was already loaded if exists("b:current_syntax") @@ -97,6 +97,8 @@ syn match nsisSysVar "$RESOURCES_LOCALIZED" syn match nsisSysVar "$CDBURN_AREA" syn match nsisSysVar "$HWNDPARENT" syn match nsisSysVar "$PLUGINSDIR" +syn match nsisSysVar "$\%(USERTEMPLATES\|USERSTARTMENU\|USERSMPROGRAMS\|USERDESKTOP\)" +syn match nsisSysVar "$\%(COMMONTEMPLATES\|COMMONSTARTMENU\|COMMONSMPROGRAMS\|COMMONDESKTOP\|COMMONPROGRAMDATA\)" syn match nsisSysVar "$\\r" syn match nsisSysVar "$\\n" syn match nsisSysVar "$\\t" @@ -149,7 +151,7 @@ syn keyword nsisStatement contained Section nextgroup=nsisSectionOpt skipwhite syn region nsisSectionOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisSectionKwd syn match nsisSectionKwd contained "/o\>" -syn keyword nsisStatement contained SectionIn nextgroup=nsisSectionInOpt skipwhite +syn keyword nsisStatement contained SectionInstType SectionIn nextgroup=nsisSectionInOpt skipwhite syn region nsisSectionInOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisSectionInKwd syn keyword nsisSectionInKwd contained RO @@ -269,10 +271,22 @@ syn keyword nsisAttribute contained ManifestDPIAware nextgroup=nsisManifestDPIAw syn region nsisManifestDPIAwareOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisManifestDPIAwareKwd syn keyword nsisManifestDPIAwareKwd contained notset true false +syn keyword nsisAttribute contained ManifestLongPathAware nextgroup=nsisManifestLongPathAwareOpt skipwhite +syn region nsisManifestLongPathAwareOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisManifestLongPathAwareKwd +syn match nsisManifestLongPathAwareKwd contained "\<\%(notset\|true\|false\)\>" + syn keyword nsisAttribute contained ManifestSupportedOS nextgroup=nsisManifestSupportedOSOpt skipwhite syn region nsisManifestSupportedOSOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisManifestSupportedOSKwd syn match nsisManifestSupportedOSKwd contained "\<\%(none\|all\|WinVista\|Win7\|Win8\|Win8\.1\|Win10\)\>" +syn keyword nsisAttribute contained PEAddResource nextgroup=nsisPEAddResourceOpt skipwhite +syn region nsisPEAddResourceOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisPEAddResourceKwd +syn match nsisPEAddResourceKwd contained "/\%(OVERWRITE\|REPLACE\)\>" + +syn keyword nsisAttribute contained PERemoveResource nextgroup=nsisPERemoveResourceOpt skipwhite +syn region nsisPERemoveResourceOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisPERemoveResourceKwd +syn match nsisPERemoveResourceKwd contained "/NOERRORS\>" + syn keyword nsisAttribute contained RequestExecutionLevel nextgroup=nsisRequestExecutionLevelOpt skipwhite syn region nsisRequestExecutionLevelOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisRequestExecutionLevelKwd syn keyword nsisRequestExecutionLevelKwd contained none user highest admin @@ -353,7 +367,7 @@ syn keyword nsisInstruction contained ExpandEnvStrings ReadEnvStr syn keyword nsisInstruction contained DeleteRegKey nextgroup=nsisDeleteRegKeyOpt skipwhite syn region nsisDeleteRegKeyOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisDeleteRegKeyKwd,nsisRegistry -syn match nsisDeleteRegKeyKwd contained "/ifempty\>" +syn match nsisDeleteRegKeyKwd contained "/\%(ifempty\|ifnosubkeys\|ifnovalues\)\>" syn keyword nsisInstruction contained nextgroup=nsisRegistryOpt skipwhite \ DeleteRegValue EnumRegKey EnumRegValue ReadRegDWORD ReadRegStr WriteRegBin WriteRegDWORD WriteRegExpandStr WriteRegStr @@ -368,8 +382,8 @@ syn region nsisSetRegViewOpt contained start="" end="$" transparent keepend cont syn keyword nsisSetRegViewKwd contained default lastused "FUNCTIONS - general purpose (4.9.3) -syn keyword nsisInstruction contained CallInstDLL CreateDirectory GetDLLVersion -syn keyword nsisInstruction contained GetDLLVersionLocal GetFileTime GetFileTimeLocal +syn keyword nsisInstruction contained CallInstDLL CreateDirectory GetWinVer +syn keyword nsisInstruction contained GetFileTime GetFileTimeLocal GetKnownFolderPath syn keyword nsisInstruction contained GetTempFileName SearchPath RegDLL UnRegDLL syn keyword nsisInstruction contained CopyFiles nextgroup=nsisCopyFilesOpt skipwhite @@ -380,6 +394,10 @@ syn keyword nsisInstruction contained CreateShortcut nextgroup=nsisCreateShortcu syn region nsisCreateShortcutOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisCreateShortcutKwd syn match nsisCreateShortcutKwd contained "/NoWorkingDir\>" +syn keyword nsisInstruction contained GetDLLVersion GetDLLVersionLocal nextgroup=nsisGetDLLVersionOpt skipwhite +syn region nsisGetDLLVersionOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisGetDLLVersionKwd +syn match nsisGetDLLVersionKwd contained "/ProductVersion\>" + syn keyword nsisInstruction contained GetFullPathName nextgroup=nsisGetFullPathNameOpt skipwhite syn region nsisGetFullPathNameOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisGetFullPathNameKwd syn match nsisGetFullPathNameKwd contained "/SHORT\>" @@ -395,6 +413,7 @@ syn keyword nsisFileAttrib contained FILE_ATTRIBUTE_TEMPORARY syn keyword nsisInstruction contained Abort Call ClearErrors GetCurrentAddress syn keyword nsisInstruction contained GetFunctionAddress GetLabelAddress Goto syn keyword nsisInstruction contained IfAbort IfErrors IfFileExists IfRebootFlag IfSilent +syn keyword nsisInstruction contained IfShellVarContextAll IfRtlLanguage syn keyword nsisInstruction contained IntCmp IntCmpU Int64Cmp Int64CmpU IntPtrCmp IntPtrCmpU syn keyword nsisInstruction contained Return Quit SetErrors StrCmp StrCmpS @@ -460,6 +479,10 @@ syn keyword nsisInstruction contained CreateFont nextgroup=nsisFontOpt skipwhite syn keyword nsisInstruction contained nextgroup=nsisBooleanOpt skipwhite \ LockWindow SetAutoClose +syn keyword nsisInstruction contained LoadAndSetImage nextgroup=nsisLoadAndSetImageOpt skipwhite +syn region nsisLoadAndSetImageOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisLoadAndSetImageKwd +syn match nsisLoadAndSetImageKwd contained "/\%(EXERESOURCE\|STRINGID\|RESIZETOFIT\%(WIDTH\|HEIGHT\)\)\>" + syn keyword nsisInstruction contained SendMessage nextgroup=nsisSendMessageOpt skipwhite syn region nsisSendMessageOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisSendMessageKwd syn match nsisSendMessageKwd contained "/TIMEOUT\>" @@ -556,7 +579,7 @@ syn keyword nsisVerboseKwd contained push pop "PREPROCESSOR (5.4) syn match nsisDefine contained "!define\>" nextgroup=nsisDefineOpt skipwhite syn region nsisDefineOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisDefineKwd -syn match nsisDefineKwd contained "/\%(ifndef\|redef\|date\|utcdate\|math\|file\)\>" +syn match nsisDefineKwd contained "/\%(ifndef\|redef\|date\|utcdate\|file\|intfmt\|math\)\>" syn match nsisDefine contained "!undef\>" syn match nsisPreCondit contained "!ifdef\>" @@ -615,7 +638,10 @@ hi def link nsisInstTypeKwd Constant hi def link nsisLicenseBkColorKwd Constant hi def link nsisLicenseForceSelectionKwd Constant hi def link nsisManifestDPIAwareKwd Constant +hi def link nsisManifestLongPathAwareKwd Constant hi def link nsisManifestSupportedOSKwd Constant +hi def link nsisPEAddResourceKwd Constant +hi def link nsisPERemoveResourceKwd Constant hi def link nsisRequestExecutionLevelKwd Constant hi def link nsisShowInstDetailsKwd Constant hi def link nsisSilentInstallKwd Constant @@ -633,11 +659,13 @@ hi def link nsisWriteRegMultiStrKwd Constant hi def link nsisSetRegViewKwd Constant hi def link nsisCopyFilesKwd Constant hi def link nsisCreateShortcutKwd Constant +hi def link nsisGetDLLVersionKwd Constant hi def link nsisGetFullPathNameKwd Constant hi def link nsisFileAttrib Constant hi def link nsisMessageBox Constant hi def link nsisFileWriteUTF16LEKwd Constant hi def link nsisSetShellVarContextKwd Constant +hi def link nsisLoadAndSetImageKwd Constant hi def link nsisSendMessageKwd Constant hi def link nsisSetBrandingImageKwd Constant hi def link nsisSetDetailsViewKwd Constant diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim index 0ab9c0ad58..731a514cb2 100644 --- a/runtime/syntax/sh.vim +++ b/runtime/syntax/sh.vim @@ -2,8 +2,8 @@ " Language: shell (sh) Korn shell (ksh) bash (sh) " Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM> " Previous Maintainer: Lennart Schultz <Lennart.Schultz@ecmwf.int> -" Last Change: Feb 18, 2021 -" Version: 198 +" Last Change: Oct 26, 2021 +" Version: 199 " 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) and heredoc fixes from Felipe Contreras @@ -147,7 +147,7 @@ if exists("b:is_kornshell") || exists("b:is_bash") endif syn cluster shCommandSubList contains=shAlias,shArithmetic,shCmdParenRegion,shCommandSub,shComment,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 -" COMBAK: removing shEscape fromshDblQuoteList fails ksh04:43 +" COMBAK: removing shEscape from shDblQuoteList fails ksh04:43 syn cluster shDblQuoteList contains=shArithmetic,shCommandSub,shCommandSubBQ,shDeref,shDerefSimple,shPosnParm,shCtrlSeq,shSpecial,shSpecialDQ syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPSR,shDerefPPS syn cluster shDerefVarList contains=shDerefOffset,shDerefOp,shDerefVarArray,shDerefOpError @@ -401,7 +401,7 @@ endif syn match shComment "^\s*\zs#.*$" contains=@shCommentGroup syn match shComment "\s\zs#.*$" contains=@shCommentGroup syn match shComment contained "#.*$" contains=@shCommentGroup -syn match shQuickComment contained "#.*$" +syn match shQuickComment contained "#.*$" contains=@shCommentGroup syn match shBQComment contained "#.\{-}\ze`" contains=@shCommentGroup " Here Documents: {{{1 diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index f695a1a1bf..67756fa320 100644 --- a/runtime/syntax/vim.vim +++ b/runtime/syntax/vim.vim @@ -165,7 +165,6 @@ syn keyword vimCommand contained in syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=a\%[ppend]$" matchgroup=vimCommand end="^\.$"" syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=c\%[hange]$" matchgroup=vimCommand end="^\.$"" syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=i\%[nsert]$" matchgroup=vimCommand end="^\.$"" -syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=starti\%[nsert]$" matchgroup=vimCommand end="^\.$"" " Behave! {{{2 " ======= @@ -201,9 +200,9 @@ syn keyword vimAugroupKey contained aug[roup] " Operators: {{{2 " ========= syn cluster vimOperGroup contains=vimEnvvar,vimFunc,vimFuncVar,vimOper,vimOperParen,vimNumber,vimString,vimType,vimRegister,vimContinue,vim9Comment -syn match vimOper "\%#=1\(==\|!=\|>=\|<=\|=\~\|!\~\|>\|<\|=\)[?#]\{0,2}" skipwhite nextgroup=vimString,vimSpecFile -syn match vimOper "\(\<is\|\<isnot\)[?#]\{0,2}\>" skipwhite nextgroup=vimString,vimSpecFile syn match vimOper "||\|&&\|[-+.!]" skipwhite nextgroup=vimString,vimSpecFile +syn match vimOper "\%#=1\(==\|!=\|>=\|<=\|=\~\|!\~\|>\|<\|=\|!\~#\)[?#]\{0,2}" skipwhite nextgroup=vimString,vimSpecFile +syn match vimOper "\(\<is\|\<isnot\)[?#]\{0,2}\>" skipwhite nextgroup=vimString,vimSpecFile syn region vimOperParen matchgroup=vimParenSep start="(" end=")" contains=vimoperStar,@vimOperGroup syn region vimOperParen matchgroup=vimSep start="#\={" end="}" contains=@vimOperGroup nextgroup=vimVar,vimFuncVar if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_noopererror") @@ -368,7 +367,7 @@ syn match vimSetMod contained "&vim\=\|[!&?<]\|all&" " Let: {{{2 " === syn keyword vimLet let unl[et] skipwhite nextgroup=vimVar,vimFuncVar,vimLetHereDoc -VimFoldh syn region vimLetHereDoc matchgroup=vimLetHereDocStart start='=<<\s\+\%(trim\>\)\=\s*\z(\L\S*\)' matchgroup=vimLetHereDocStop end='^\s*\z1\s*$' contains=vimComment,vim9Comment +VimFoldh syn region vimLetHereDoc matchgroup=vimLetHereDocStart start='=<<\s\+\%(trim\>\)\=\s*\z(\L\S*\)' matchgroup=vimLetHereDocStop end='^\s*\z1\s*$' " Abbreviations: {{{2 " ============= diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index f37e4c9d37..2d2d46d1bd 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -89,11 +89,14 @@ CONFIG = { # Section ordering. 'section_order': [ 'vim.c', + 'vimscript.c', 'buffer.c', + 'extmark.c', 'window.c', 'win_config.c', 'tabpage.c', 'ui.c', + 'extmark.c', ], # List of files/directories for doxygen to read, separated by blanks 'files': os.path.join(base_dir, 'src/nvim/api'), @@ -163,6 +166,7 @@ CONFIG = { 'util.lua', 'log.lua', 'rpc.lua', + 'sync.lua', 'protocol.lua', ], 'files': ' '.join([ @@ -506,6 +510,11 @@ def render_node(n, text, prefix='', indent='', width=62): text += indent + prefix + result elif n.nodeName in ('para', 'heading'): for c in n.childNodes: + if (is_inline(c) + and '' != get_text(c).strip() + and text + and ' ' != text[-1]): + text += ' ' text += render_node(c, text, indent=indent, width=width) elif n.nodeName == 'itemizedlist': for c in n.childNodes: diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index d92480abb9..ac47f6aafd 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -183,7 +183,7 @@ assign_commit_details() { # Patch surgery preprocess_patch() { local file="$1" - local nvim="nvim -u NORC -i NONE --headless" + local nvim="nvim -u NONE -n -i NONE --headless" # Remove Filelist, README local na_files='Filelist\|README.*' @@ -683,7 +683,7 @@ review_commit() { msg_ok "Saved pull request diff to '${NVIM_SOURCE_DIR}/n${patch_file}'." CREATED_FILES+=("${NVIM_SOURCE_DIR}/n${patch_file}") - local nvim="nvim -u NORC -n -i NONE --headless" + local nvim="nvim -u NONE -n -i NONE --headless" 2>/dev/null $nvim --cmd 'set dir=/tmp' +'1,/^$/g/^ /-1join' +w +q "${NVIM_SOURCE_DIR}/n${patch_file}" local expected_commit_message diff --git a/src/mpack/lmpack.c b/src/mpack/lmpack.c index 24d27fd17a..87acf46592 100644 --- a/src/mpack/lmpack.c +++ b/src/mpack/lmpack.c @@ -34,7 +34,9 @@ #include "rpc.h" #define UNPACKER_META_NAME "mpack.Unpacker" +#define UNPACK_FN_NAME "decode" #define PACKER_META_NAME "mpack.Packer" +#define PACK_FN_NAME "encode" #define SESSION_META_NAME "mpack.Session" #define NIL_NAME "mpack.NIL" #define EMPTY_DICT_NAME "mpack.empty_dict" @@ -432,8 +434,8 @@ static int lmpack_unpacker_unpack_str(lua_State *L, Unpacker *unpacker, if (unpacker->unpacking) { return luaL_error(L, "Unpacker instance already working. Use another " - "Unpacker or the module's \"unpack\" function if you " - "need to unpack from the ext handler"); + "Unpacker or mpack." UNPACK_FN_NAME "() if you " + "need to " UNPACK_FN_NAME " from the ext handler"); } do { @@ -784,8 +786,8 @@ static int lmpack_packer_pack(lua_State *L) if (packer->packing) { return luaL_error(L, "Packer instance already working. Use another Packer " - "or the module's \"pack\" function if you need to " - "pack from the ext handler"); + "or mpack." PACK_FN_NAME "() if you need to " + PACK_FN_NAME " from the ext handler"); } do { @@ -1161,8 +1163,8 @@ static const luaL_reg mpack_functions[] = { {"Unpacker", lmpack_unpacker_new}, {"Packer", lmpack_packer_new}, {"Session", lmpack_session_new}, - {"unpack", lmpack_unpack}, - {"pack", lmpack_pack}, + {UNPACK_FN_NAME, lmpack_unpack}, + {PACK_FN_NAME, lmpack_pack}, {NULL, NULL} }; diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 9c6eafa2df..185d55daed 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -231,8 +231,6 @@ endfunction() set(use_git_version 0) if(NVIM_VERSION_MEDIUM) message(STATUS "NVIM_VERSION_MEDIUM: ${NVIM_VERSION_MEDIUM}") -elseif(${CMAKE_VERSION} VERSION_LESS "3.2.0") - message(STATUS "Skipping version-string generation (requires CMake 3.2.0+)") elseif(EXISTS ${PROJECT_SOURCE_DIR}/.git) find_program(GIT_EXECUTABLE git) if(GIT_EXECUTABLE) diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 31d44c68bf..4076a0d220 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -32,7 +32,6 @@ #include "nvim/misc1.h" #include "nvim/move.h" #include "nvim/ops.h" -#include "nvim/syntax.h" #include "nvim/undo.h" #include "nvim/vim.h" #include "nvim/window.h" @@ -247,7 +246,6 @@ Boolean nvim_buf_detach(uint64_t channel_id, Buffer buffer, Error *err) } void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, Error *err) - FUNC_API_LUA_ONLY { buf_T *buf = find_buffer_by_handle(buffer, err); if (!buf) { @@ -1163,10 +1161,12 @@ Boolean nvim_buf_del_mark(Buffer buffer, String name, Error *err) /// @param name Mark name /// @param line Line number /// @param col Column/row number +/// @param opts Optional parameters. Reserved for future use. /// @return true if the mark was set, else false. /// @see |nvim_buf_del_mark()| /// @see |nvim_buf_get_mark()| -Boolean nvim_buf_set_mark(Buffer buffer, String name, Integer line, Integer col, Error *err) +Boolean nvim_buf_set_mark(Buffer buffer, String name, Integer line, Integer col, Dictionary opts, + Error *err) FUNC_API_SINCE(8) { bool res = false; @@ -1239,720 +1239,6 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err) return rv; } -static Array extmark_to_array(ExtmarkInfo extmark, bool id, bool add_dict) -{ - Array rv = ARRAY_DICT_INIT; - if (id) { - ADD(rv, INTEGER_OBJ((Integer)extmark.mark_id)); - } - ADD(rv, INTEGER_OBJ(extmark.row)); - ADD(rv, INTEGER_OBJ(extmark.col)); - - if (add_dict) { - Dictionary dict = ARRAY_DICT_INIT; - - if (extmark.end_row >= 0) { - PUT(dict, "end_row", INTEGER_OBJ(extmark.end_row)); - PUT(dict, "end_col", INTEGER_OBJ(extmark.end_col)); - } - - if (extmark.decor) { - Decoration *decor = extmark.decor; - if (decor->hl_id) { - String name = cstr_to_string((const char *)syn_id2name(decor->hl_id)); - PUT(dict, "hl_group", STRING_OBJ(name)); - } - if (kv_size(decor->virt_text)) { - Array chunks = ARRAY_DICT_INIT; - for (size_t i = 0; i < decor->virt_text.size; i++) { - Array chunk = ARRAY_DICT_INIT; - VirtTextChunk *vtc = &decor->virt_text.items[i]; - ADD(chunk, STRING_OBJ(cstr_to_string(vtc->text))); - if (vtc->hl_id > 0) { - ADD(chunk, - STRING_OBJ(cstr_to_string((const char *)syn_id2name(vtc->hl_id)))); - } - ADD(chunks, ARRAY_OBJ(chunk)); - } - PUT(dict, "virt_text", ARRAY_OBJ(chunks)); - } - - PUT(dict, "priority", INTEGER_OBJ(decor->priority)); - } - - if (dict.size) { - ADD(rv, DICTIONARY_OBJ(dict)); - } - } - - return rv; -} - -/// Gets the position (0-indexed) of an extmark. -/// -/// @param buffer Buffer handle, or 0 for current buffer -/// @param ns_id Namespace id from |nvim_create_namespace()| -/// @param id Extmark id -/// @param opts Optional parameters. Keys: -/// - details: Whether to include the details dict -/// @param[out] err Error details, if any -/// @return 0-indexed (row, col) tuple or empty list () if extmark id was -/// absent -ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, - Integer id, Dictionary opts, - Error *err) - FUNC_API_SINCE(7) -{ - Array rv = ARRAY_DICT_INIT; - - buf_T *buf = find_buffer_by_handle(buffer, err); - - if (!buf) { - return rv; - } - - if (!ns_initialized((uint64_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); - return rv; - } - - bool details = false; - for (size_t i = 0; i < opts.size; i++) { - String k = opts.items[i].key; - Object *v = &opts.items[i].value; - if (strequal("details", k.data)) { - if (v->type == kObjectTypeBoolean) { - details = v->data.boolean; - } else if (v->type == kObjectTypeInteger) { - details = v->data.integer; - } else { - api_set_error(err, kErrorTypeValidation, "details is not an boolean"); - return rv; - } - } else { - api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); - return rv; - } - } - - - ExtmarkInfo extmark = extmark_from_id(buf, (uint64_t)ns_id, (uint64_t)id); - if (extmark.row < 0) { - return rv; - } - return extmark_to_array(extmark, false, details); -} - -/// Gets extmarks in "traversal order" from a |charwise| region defined by -/// buffer positions (inclusive, 0-indexed |api-indexing|). -/// -/// Region can be given as (row,col) tuples, or valid extmark ids (whose -/// positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1) -/// respectively, thus the following are equivalent: -/// -/// <pre> -/// nvim_buf_get_extmarks(0, my_ns, 0, -1, {}) -/// nvim_buf_get_extmarks(0, my_ns, [0,0], [-1,-1], {}) -/// </pre> -/// -/// If `end` is less than `start`, traversal works backwards. (Useful -/// with `limit`, to get the first marks prior to a given position.) -/// -/// Example: -/// -/// <pre> -/// local a = vim.api -/// local pos = a.nvim_win_get_cursor(0) -/// local ns = a.nvim_create_namespace('my-plugin') -/// -- Create new extmark at line 1, column 1. -/// local m1 = a.nvim_buf_set_extmark(0, ns, 0, 0, 0, {}) -/// -- Create new extmark at line 3, column 1. -/// local m2 = a.nvim_buf_set_extmark(0, ns, 0, 2, 0, {}) -/// -- Get extmarks only from line 3. -/// local ms = a.nvim_buf_get_extmarks(0, ns, {2,0}, {2,0}, {}) -/// -- Get all marks in this buffer + namespace. -/// local all = a.nvim_buf_get_extmarks(0, ns, 0, -1, {}) -/// print(vim.inspect(ms)) -/// </pre> -/// -/// @param buffer Buffer handle, or 0 for current buffer -/// @param ns_id Namespace id from |nvim_create_namespace()| -/// @param start Start of range: a 0-indexed (row, col) or valid extmark id -/// (whose position defines the bound). |api-indexing| -/// @param end End of range (inclusive): a 0-indexed (row, col) or valid -/// extmark id (whose position defines the bound). |api-indexing| -/// @param opts Optional parameters. Keys: -/// - limit: Maximum number of marks to return -/// - details Whether to include the details dict -/// @param[out] err Error details, if any -/// @return List of [extmark_id, row, col] tuples in "traversal order". -Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object end, Dictionary opts, - Error *err) - FUNC_API_SINCE(7) -{ - Array rv = ARRAY_DICT_INIT; - - buf_T *buf = find_buffer_by_handle(buffer, err); - if (!buf) { - return rv; - } - - if (!ns_initialized((uint64_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); - return rv; - } - - Integer limit = -1; - bool details = false; - - for (size_t i = 0; i < opts.size; i++) { - String k = opts.items[i].key; - Object *v = &opts.items[i].value; - if (strequal("limit", k.data)) { - if (v->type != kObjectTypeInteger) { - api_set_error(err, kErrorTypeValidation, "limit is not an integer"); - return rv; - } - limit = v->data.integer; - } else if (strequal("details", k.data)) { - if (v->type == kObjectTypeBoolean) { - details = v->data.boolean; - } else if (v->type == kObjectTypeInteger) { - details = v->data.integer; - } else { - api_set_error(err, kErrorTypeValidation, "details is not an boolean"); - return rv; - } - } else { - api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); - return rv; - } - } - - if (limit == 0) { - return rv; - } else if (limit < 0) { - limit = INT64_MAX; - } - - - bool reverse = false; - - int l_row; - colnr_T l_col; - if (!extmark_get_index_from_obj(buf, ns_id, start, &l_row, &l_col, err)) { - return rv; - } - - int u_row; - colnr_T u_col; - if (!extmark_get_index_from_obj(buf, ns_id, end, &u_row, &u_col, err)) { - return rv; - } - - if (l_row > u_row || (l_row == u_row && l_col > u_col)) { - reverse = true; - } - - - ExtmarkInfoArray marks = extmark_get(buf, (uint64_t)ns_id, l_row, l_col, - u_row, u_col, (int64_t)limit, reverse); - - for (size_t i = 0; i < kv_size(marks); i++) { - ADD(rv, ARRAY_OBJ(extmark_to_array(kv_A(marks, i), true, (bool)details))); - } - - kv_destroy(marks); - return rv; -} - -/// Creates or updates an extmark. -/// -/// To create a new extmark, pass id=0. The extmark id will be returned. -/// To move an existing mark, pass its id. -/// -/// It is also allowed to create a new mark by passing in a previously unused -/// id, but the caller must then keep track of existing and unused ids itself. -/// (Useful over RPC, to avoid waiting for the return value.) -/// -/// Using the optional arguments, it is possible to use this to highlight -/// a range of text, and also to associate virtual text to the mark. -/// -/// @param buffer Buffer handle, or 0 for current buffer -/// @param ns_id Namespace id from |nvim_create_namespace()| -/// @param line Line where to place the mark, 0-based. |api-indexing| -/// @param col Column where to place the mark, 0-based. |api-indexing| -/// @param opts Optional parameters. -/// - id : id of the extmark to edit. -/// - end_line : ending line of the mark, 0-based inclusive. -/// - end_col : ending col of the mark, 0-based exclusive. -/// - hl_group : name of the highlight group used to highlight -/// this mark. -/// - hl_eol : when true, for a multiline highlight covering the -/// EOL of a line, continue the highlight for the rest -/// of the screen line (just like for diff and -/// cursorline highlight). -/// - virt_text : virtual text to link to this mark. -/// A list of [text, highlight] tuples, each representing a -/// text chunk with specified highlight. `highlight` element -/// can either be a a single highlight group, or an array of -/// multiple highlight groups that will be stacked -/// (highest priority last). A highlight group can be supplied -/// either as a string or as an integer, the latter which -/// can be obtained using |nvim_get_hl_id_by_name|. -/// - virt_text_pos : position of virtual text. Possible values: -/// - "eol": right after eol character (default) -/// - "overlay": display over the specified column, without -/// shifting the underlying text. -/// - "right_align": display right aligned in the window. -/// - virt_text_win_col : position the virtual text at a fixed -/// window column (starting from the first -/// text column) -/// - virt_text_hide : hide the virtual text when the background -/// text is selected or hidden due to -/// horizontal scroll 'nowrap' -/// - hl_mode : control how highlights are combined with the -/// highlights of the text. Currently only affects -/// virt_text highlights, but might affect `hl_group` -/// in later versions. -/// - "replace": only show the virt_text color. This is the -/// default -/// - "combine": combine with background text color -/// - "blend": blend with background text color. -/// -/// - virt_lines : virtual lines to add next to this mark -/// This should be an array over lines, where each line in -/// turn is an array over [text, highlight] tuples. In -/// general, buffer and window options do not affect the -/// display of the text. In particular 'wrap' -/// and 'linebreak' options do not take effect, so -/// the number of extra screen lines will always match -/// the size of the array. However the 'tabstop' buffer -/// option is still used for hard tabs. By default lines are -/// placed below the buffer line containing the mark. -/// -/// Note: currently virtual lines are limited to one block -/// per buffer. Thus setting a new mark disables any previous -/// `virt_lines` decoration. However plugins should not rely -/// on this behaviour, as this limitation is planned to be -/// removed. -/// -/// - virt_lines_above: place virtual lines above instead. -/// - virt_lines_leftcol: Place extmarks in the leftmost -/// column of the window, bypassing -/// sign and number columns. -/// -/// - ephemeral : for use with |nvim_set_decoration_provider| -/// callbacks. The mark will only be used for the current -/// redraw cycle, and not be permantently stored in the -/// buffer. -/// - right_gravity : boolean that indicates the direction -/// the extmark will be shifted in when new text is inserted -/// (true for right, false for left). defaults to true. -/// - end_right_gravity : boolean that indicates the direction -/// the extmark end position (if it exists) will be shifted -/// in when new text is inserted (true for right, false -/// for left). Defaults to false. -/// - priority: a priority value for the highlight group. For -/// example treesitter highlighting uses a value of 100. -/// @param[out] err Error details, if any -/// @return Id of the created/updated extmark -Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer col, - Dict(set_extmark) *opts, Error *err) - FUNC_API_SINCE(7) -{ - Decoration decor = DECORATION_INIT; - - buf_T *buf = find_buffer_by_handle(buffer, err); - if (!buf) { - goto error; - } - - if (!ns_initialized((uint64_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); - goto error; - } - - uint64_t id = 0; - if (opts->id.type == kObjectTypeInteger && opts->id.data.integer > 0) { - id = (uint64_t)opts->id.data.integer; - } else if (HAS_KEY(opts->id)) { - api_set_error(err, kErrorTypeValidation, "id is not a positive integer"); - goto error; - } - - int line2 = -1; - if (opts->end_line.type == kObjectTypeInteger) { - Integer val = opts->end_line.data.integer; - if (val < 0 || val > buf->b_ml.ml_line_count) { - api_set_error(err, kErrorTypeValidation, "end_line value outside range"); - goto error; - } else { - line2 = (int)val; - } - } else if (HAS_KEY(opts->end_line)) { - api_set_error(err, kErrorTypeValidation, "end_line is not an integer"); - goto error; - } - - colnr_T col2 = -1; - if (opts->end_col.type == kObjectTypeInteger) { - Integer val = opts->end_col.data.integer; - if (val < 0 || val > MAXCOL) { - api_set_error(err, kErrorTypeValidation, "end_col value outside range"); - goto error; - } else { - col2 = (int)val; - } - } else if (HAS_KEY(opts->end_col)) { - api_set_error(err, kErrorTypeValidation, "end_col is not an integer"); - goto error; - } - - if (HAS_KEY(opts->hl_group)) { - decor.hl_id = object_to_hl_id(opts->hl_group, "hl_group", err); - if (ERROR_SET(err)) { - goto error; - } - } - - if (opts->virt_text.type == kObjectTypeArray) { - decor.virt_text = parse_virt_text(opts->virt_text.data.array, err, - &decor.virt_text_width); - if (ERROR_SET(err)) { - goto error; - } - } else if (HAS_KEY(opts->virt_text)) { - api_set_error(err, kErrorTypeValidation, "virt_text is not an Array"); - goto error; - } - - if (opts->virt_text_pos.type == kObjectTypeString) { - String str = opts->virt_text_pos.data.string; - if (strequal("eol", str.data)) { - decor.virt_text_pos = kVTEndOfLine; - } else if (strequal("overlay", str.data)) { - decor.virt_text_pos = kVTOverlay; - } else if (strequal("right_align", str.data)) { - decor.virt_text_pos = kVTRightAlign; - } else { - api_set_error(err, kErrorTypeValidation, "virt_text_pos: invalid value"); - goto error; - } - } else if (HAS_KEY(opts->virt_text_pos)) { - api_set_error(err, kErrorTypeValidation, "virt_text_pos is not a String"); - goto error; - } - - if (opts->virt_text_win_col.type == kObjectTypeInteger) { - decor.col = (int)opts->virt_text_win_col.data.integer; - decor.virt_text_pos = kVTWinCol; - } else if (HAS_KEY(opts->virt_text_win_col)) { - api_set_error(err, kErrorTypeValidation, - "virt_text_win_col is not a Number of the correct size"); - goto error; - } - -#define OPTION_TO_BOOL(target, name, val) \ - target = api_object_to_bool(opts-> name, #name, val, err); \ - if (ERROR_SET(err)) { \ - goto error; \ - } - - OPTION_TO_BOOL(decor.virt_text_hide, virt_text_hide, false); - OPTION_TO_BOOL(decor.hl_eol, hl_eol, false); - - if (opts->hl_mode.type == kObjectTypeString) { - String str = opts->hl_mode.data.string; - if (strequal("replace", str.data)) { - decor.hl_mode = kHlModeReplace; - } else if (strequal("combine", str.data)) { - decor.hl_mode = kHlModeCombine; - } else if (strequal("blend", str.data)) { - decor.hl_mode = kHlModeBlend; - } else { - api_set_error(err, kErrorTypeValidation, - "virt_text_pos: invalid value"); - goto error; - } - } else if (HAS_KEY(opts->hl_mode)) { - api_set_error(err, kErrorTypeValidation, "hl_mode is not a String"); - goto error; - } - - VirtLines virt_lines = KV_INITIAL_VALUE; - bool virt_lines_above = false; - bool virt_lines_leftcol = false; - - if (opts->virt_lines.type == kObjectTypeArray) { - Array a = opts->virt_lines.data.array; - for (size_t j = 0; j < a.size; j++) { - if (a.items[j].type != kObjectTypeArray) { - api_set_error(err, kErrorTypeValidation, "virt_text_line item is not an Array"); - goto error; - } - int dummig; - VirtText jtem = parse_virt_text(a.items[j].data.array, err, &dummig); - kv_push(virt_lines, jtem); - if (ERROR_SET(err)) { - goto error; - } - } - } else if (HAS_KEY(opts->virt_lines)) { - api_set_error(err, kErrorTypeValidation, "virt_lines is not an Array"); - goto error; - } - - OPTION_TO_BOOL(virt_lines_above, virt_lines_above, false); - OPTION_TO_BOOL(virt_lines_leftcol, virt_lines_leftcol, false); - - if (opts->priority.type == kObjectTypeInteger) { - Integer val = opts->priority.data.integer; - - if (val < 0 || val > UINT16_MAX) { - api_set_error(err, kErrorTypeValidation, "priority is not a valid value"); - goto error; - } - decor.priority = (DecorPriority)val; - } else if (HAS_KEY(opts->priority)) { - api_set_error(err, kErrorTypeValidation, "priority is not a Number of the correct size"); - goto error; - } - - bool right_gravity = true; - OPTION_TO_BOOL(right_gravity, right_gravity, true); - - // Only error out if they try to set end_right_gravity without - // setting end_col or end_line - if (line2 == -1 && col2 == -1 && HAS_KEY(opts->end_right_gravity)) { - api_set_error(err, kErrorTypeValidation, - "cannot set end_right_gravity without setting end_line or end_col"); - goto error; - } - - bool end_right_gravity = false; - OPTION_TO_BOOL(end_right_gravity, end_right_gravity, false); - - size_t len = 0; - - bool ephemeral = false; - OPTION_TO_BOOL(ephemeral, ephemeral, false); - - if (line < 0 || line > buf->b_ml.ml_line_count) { - api_set_error(err, kErrorTypeValidation, "line value outside range"); - goto error; - } else if (line < buf->b_ml.ml_line_count) { - len = ephemeral ? MAXCOL : STRLEN(ml_get_buf(buf, (linenr_T)line+1, false)); - } - - if (col == -1) { - col = (Integer)len; - } else if (col < -1 || col > (Integer)len) { - api_set_error(err, kErrorTypeValidation, "col value outside range"); - goto error; - } - - if (col2 >= 0) { - if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) { - len = ephemeral ? MAXCOL : STRLEN(ml_get_buf(buf, (linenr_T)line2 + 1, false)); - } else if (line2 == buf->b_ml.ml_line_count) { - // We are trying to add an extmark past final newline - len = 0; - } else { - // reuse len from before - line2 = (int)line; - } - if (col2 > (Integer)len) { - api_set_error(err, kErrorTypeValidation, "end_col value outside range"); - goto error; - } - } else if (line2 >= 0) { - col2 = 0; - } - - Decoration *d = NULL; - - if (ephemeral) { - d = &decor; - } else if (kv_size(decor.virt_text) - || decor.priority != DECOR_PRIORITY_BASE - || decor.hl_eol) { - // TODO(bfredl): this is a bit sketchy. eventually we should - // have predefined decorations for both marks/ephemerals - d = xcalloc(1, sizeof(*d)); - *d = decor; - } else if (decor.hl_id) { - d = decor_hl(decor.hl_id); - } - - // TODO(bfredl): synergize these two branches even more - if (ephemeral && decor_state.buf == buf) { - decor_add_ephemeral((int)line, (int)col, line2, col2, &decor); - } else { - if (ephemeral) { - api_set_error(err, kErrorTypeException, "not yet implemented"); - goto error; - } - - if (kv_size(virt_lines) && buf->b_virt_line_mark) { - mtpos_t pos = marktree_lookup(buf->b_marktree, buf->b_virt_line_mark, NULL); - clear_virt_lines(buf, pos.row); // handles pos.row == -1 - } - - uint64_t mark = extmark_set(buf, (uint64_t)ns_id, &id, (int)line, (colnr_T)col, - line2, col2, d, right_gravity, - end_right_gravity, kExtmarkNoUndo); - - if (kv_size(virt_lines)) { - buf->b_virt_lines = virt_lines; - buf->b_virt_line_mark = mark; - buf->b_virt_line_pos = -1; - buf->b_virt_line_above = virt_lines_above; - buf->b_virt_line_leftcol = virt_lines_leftcol; - redraw_buf_line_later(buf, MIN(buf->b_ml.ml_line_count, line+1+(virt_lines_above?0:1))); - } - } - - return (Integer)id; - -error: - clear_virttext(&decor.virt_text); - return 0; -} - -/// Removes an extmark. -/// -/// @param buffer Buffer handle, or 0 for current buffer -/// @param ns_id Namespace id from |nvim_create_namespace()| -/// @param id Extmark id -/// @param[out] err Error details, if any -/// @return true if the extmark was found, else false -Boolean nvim_buf_del_extmark(Buffer buffer, Integer ns_id, Integer id, Error *err) - FUNC_API_SINCE(7) -{ - buf_T *buf = find_buffer_by_handle(buffer, err); - - if (!buf) { - return false; - } - if (!ns_initialized((uint64_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); - return false; - } - - return extmark_del(buf, (uint64_t)ns_id, (uint64_t)id); -} - -/// Adds a highlight to buffer. -/// -/// Useful for plugins that 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. -/// -/// Namespaces are used for batch deletion/updating of a set of highlights. To -/// create a namespace, use |nvim_create_namespace()| which returns a namespace -/// id. Pass it in to this function as `ns_id` to add highlights to the -/// namespace. All highlights in the same namespace can then be cleared with -/// single call to |nvim_buf_clear_namespace()|. If the highlight never will be -/// deleted by an API call, pass `ns_id = -1`. -/// -/// As a shorthand, `ns_id = 0` can be used to create a new namespace for the -/// highlight, the allocated id is then returned. If `hl_group` is the empty -/// string no highlight is added, but a new `ns_id` is still returned. This is -/// supported for backwards compatibility, new code should use -/// |nvim_create_namespace()| to create a new empty namespace. -/// -/// @param buffer Buffer handle, or 0 for current buffer -/// @param ns_id namespace to use or -1 for ungrouped highlight -/// @param hl_group Name of the highlight group to use -/// @param line Line to highlight (zero-indexed) -/// @param col_start Start of (byte-indexed) column range to highlight -/// @param col_end End of (byte-indexed) column range to highlight, -/// or -1 to highlight to end of line -/// @param[out] err Error details, if any -/// @return The ns_id that was used -Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, Integer line, - Integer col_start, Integer col_end, Error *err) - FUNC_API_SINCE(1) -{ - buf_T *buf = find_buffer_by_handle(buffer, err); - if (!buf) { - return 0; - } - - if (line < 0 || line >= MAXLNUM) { - api_set_error(err, kErrorTypeValidation, "Line number outside range"); - return 0; - } - if (col_start < 0 || col_start > MAXCOL) { - api_set_error(err, kErrorTypeValidation, "Column value outside range"); - return 0; - } - if (col_end < 0 || col_end > MAXCOL) { - col_end = MAXCOL; - } - - uint64_t ns = src2ns(&ns_id); - - if (!(line < buf->b_ml.ml_line_count)) { - // safety check, we can't add marks outside the range - return ns_id; - } - - int hl_id = 0; - if (hl_group.size > 0) { - hl_id = syn_check_group(hl_group.data, (int)hl_group.size); - } else { - return ns_id; - } - - int end_line = (int)line; - if (col_end == MAXCOL) { - col_end = 0; - end_line++; - } - - extmark_set(buf, ns, NULL, - (int)line, (colnr_T)col_start, - end_line, (colnr_T)col_end, - decor_hl(hl_id), true, false, kExtmarkNoUndo); - return ns_id; -} - -/// Clears namespaced objects (highlights, extmarks, virtual text) from -/// a region. -/// -/// Lines are 0-indexed. |api-indexing| To clear the namespace in the entire -/// buffer, specify line_start=0 and line_end=-1. -/// -/// @param buffer Buffer handle, or 0 for current buffer -/// @param ns_id Namespace to clear, or -1 to clear all namespaces. -/// @param line_start Start of range of lines to clear -/// @param line_end End of range of lines to clear (exclusive) or -1 to clear -/// to end of buffer. -/// @param[out] err Error details, if any -void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start, Integer line_end, - Error *err) - FUNC_API_SINCE(5) -{ - buf_T *buf = find_buffer_by_handle(buffer, err); - if (!buf) { - return; - } - - if (line_start < 0 || line_start >= MAXLNUM) { - api_set_error(err, kErrorTypeValidation, "Line number outside range"); - return; - } - if (line_end < 0 || line_end > MAXLNUM) { - line_end = MAXLNUM; - } - extmark_clear(buf, (ns_id < 0 ? 0 : (uint64_t)ns_id), - (int)line_start, 0, - (int)line_end-1, MAXCOL); -} /// call a function with buffer as temporary current buffer /// @@ -2013,6 +1299,7 @@ Dictionary nvim__buf_stats(Buffer buffer, Error *err) // this exists to debug issues PUT(rv, "dirty_bytes", INTEGER_OBJ((Integer)buf->deleted_bytes)); PUT(rv, "dirty_bytes2", INTEGER_OBJ((Integer)buf->deleted_bytes2)); + PUT(rv, "virt_blocks", INTEGER_OBJ((Integer)buf->b_virt_line_blocks)); u_header_T *uhp = NULL; if (buf->b_u_curhead != NULL) { diff --git a/src/nvim/api/buffer.h b/src/nvim/api/buffer.h index 9aa898f7da..1c4a93a587 100644 --- a/src/nvim/api/buffer.h +++ b/src/nvim/api/buffer.h @@ -1,8 +1,6 @@ #ifndef NVIM_API_BUFFER_H #define NVIM_API_BUFFER_H -#include <stdint.h> - #include "nvim/api/private/defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c index 907d09e5b7..76b699800e 100644 --- a/src/nvim/api/deprecated.c +++ b/src/nvim/api/deprecated.c @@ -8,9 +8,11 @@ #include "nvim/api/buffer.h" #include "nvim/api/deprecated.h" +#include "nvim/api/extmark.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" +#include "nvim/api/vimscript.h" #include "nvim/extmark.h" #include "nvim/lua/executor.h" diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c new file mode 100644 index 0000000000..6f1fb15dac --- /dev/null +++ b/src/nvim/api/extmark.c @@ -0,0 +1,895 @@ +// 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> + +#include "nvim/api/extmark.h" +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/extmark.h" +#include "nvim/lua/executor.h" +#include "nvim/memline.h" +#include "nvim/screen.h" +#include "nvim/syntax.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "api/extmark.c.generated.h" +#endif + +void api_extmark_free_all_mem(void) +{ + String name; + handle_T id; + map_foreach(&namespace_ids, name, id, { + (void)id; + xfree(name.data); + }) + map_destroy(String, handle_T)(&namespace_ids); +} + +/// Creates a new \*namespace\* or gets an existing one. +/// +/// Namespaces are used for buffer highlights and virtual text, see +/// |nvim_buf_add_highlight()| and |nvim_buf_set_extmark()|. +/// +/// Namespaces can be named or anonymous. If `name` matches an existing +/// namespace, the associated id is returned. If `name` is an empty string +/// a new, anonymous namespace is created. +/// +/// @param name Namespace name or empty string +/// @return Namespace id +Integer nvim_create_namespace(String name) + FUNC_API_SINCE(5) +{ + handle_T id = map_get(String, handle_T)(&namespace_ids, name); + if (id > 0) { + return id; + } + id = next_namespace_id++; + if (name.size > 0) { + String name_alloc = copy_string(name); + map_put(String, handle_T)(&namespace_ids, name_alloc, id); + } + return (Integer)id; +} + +/// Gets existing, non-anonymous namespaces. +/// +/// @return dict that maps from names to namespace ids. +Dictionary nvim_get_namespaces(void) + FUNC_API_SINCE(5) +{ + Dictionary retval = ARRAY_DICT_INIT; + String name; + handle_T id; + + map_foreach(&namespace_ids, name, id, { + PUT(retval, name.data, INTEGER_OBJ(id)); + }) + + return retval; +} + +const char *describe_ns(NS ns_id) +{ + String name; + handle_T id; + map_foreach(&namespace_ids, name, id, { + if ((NS)id == ns_id && name.size) { + return name.data; + } + }) + return "(UNKNOWN PLUGIN)"; +} + +// Is the Namespace in use? +static bool ns_initialized(uint64_t ns) +{ + if (ns < 1) { + return false; + } + return ns < (uint64_t)next_namespace_id; +} + + +static Array extmark_to_array(ExtmarkInfo extmark, bool id, bool add_dict) +{ + Array rv = ARRAY_DICT_INIT; + if (id) { + ADD(rv, INTEGER_OBJ((Integer)extmark.mark_id)); + } + ADD(rv, INTEGER_OBJ(extmark.row)); + ADD(rv, INTEGER_OBJ(extmark.col)); + + if (add_dict) { + Dictionary dict = ARRAY_DICT_INIT; + + if (extmark.end_row >= 0) { + PUT(dict, "end_row", INTEGER_OBJ(extmark.end_row)); + PUT(dict, "end_col", INTEGER_OBJ(extmark.end_col)); + } + + if (extmark.decor) { + Decoration *decor = extmark.decor; + if (decor->hl_id) { + String name = cstr_to_string((const char *)syn_id2name(decor->hl_id)); + PUT(dict, "hl_group", STRING_OBJ(name)); + } + if (kv_size(decor->virt_text)) { + Array chunks = ARRAY_DICT_INIT; + for (size_t i = 0; i < decor->virt_text.size; i++) { + Array chunk = ARRAY_DICT_INIT; + VirtTextChunk *vtc = &decor->virt_text.items[i]; + ADD(chunk, STRING_OBJ(cstr_to_string(vtc->text))); + if (vtc->hl_id > 0) { + ADD(chunk, + STRING_OBJ(cstr_to_string((const char *)syn_id2name(vtc->hl_id)))); + } + ADD(chunks, ARRAY_OBJ(chunk)); + } + PUT(dict, "virt_text", ARRAY_OBJ(chunks)); + } + + PUT(dict, "priority", INTEGER_OBJ(decor->priority)); + } + + if (dict.size) { + ADD(rv, DICTIONARY_OBJ(dict)); + } + } + + return rv; +} + +/// Gets the position (0-indexed) of an extmark. +/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param ns_id Namespace id from |nvim_create_namespace()| +/// @param id Extmark id +/// @param opts Optional parameters. Keys: +/// - details: Whether to include the details dict +/// @param[out] err Error details, if any +/// @return 0-indexed (row, col) tuple or empty list () if extmark id was +/// absent +ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, + Integer id, Dictionary opts, + Error *err) + FUNC_API_SINCE(7) +{ + Array rv = ARRAY_DICT_INIT; + + buf_T *buf = find_buffer_by_handle(buffer, err); + + if (!buf) { + return rv; + } + + if (!ns_initialized((uint64_t)ns_id)) { + api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); + return rv; + } + + bool details = false; + for (size_t i = 0; i < opts.size; i++) { + String k = opts.items[i].key; + Object *v = &opts.items[i].value; + if (strequal("details", k.data)) { + if (v->type == kObjectTypeBoolean) { + details = v->data.boolean; + } else if (v->type == kObjectTypeInteger) { + details = v->data.integer; + } else { + api_set_error(err, kErrorTypeValidation, "details is not an boolean"); + return rv; + } + } else { + api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); + return rv; + } + } + + + ExtmarkInfo extmark = extmark_from_id(buf, (uint64_t)ns_id, (uint64_t)id); + if (extmark.row < 0) { + return rv; + } + return extmark_to_array(extmark, false, details); +} + +/// Gets extmarks in "traversal order" from a |charwise| region defined by +/// buffer positions (inclusive, 0-indexed |api-indexing|). +/// +/// Region can be given as (row,col) tuples, or valid extmark ids (whose +/// positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1) +/// respectively, thus the following are equivalent: +/// +/// <pre> +/// nvim_buf_get_extmarks(0, my_ns, 0, -1, {}) +/// nvim_buf_get_extmarks(0, my_ns, [0,0], [-1,-1], {}) +/// </pre> +/// +/// If `end` is less than `start`, traversal works backwards. (Useful +/// with `limit`, to get the first marks prior to a given position.) +/// +/// Example: +/// +/// <pre> +/// local a = vim.api +/// local pos = a.nvim_win_get_cursor(0) +/// local ns = a.nvim_create_namespace('my-plugin') +/// -- Create new extmark at line 1, column 1. +/// local m1 = a.nvim_buf_set_extmark(0, ns, 0, 0, 0, {}) +/// -- Create new extmark at line 3, column 1. +/// local m2 = a.nvim_buf_set_extmark(0, ns, 0, 2, 0, {}) +/// -- Get extmarks only from line 3. +/// local ms = a.nvim_buf_get_extmarks(0, ns, {2,0}, {2,0}, {}) +/// -- Get all marks in this buffer + namespace. +/// local all = a.nvim_buf_get_extmarks(0, ns, 0, -1, {}) +/// print(vim.inspect(ms)) +/// </pre> +/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param ns_id Namespace id from |nvim_create_namespace()| +/// @param start Start of range: a 0-indexed (row, col) or valid extmark id +/// (whose position defines the bound). |api-indexing| +/// @param end End of range (inclusive): a 0-indexed (row, col) or valid +/// extmark id (whose position defines the bound). |api-indexing| +/// @param opts Optional parameters. Keys: +/// - limit: Maximum number of marks to return +/// - details Whether to include the details dict +/// @param[out] err Error details, if any +/// @return List of [extmark_id, row, col] tuples in "traversal order". +Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object end, Dictionary opts, + Error *err) + FUNC_API_SINCE(7) +{ + Array rv = ARRAY_DICT_INIT; + + buf_T *buf = find_buffer_by_handle(buffer, err); + if (!buf) { + return rv; + } + + if (!ns_initialized((uint64_t)ns_id)) { + api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); + return rv; + } + + Integer limit = -1; + bool details = false; + + for (size_t i = 0; i < opts.size; i++) { + String k = opts.items[i].key; + Object *v = &opts.items[i].value; + if (strequal("limit", k.data)) { + if (v->type != kObjectTypeInteger) { + api_set_error(err, kErrorTypeValidation, "limit is not an integer"); + return rv; + } + limit = v->data.integer; + } else if (strequal("details", k.data)) { + if (v->type == kObjectTypeBoolean) { + details = v->data.boolean; + } else if (v->type == kObjectTypeInteger) { + details = v->data.integer; + } else { + api_set_error(err, kErrorTypeValidation, "details is not an boolean"); + return rv; + } + } else { + api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); + return rv; + } + } + + if (limit == 0) { + return rv; + } else if (limit < 0) { + limit = INT64_MAX; + } + + + bool reverse = false; + + int l_row; + colnr_T l_col; + if (!extmark_get_index_from_obj(buf, ns_id, start, &l_row, &l_col, err)) { + return rv; + } + + int u_row; + colnr_T u_col; + if (!extmark_get_index_from_obj(buf, ns_id, end, &u_row, &u_col, err)) { + return rv; + } + + if (l_row > u_row || (l_row == u_row && l_col > u_col)) { + reverse = true; + } + + + ExtmarkInfoArray marks = extmark_get(buf, (uint64_t)ns_id, l_row, l_col, + u_row, u_col, (int64_t)limit, reverse); + + for (size_t i = 0; i < kv_size(marks); i++) { + ADD(rv, ARRAY_OBJ(extmark_to_array(kv_A(marks, i), true, (bool)details))); + } + + kv_destroy(marks); + return rv; +} + +/// Creates or updates an extmark. +/// +/// To create a new extmark, pass id=0. The extmark id will be returned. +/// To move an existing mark, pass its id. +/// +/// It is also allowed to create a new mark by passing in a previously unused +/// id, but the caller must then keep track of existing and unused ids itself. +/// (Useful over RPC, to avoid waiting for the return value.) +/// +/// Using the optional arguments, it is possible to use this to highlight +/// a range of text, and also to associate virtual text to the mark. +/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param ns_id Namespace id from |nvim_create_namespace()| +/// @param line Line where to place the mark, 0-based. |api-indexing| +/// @param col Column where to place the mark, 0-based. |api-indexing| +/// @param opts Optional parameters. +/// - id : id of the extmark to edit. +/// - end_line : ending line of the mark, 0-based inclusive. +/// - end_col : ending col of the mark, 0-based exclusive. +/// - hl_group : name of the highlight group used to highlight +/// this mark. +/// - hl_eol : when true, for a multiline highlight covering the +/// EOL of a line, continue the highlight for the rest +/// of the screen line (just like for diff and +/// cursorline highlight). +/// - virt_text : virtual text to link to this mark. +/// A list of [text, highlight] tuples, each representing a +/// text chunk with specified highlight. `highlight` element +/// can either be a a single highlight group, or an array of +/// multiple highlight groups that will be stacked +/// (highest priority last). A highlight group can be supplied +/// either as a string or as an integer, the latter which +/// can be obtained using |nvim_get_hl_id_by_name|. +/// - virt_text_pos : position of virtual text. Possible values: +/// - "eol": right after eol character (default) +/// - "overlay": display over the specified column, without +/// shifting the underlying text. +/// - "right_align": display right aligned in the window. +/// - virt_text_win_col : position the virtual text at a fixed +/// window column (starting from the first +/// text column) +/// - virt_text_hide : hide the virtual text when the background +/// text is selected or hidden due to +/// horizontal scroll 'nowrap' +/// - hl_mode : control how highlights are combined with the +/// highlights of the text. Currently only affects +/// virt_text highlights, but might affect `hl_group` +/// in later versions. +/// - "replace": only show the virt_text color. This is the +/// default +/// - "combine": combine with background text color +/// - "blend": blend with background text color. +/// +/// - virt_lines : virtual lines to add next to this mark +/// This should be an array over lines, where each line in +/// turn is an array over [text, highlight] tuples. In +/// general, buffer and window options do not affect the +/// display of the text. In particular 'wrap' +/// and 'linebreak' options do not take effect, so +/// the number of extra screen lines will always match +/// the size of the array. However the 'tabstop' buffer +/// option is still used for hard tabs. By default lines are +/// placed below the buffer line containing the mark. +/// +/// - virt_lines_above: place virtual lines above instead. +/// - virt_lines_leftcol: Place extmarks in the leftmost +/// column of the window, bypassing +/// sign and number columns. +/// +/// - ephemeral : for use with |nvim_set_decoration_provider| +/// callbacks. The mark will only be used for the current +/// redraw cycle, and not be permantently stored in the +/// buffer. +/// - right_gravity : boolean that indicates the direction +/// the extmark will be shifted in when new text is inserted +/// (true for right, false for left). defaults to true. +/// - end_right_gravity : boolean that indicates the direction +/// the extmark end position (if it exists) will be shifted +/// in when new text is inserted (true for right, false +/// for left). Defaults to false. +/// - priority: a priority value for the highlight group. For +/// example treesitter highlighting uses a value of 100. +/// @param[out] err Error details, if any +/// @return Id of the created/updated extmark +Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer col, + Dict(set_extmark) *opts, Error *err) + FUNC_API_SINCE(7) +{ + Decoration decor = DECORATION_INIT; + + buf_T *buf = find_buffer_by_handle(buffer, err); + if (!buf) { + goto error; + } + + if (!ns_initialized((uint64_t)ns_id)) { + api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); + goto error; + } + + uint64_t id = 0; + if (opts->id.type == kObjectTypeInteger && opts->id.data.integer > 0) { + id = (uint64_t)opts->id.data.integer; + } else if (HAS_KEY(opts->id)) { + api_set_error(err, kErrorTypeValidation, "id is not a positive integer"); + goto error; + } + + int line2 = -1; + if (opts->end_line.type == kObjectTypeInteger) { + Integer val = opts->end_line.data.integer; + if (val < 0 || val > buf->b_ml.ml_line_count) { + api_set_error(err, kErrorTypeValidation, "end_line value outside range"); + goto error; + } else { + line2 = (int)val; + } + } else if (HAS_KEY(opts->end_line)) { + api_set_error(err, kErrorTypeValidation, "end_line is not an integer"); + goto error; + } + + colnr_T col2 = -1; + if (opts->end_col.type == kObjectTypeInteger) { + Integer val = opts->end_col.data.integer; + if (val < 0 || val > MAXCOL) { + api_set_error(err, kErrorTypeValidation, "end_col value outside range"); + goto error; + } else { + col2 = (int)val; + } + } else if (HAS_KEY(opts->end_col)) { + api_set_error(err, kErrorTypeValidation, "end_col is not an integer"); + goto error; + } + + if (HAS_KEY(opts->hl_group)) { + decor.hl_id = object_to_hl_id(opts->hl_group, "hl_group", err); + if (ERROR_SET(err)) { + goto error; + } + } + + if (opts->virt_text.type == kObjectTypeArray) { + decor.virt_text = parse_virt_text(opts->virt_text.data.array, err, + &decor.virt_text_width); + if (ERROR_SET(err)) { + goto error; + } + } else if (HAS_KEY(opts->virt_text)) { + api_set_error(err, kErrorTypeValidation, "virt_text is not an Array"); + goto error; + } + + if (opts->virt_text_pos.type == kObjectTypeString) { + String str = opts->virt_text_pos.data.string; + if (strequal("eol", str.data)) { + decor.virt_text_pos = kVTEndOfLine; + } else if (strequal("overlay", str.data)) { + decor.virt_text_pos = kVTOverlay; + } else if (strequal("right_align", str.data)) { + decor.virt_text_pos = kVTRightAlign; + } else { + api_set_error(err, kErrorTypeValidation, "virt_text_pos: invalid value"); + goto error; + } + } else if (HAS_KEY(opts->virt_text_pos)) { + api_set_error(err, kErrorTypeValidation, "virt_text_pos is not a String"); + goto error; + } + + if (opts->virt_text_win_col.type == kObjectTypeInteger) { + decor.col = (int)opts->virt_text_win_col.data.integer; + decor.virt_text_pos = kVTWinCol; + } else if (HAS_KEY(opts->virt_text_win_col)) { + api_set_error(err, kErrorTypeValidation, + "virt_text_win_col is not a Number of the correct size"); + goto error; + } + +#define OPTION_TO_BOOL(target, name, val) \ + target = api_object_to_bool(opts->name, #name, val, err); \ + if (ERROR_SET(err)) { \ + goto error; \ + } + + OPTION_TO_BOOL(decor.virt_text_hide, virt_text_hide, false); + OPTION_TO_BOOL(decor.hl_eol, hl_eol, false); + + if (opts->hl_mode.type == kObjectTypeString) { + String str = opts->hl_mode.data.string; + if (strequal("replace", str.data)) { + decor.hl_mode = kHlModeReplace; + } else if (strequal("combine", str.data)) { + decor.hl_mode = kHlModeCombine; + } else if (strequal("blend", str.data)) { + decor.hl_mode = kHlModeBlend; + } else { + api_set_error(err, kErrorTypeValidation, + "virt_text_pos: invalid value"); + goto error; + } + } else if (HAS_KEY(opts->hl_mode)) { + api_set_error(err, kErrorTypeValidation, "hl_mode is not a String"); + goto error; + } + + bool virt_lines_leftcol = false; + OPTION_TO_BOOL(virt_lines_leftcol, virt_lines_leftcol, false); + + if (opts->virt_lines.type == kObjectTypeArray) { + Array a = opts->virt_lines.data.array; + for (size_t j = 0; j < a.size; j++) { + if (a.items[j].type != kObjectTypeArray) { + api_set_error(err, kErrorTypeValidation, "virt_text_line item is not an Array"); + goto error; + } + int dummig; + VirtText jtem = parse_virt_text(a.items[j].data.array, err, &dummig); + kv_push(decor.virt_lines, ((struct virt_line){ jtem, virt_lines_leftcol })); + if (ERROR_SET(err)) { + goto error; + } + } + } else if (HAS_KEY(opts->virt_lines)) { + api_set_error(err, kErrorTypeValidation, "virt_lines is not an Array"); + goto error; + } + + + OPTION_TO_BOOL(decor.virt_lines_above, virt_lines_above, false); + + if (opts->priority.type == kObjectTypeInteger) { + Integer val = opts->priority.data.integer; + + if (val < 0 || val > UINT16_MAX) { + api_set_error(err, kErrorTypeValidation, "priority is not a valid value"); + goto error; + } + decor.priority = (DecorPriority)val; + } else if (HAS_KEY(opts->priority)) { + api_set_error(err, kErrorTypeValidation, "priority is not a Number of the correct size"); + goto error; + } + + bool right_gravity = true; + OPTION_TO_BOOL(right_gravity, right_gravity, true); + + // Only error out if they try to set end_right_gravity without + // setting end_col or end_line + if (line2 == -1 && col2 == -1 && HAS_KEY(opts->end_right_gravity)) { + api_set_error(err, kErrorTypeValidation, + "cannot set end_right_gravity without setting end_line or end_col"); + goto error; + } + + bool end_right_gravity = false; + OPTION_TO_BOOL(end_right_gravity, end_right_gravity, false); + + size_t len = 0; + + bool ephemeral = false; + OPTION_TO_BOOL(ephemeral, ephemeral, false); + + if (line < 0 || line > buf->b_ml.ml_line_count) { + api_set_error(err, kErrorTypeValidation, "line value outside range"); + goto error; + } else if (line < buf->b_ml.ml_line_count) { + len = ephemeral ? MAXCOL : STRLEN(ml_get_buf(buf, (linenr_T)line+1, false)); + } + + if (col == -1) { + col = (Integer)len; + } else if (col < -1 || col > (Integer)len) { + api_set_error(err, kErrorTypeValidation, "col value outside range"); + goto error; + } + + if (col2 >= 0) { + if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) { + len = ephemeral ? MAXCOL : STRLEN(ml_get_buf(buf, (linenr_T)line2 + 1, false)); + } else if (line2 == buf->b_ml.ml_line_count) { + // We are trying to add an extmark past final newline + len = 0; + } else { + // reuse len from before + line2 = (int)line; + } + if (col2 > (Integer)len) { + api_set_error(err, kErrorTypeValidation, "end_col value outside range"); + goto error; + } + } else if (line2 >= 0) { + col2 = 0; + } + + Decoration *d = NULL; + + if (ephemeral) { + d = &decor; + } else if (kv_size(decor.virt_text) || kv_size(decor.virt_lines) + || decor.priority != DECOR_PRIORITY_BASE + || decor.hl_eol) { + // TODO(bfredl): this is a bit sketchy. eventually we should + // have predefined decorations for both marks/ephemerals + d = xcalloc(1, sizeof(*d)); + *d = decor; + } else if (decor.hl_id) { + d = decor_hl(decor.hl_id); + } + + // TODO(bfredl): synergize these two branches even more + if (ephemeral && decor_state.buf == buf) { + decor_add_ephemeral((int)line, (int)col, line2, col2, &decor); + } else { + if (ephemeral) { + api_set_error(err, kErrorTypeException, "not yet implemented"); + goto error; + } + + extmark_set(buf, (uint64_t)ns_id, &id, (int)line, (colnr_T)col, line2, col2, + d, right_gravity, end_right_gravity, kExtmarkNoUndo); + + if (kv_size(decor.virt_lines)) { + redraw_buf_line_later(buf, MIN(buf->b_ml.ml_line_count, line+1+(decor.virt_lines_above?0:1))); + } + } + + return (Integer)id; + +error: + clear_virttext(&decor.virt_text); + return 0; +} + +/// Removes an extmark. +/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param ns_id Namespace id from |nvim_create_namespace()| +/// @param id Extmark id +/// @param[out] err Error details, if any +/// @return true if the extmark was found, else false +Boolean nvim_buf_del_extmark(Buffer buffer, Integer ns_id, Integer id, Error *err) + FUNC_API_SINCE(7) +{ + buf_T *buf = find_buffer_by_handle(buffer, err); + + if (!buf) { + return false; + } + if (!ns_initialized((uint64_t)ns_id)) { + api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); + return false; + } + + return extmark_del(buf, (uint64_t)ns_id, (uint64_t)id); +} + +uint64_t src2ns(Integer *src_id) +{ + if (*src_id == 0) { + *src_id = nvim_create_namespace((String)STRING_INIT); + } + if (*src_id < 0) { + return UINT64_MAX; + } else { + return (uint64_t)(*src_id); + } +} + +/// Adds a highlight to buffer. +/// +/// Useful for plugins that 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. +/// +/// Namespaces are used for batch deletion/updating of a set of highlights. To +/// create a namespace, use |nvim_create_namespace()| which returns a namespace +/// id. Pass it in to this function as `ns_id` to add highlights to the +/// namespace. All highlights in the same namespace can then be cleared with +/// single call to |nvim_buf_clear_namespace()|. If the highlight never will be +/// deleted by an API call, pass `ns_id = -1`. +/// +/// As a shorthand, `ns_id = 0` can be used to create a new namespace for the +/// highlight, the allocated id is then returned. If `hl_group` is the empty +/// string no highlight is added, but a new `ns_id` is still returned. This is +/// supported for backwards compatibility, new code should use +/// |nvim_create_namespace()| to create a new empty namespace. +/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param ns_id namespace to use or -1 for ungrouped highlight +/// @param hl_group Name of the highlight group to use +/// @param line Line to highlight (zero-indexed) +/// @param col_start Start of (byte-indexed) column range to highlight +/// @param col_end End of (byte-indexed) column range to highlight, +/// or -1 to highlight to end of line +/// @param[out] err Error details, if any +/// @return The ns_id that was used +Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, Integer line, + Integer col_start, Integer col_end, Error *err) + FUNC_API_SINCE(1) +{ + buf_T *buf = find_buffer_by_handle(buffer, err); + if (!buf) { + return 0; + } + + if (line < 0 || line >= MAXLNUM) { + api_set_error(err, kErrorTypeValidation, "Line number outside range"); + return 0; + } + if (col_start < 0 || col_start > MAXCOL) { + api_set_error(err, kErrorTypeValidation, "Column value outside range"); + return 0; + } + if (col_end < 0 || col_end > MAXCOL) { + col_end = MAXCOL; + } + + uint64_t ns = src2ns(&ns_id); + + if (!(line < buf->b_ml.ml_line_count)) { + // safety check, we can't add marks outside the range + return ns_id; + } + + int hl_id = 0; + if (hl_group.size > 0) { + hl_id = syn_check_group(hl_group.data, (int)hl_group.size); + } else { + return ns_id; + } + + int end_line = (int)line; + if (col_end == MAXCOL) { + col_end = 0; + end_line++; + } + + extmark_set(buf, ns, NULL, + (int)line, (colnr_T)col_start, + end_line, (colnr_T)col_end, + decor_hl(hl_id), true, false, kExtmarkNoUndo); + return ns_id; +} + +/// Clears namespaced objects (highlights, extmarks, virtual text) from +/// a region. +/// +/// Lines are 0-indexed. |api-indexing| To clear the namespace in the entire +/// buffer, specify line_start=0 and line_end=-1. +/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param ns_id Namespace to clear, or -1 to clear all namespaces. +/// @param line_start Start of range of lines to clear +/// @param line_end End of range of lines to clear (exclusive) or -1 to clear +/// to end of buffer. +/// @param[out] err Error details, if any +void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start, Integer line_end, + Error *err) + FUNC_API_SINCE(5) +{ + buf_T *buf = find_buffer_by_handle(buffer, err); + if (!buf) { + return; + } + + if (line_start < 0 || line_start >= MAXLNUM) { + api_set_error(err, kErrorTypeValidation, "Line number outside range"); + return; + } + if (line_end < 0 || line_end > MAXLNUM) { + line_end = MAXLNUM; + } + extmark_clear(buf, (ns_id < 0 ? 0 : (uint64_t)ns_id), + (int)line_start, 0, + (int)line_end-1, MAXCOL); +} + +/// Set or change decoration provider for a namespace +/// +/// This is a very general purpose interface for having lua callbacks +/// being triggered during the redraw code. +/// +/// The expected usage is to set extmarks for the currently +/// redrawn buffer. |nvim_buf_set_extmark| can be called to add marks +/// on a per-window or per-lines basis. Use the `ephemeral` key to only +/// use the mark for the current screen redraw (the callback will be called +/// again for the next redraw ). +/// +/// Note: this function should not be called often. Rather, the callbacks +/// themselves can be used to throttle unneeded callbacks. the `on_start` +/// callback can return `false` to disable the provider until the next redraw. +/// Similarly, return `false` in `on_win` will skip the `on_lines` calls +/// for that window (but any extmarks set in `on_win` will still be used). +/// A plugin managing multiple sources of decoration should ideally only set +/// one provider, and merge the sources internally. You can use multiple `ns_id` +/// for the extmarks set/modified inside the callback anyway. +/// +/// Note: doing anything other than setting extmarks is considered experimental. +/// Doing things like changing options are not expliticly forbidden, but is +/// likely to have unexpected consequences (such as 100% CPU consumption). +/// doing `vim.rpcnotify` should be OK, but `vim.rpcrequest` is quite dubious +/// for the moment. +/// +/// @param ns_id Namespace id from |nvim_create_namespace()| +/// @param opts Callbacks invoked during redraw: +/// - on_start: called first on each screen redraw +/// ["start", tick] +/// - on_buf: called for each buffer being redrawn (before window +/// callbacks) +/// ["buf", bufnr, tick] +/// - on_win: called when starting to redraw a specific window. +/// ["win", winid, bufnr, topline, botline_guess] +/// - on_line: called for each buffer line being redrawn. (The +/// interation with fold lines is subject to change) +/// ["win", winid, bufnr, row] +/// - on_end: called at the end of a redraw cycle +/// ["end", tick] +void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, Error *err) + FUNC_API_SINCE(7) FUNC_API_LUA_ONLY +{ + DecorProvider *p = get_decor_provider((NS)ns_id, true); + assert(p != NULL); + decor_provider_clear(p); + + // regardless of what happens, it seems good idea to redraw + redraw_all_later(NOT_VALID); // TODO(bfredl): too soon? + + struct { + const char *name; + LuaRef *dest; + } cbs[] = { + { "on_start", &p->redraw_start }, + { "on_buf", &p->redraw_buf }, + { "on_win", &p->redraw_win }, + { "on_line", &p->redraw_line }, + { "on_end", &p->redraw_end }, + { "_on_hl_def", &p->hl_def }, + { NULL, NULL }, + }; + + for (size_t i = 0; i < opts.size; i++) { + String k = opts.items[i].key; + Object *v = &opts.items[i].value; + size_t j; + for (j = 0; cbs[j].name && cbs[j].dest; j++) { + if (strequal(cbs[j].name, k.data)) { + if (v->type != kObjectTypeLuaRef) { + api_set_error(err, kErrorTypeValidation, + "%s is not a function", cbs[j].name); + goto error; + } + *(cbs[j].dest) = v->data.luaref; + v->data.luaref = LUA_NOREF; + break; + } + } + if (!cbs[j].name) { + api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); + goto error; + } + } + + p->active = true; + return; +error: + decor_provider_clear(p); +} diff --git a/src/nvim/api/extmark.h b/src/nvim/api/extmark.h new file mode 100644 index 0000000000..c5e463cd86 --- /dev/null +++ b/src/nvim/api/extmark.h @@ -0,0 +1,13 @@ +#ifndef NVIM_API_EXTMARK_H +#define NVIM_API_EXTMARK_H + +#include "nvim/api/private/defs.h" +#include "nvim/map.h" + +EXTERN Map(String, handle_T) namespace_ids INIT(= MAP_INIT); +EXTERN handle_T next_namespace_id INIT(= 1); + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "api/extmark.h.generated.h" +#endif +#endif // NVIM_API_EXTMARK_H diff --git a/src/nvim/api/private/converter.c b/src/nvim/api/private/converter.c new file mode 100644 index 0000000000..36da6c13a9 --- /dev/null +++ b/src/nvim/api/private/converter.c @@ -0,0 +1,348 @@ +// 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 <stdlib.h> + +#include "nvim/api/private/converter.h" +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/assert.h" +#include "nvim/eval/typval.h" + +/// Helper structure for vim_to_object +typedef struct { + kvec_withinit_t(Object, 2) stack; ///< Object stack. +} EncodedData; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "api/private/converter.c.generated.h" +#endif + +#define TYPVAL_ENCODE_ALLOW_SPECIALS false + +#define TYPVAL_ENCODE_CONV_NIL(tv) \ + kvi_push(edata->stack, NIL) + +#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ + kvi_push(edata->stack, BOOLEAN_OBJ((Boolean)(num))) + +#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ + kvi_push(edata->stack, INTEGER_OBJ((Integer)(num))) + +#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER TYPVAL_ENCODE_CONV_NUMBER + +#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ + kvi_push(edata->stack, FLOAT_OBJ((Float)(flt))) + +#define TYPVAL_ENCODE_CONV_STRING(tv, str, len) \ + do { \ + const size_t len_ = (size_t)(len); \ + const char *const str_ = (const char *)(str); \ + assert(len_ == 0 || str_ != NULL); \ + kvi_push(edata->stack, STRING_OBJ(cbuf_to_string((len_?str_:""), len_))); \ + } while (0) + +#define TYPVAL_ENCODE_CONV_STR_STRING TYPVAL_ENCODE_CONV_STRING + +#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, str, len, type) \ + TYPVAL_ENCODE_CONV_NIL(tv) + +#define TYPVAL_ENCODE_CONV_BLOB(tv, blob, len) \ + do { \ + const size_t len_ = (size_t)(len); \ + const blob_T *const blob_ = (blob); \ + kvi_push(edata->stack, STRING_OBJ(((String) { \ + .data = len_ != 0 ? xmemdup(blob_->bv_ga.ga_data, len_) : NULL, \ + .size = len_ \ + }))); \ + } while (0) + +#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) \ + kvi_push(edata->stack, ARRAY_OBJ(((Array) { .capacity = 0, .size = 0 }))) + +#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ + kvi_push(edata->stack, \ + DICTIONARY_OBJ(((Dictionary) { .capacity = 0, .size = 0 }))) + +static inline void typval_encode_list_start(EncodedData *const edata, const size_t len) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL +{ + kvi_push(edata->stack, ARRAY_OBJ(((Array) { + .capacity = len, + .size = 0, + .items = xmalloc(len * sizeof(*((Object)OBJECT_INIT).data.array.items)), + }))); +} + +#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \ + typval_encode_list_start(edata, (size_t)(len)) + +#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) + +static inline void typval_encode_between_list_items(EncodedData *const edata) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL +{ + Object item = kv_pop(edata->stack); + Object *const list = &kv_last(edata->stack); + assert(list->type == kObjectTypeArray); + assert(list->data.array.size < list->data.array.capacity); + list->data.array.items[list->data.array.size++] = item; +} + +#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) \ + typval_encode_between_list_items(edata) + +static inline void typval_encode_list_end(EncodedData *const edata) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL +{ + typval_encode_between_list_items(edata); +#ifndef NDEBUG + const Object *const list = &kv_last(edata->stack); + assert(list->data.array.size == list->data.array.capacity); +#endif +} + +#define TYPVAL_ENCODE_CONV_LIST_END(tv) \ + typval_encode_list_end(edata) + +static inline void typval_encode_dict_start(EncodedData *const edata, const size_t len) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL +{ + kvi_push(edata->stack, DICTIONARY_OBJ(((Dictionary) { + .capacity = len, + .size = 0, + .items = xmalloc(len * sizeof(*((Object)OBJECT_INIT).data.dictionary.items)), + }))); +} + +#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ + typval_encode_dict_start(edata, (size_t)(len)) + +#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) + +#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, kv_pair) + +static inline void typval_encode_after_key(EncodedData *const edata) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL +{ + Object key = kv_pop(edata->stack); + Object *const dict = &kv_last(edata->stack); + assert(dict->type == kObjectTypeDictionary); + assert(dict->data.dictionary.size < dict->data.dictionary.capacity); + if (key.type == kObjectTypeString) { + dict->data.dictionary.items[dict->data.dictionary.size].key + = key.data.string; + } else { + api_free_object(key); + dict->data.dictionary.items[dict->data.dictionary.size].key + = STATIC_CSTR_TO_STRING("__INVALID_KEY__"); + } +} + +#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) \ + typval_encode_after_key(edata) + +static inline void typval_encode_between_dict_items(EncodedData *const edata) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL +{ + Object val = kv_pop(edata->stack); + Object *const dict = &kv_last(edata->stack); + assert(dict->type == kObjectTypeDictionary); + assert(dict->data.dictionary.size < dict->data.dictionary.capacity); + dict->data.dictionary.items[dict->data.dictionary.size++].value = val; +} + +#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) \ + typval_encode_between_dict_items(edata) + +static inline void typval_encode_dict_end(EncodedData *const edata) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL +{ + typval_encode_between_dict_items(edata); +#ifndef NDEBUG + const Object *const dict = &kv_last(edata->stack); + assert(dict->data.dictionary.size == dict->data.dictionary.capacity); +#endif +} + +#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ + typval_encode_dict_end(edata) + +#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ + TYPVAL_ENCODE_CONV_NIL(val) + +#define TYPVAL_ENCODE_SCOPE static +#define TYPVAL_ENCODE_NAME object +#define TYPVAL_ENCODE_FIRST_ARG_TYPE EncodedData *const +#define TYPVAL_ENCODE_FIRST_ARG_NAME edata +#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_BLOB +#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 a vim object to an `Object` instance, recursively expanding +/// Arrays/Dictionaries. +/// +/// @param obj The source object +/// @return The converted value +Object vim_to_object(typval_T *obj) +{ + EncodedData edata; + kvi_init(edata.stack); + const int evo_ret = encode_vim_to_object(&edata, obj, + "vim_to_object argument"); + (void)evo_ret; + assert(evo_ret == OK); + Object ret = kv_A(edata.stack, 0); + assert(kv_size(edata.stack) == 1); + kvi_destroy(edata.stack); + return ret; +} + +/// Converts from type Object to a VimL value. +/// +/// @param obj Object to convert from. +/// @param tv Conversion result is placed here. On failure member v_type is +/// set to VAR_UNKNOWN (no allocation was made for this variable). +/// returns true if conversion is successful, otherwise false. +bool object_to_vim(Object obj, typval_T *tv, Error *err) +{ + tv->v_type = VAR_UNKNOWN; + tv->v_lock = VAR_UNLOCKED; + + switch (obj.type) { + case kObjectTypeNil: + tv->v_type = VAR_SPECIAL; + tv->vval.v_special = kSpecialVarNull; + break; + + case kObjectTypeBoolean: + tv->v_type = VAR_BOOL; + tv->vval.v_bool = obj.data.boolean? kBoolVarTrue: kBoolVarFalse; + break; + + case kObjectTypeBuffer: + case kObjectTypeWindow: + case kObjectTypeTabpage: + case kObjectTypeInteger: + STATIC_ASSERT(sizeof(obj.data.integer) <= sizeof(varnumber_T), + "Integer size must be <= VimL number size"); + tv->v_type = VAR_NUMBER; + tv->vval.v_number = (varnumber_T)obj.data.integer; + break; + + case kObjectTypeFloat: + tv->v_type = VAR_FLOAT; + tv->vval.v_float = obj.data.floating; + break; + + case kObjectTypeString: + tv->v_type = VAR_STRING; + if (obj.data.string.data == NULL) { + tv->vval.v_string = NULL; + } else { + tv->vval.v_string = xmemdupz(obj.data.string.data, + obj.data.string.size); + } + break; + + case kObjectTypeArray: { + list_T *const list = tv_list_alloc((ptrdiff_t)obj.data.array.size); + + for (uint32_t i = 0; i < obj.data.array.size; i++) { + Object item = obj.data.array.items[i]; + typval_T li_tv; + + if (!object_to_vim(item, &li_tv, err)) { + tv_list_free(list); + return false; + } + + tv_list_append_owned_tv(list, li_tv); + } + tv_list_ref(list); + + tv->v_type = VAR_LIST; + tv->vval.v_list = list; + break; + } + + case kObjectTypeDictionary: { + 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, kErrorTypeValidation, + "Empty dictionary keys aren't allowed"); + // cleanup + tv_dict_free(dict); + return false; + } + + dictitem_T *const di = tv_dict_item_alloc(key.data); + + if (!object_to_vim(item.value, &di->di_tv, err)) { + // cleanup + tv_dict_item_free(di); + tv_dict_free(dict); + return false; + } + + tv_dict_add(dict, di); + } + dict->dv_refcount++; + + tv->v_type = VAR_DICT; + tv->vval.v_dict = dict; + break; + } + default: + abort(); + } + + return true; +} diff --git a/src/nvim/api/private/converter.h b/src/nvim/api/private/converter.h new file mode 100644 index 0000000000..80ee640295 --- /dev/null +++ b/src/nvim/api/private/converter.h @@ -0,0 +1,11 @@ +#ifndef NVIM_API_PRIVATE_CONVERTER_H +#define NVIM_API_PRIVATE_CONVERTER_H + +#include "nvim/api/private/defs.h" +#include "nvim/eval/typval.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "api/private/converter.h.generated.h" +#endif + +#endif // NVIM_API_PRIVATE_CONVERTER_H diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h index 663d1e16b5..396fab721d 100644 --- a/src/nvim/api/private/defs.h +++ b/src/nvim/api/private/defs.h @@ -26,7 +26,7 @@ typedef enum { kErrorTypeNone = -1, kErrorTypeException, - kErrorTypeValidation + kErrorTypeValidation, } ErrorType; typedef enum { diff --git a/src/nvim/api/private/dispatch.c b/src/nvim/api/private/dispatch.c index 519bf8ff14..8ab7743e01 100644 --- a/src/nvim/api/private/dispatch.c +++ b/src/nvim/api/private/dispatch.c @@ -8,12 +8,14 @@ #include "nvim/api/buffer.h" #include "nvim/api/deprecated.h" +#include "nvim/api/extmark.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" #include "nvim/api/tabpage.h" #include "nvim/api/ui.h" #include "nvim/api/vim.h" +#include "nvim/api/vimscript.h" #include "nvim/api/win_config.h" #include "nvim/api/window.h" #include "nvim/log.h" diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index f1259c8a18..d470def277 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -8,6 +8,7 @@ #include <stdlib.h> #include <string.h> +#include "nvim/api/private/converter.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" @@ -37,11 +38,6 @@ #include "nvim/vim.h" #include "nvim/window.h" -/// Helper structure for vim_to_object -typedef struct { - kvec_withinit_t(Object, 2) stack; ///< Object stack. -} EncodedData; - #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/private/funcs_metadata.generated.h" # include "api/private/helpers.c.generated.h" @@ -415,226 +411,6 @@ void set_option_to(uint64_t channel_id, void *to, int type, String name, Object current_sctx = save_current_sctx; } -#define TYPVAL_ENCODE_ALLOW_SPECIALS false - -#define TYPVAL_ENCODE_CONV_NIL(tv) \ - kvi_push(edata->stack, NIL) - -#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ - kvi_push(edata->stack, BOOLEAN_OBJ((Boolean)(num))) - -#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ - kvi_push(edata->stack, INTEGER_OBJ((Integer)(num))) - -#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER TYPVAL_ENCODE_CONV_NUMBER - -#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ - kvi_push(edata->stack, FLOAT_OBJ((Float)(flt))) - -#define TYPVAL_ENCODE_CONV_STRING(tv, str, len) \ - do { \ - const size_t len_ = (size_t)(len); \ - const char *const str_ = (const char *)(str); \ - assert(len_ == 0 || str_ != NULL); \ - kvi_push(edata->stack, STRING_OBJ(cbuf_to_string((len_?str_:""), len_))); \ - } while (0) - -#define TYPVAL_ENCODE_CONV_STR_STRING TYPVAL_ENCODE_CONV_STRING - -#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, str, len, type) \ - TYPVAL_ENCODE_CONV_NIL(tv) - -#define TYPVAL_ENCODE_CONV_BLOB(tv, blob, len) \ - do { \ - const size_t len_ = (size_t)(len); \ - const blob_T *const blob_ = (blob); \ - kvi_push(edata->stack, STRING_OBJ(((String) { \ - .data = len_ != 0 ? xmemdup(blob_->bv_ga.ga_data, len_) : NULL, \ - .size = len_ \ - }))); \ - } while (0) - -#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) \ - kvi_push(edata->stack, ARRAY_OBJ(((Array) { .capacity = 0, .size = 0 }))) - -#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ - kvi_push(edata->stack, \ - DICTIONARY_OBJ(((Dictionary) { .capacity = 0, .size = 0 }))) - -static inline void typval_encode_list_start(EncodedData *const edata, const size_t len) - FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL -{ - kvi_push(edata->stack, ARRAY_OBJ(((Array) { - .capacity = len, - .size = 0, - .items = xmalloc(len * sizeof(*((Object)OBJECT_INIT).data.array.items)), - }))); -} - -#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \ - typval_encode_list_start(edata, (size_t)(len)) - -#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) - -static inline void typval_encode_between_list_items(EncodedData *const edata) - FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL -{ - Object item = kv_pop(edata->stack); - Object *const list = &kv_last(edata->stack); - assert(list->type == kObjectTypeArray); - assert(list->data.array.size < list->data.array.capacity); - list->data.array.items[list->data.array.size++] = item; -} - -#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) \ - typval_encode_between_list_items(edata) - -static inline void typval_encode_list_end(EncodedData *const edata) - FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL -{ - typval_encode_between_list_items(edata); -#ifndef NDEBUG - const Object *const list = &kv_last(edata->stack); - assert(list->data.array.size == list->data.array.capacity); -#endif -} - -#define TYPVAL_ENCODE_CONV_LIST_END(tv) \ - typval_encode_list_end(edata) - -static inline void typval_encode_dict_start(EncodedData *const edata, const size_t len) - FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL -{ - kvi_push(edata->stack, DICTIONARY_OBJ(((Dictionary) { - .capacity = len, - .size = 0, - .items = xmalloc(len * sizeof( - *((Object)OBJECT_INIT).data.dictionary.items)), - }))); -} - -#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ - typval_encode_dict_start(edata, (size_t)(len)) - -#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) - -#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, kv_pair) - -static inline void typval_encode_after_key(EncodedData *const edata) - FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL -{ - Object key = kv_pop(edata->stack); - Object *const dict = &kv_last(edata->stack); - assert(dict->type == kObjectTypeDictionary); - assert(dict->data.dictionary.size < dict->data.dictionary.capacity); - if (key.type == kObjectTypeString) { - dict->data.dictionary.items[dict->data.dictionary.size].key - = key.data.string; - } else { - api_free_object(key); - dict->data.dictionary.items[dict->data.dictionary.size].key - = STATIC_CSTR_TO_STRING("__INVALID_KEY__"); - } -} - -#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) \ - typval_encode_after_key(edata) - -static inline void typval_encode_between_dict_items(EncodedData *const edata) - FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL -{ - Object val = kv_pop(edata->stack); - Object *const dict = &kv_last(edata->stack); - assert(dict->type == kObjectTypeDictionary); - assert(dict->data.dictionary.size < dict->data.dictionary.capacity); - dict->data.dictionary.items[dict->data.dictionary.size++].value = val; -} - -#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) \ - typval_encode_between_dict_items(edata) - -static inline void typval_encode_dict_end(EncodedData *const edata) - FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL -{ - typval_encode_between_dict_items(edata); -#ifndef NDEBUG - const Object *const dict = &kv_last(edata->stack); - assert(dict->data.dictionary.size == dict->data.dictionary.capacity); -#endif -} - -#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ - typval_encode_dict_end(edata) - -#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ - TYPVAL_ENCODE_CONV_NIL(val) - -#define TYPVAL_ENCODE_SCOPE static -#define TYPVAL_ENCODE_NAME object -#define TYPVAL_ENCODE_FIRST_ARG_TYPE EncodedData *const -#define TYPVAL_ENCODE_FIRST_ARG_NAME edata -#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_BLOB -#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 a vim object to an `Object` instance, recursively expanding -/// Arrays/Dictionaries. -/// -/// @param obj The source object -/// @return The converted value -Object vim_to_object(typval_T *obj) -{ - EncodedData edata; - kvi_init(edata.stack); - const int evo_ret = encode_vim_to_object(&edata, obj, - "vim_to_object argument"); - (void)evo_ret; - assert(evo_ret == OK); - Object ret = kv_A(edata.stack, 0); - assert(kv_size(edata.stack) == 1); - kvi_destroy(edata.stack); - return ret; -} buf_T *find_buffer_by_handle(Buffer buffer, Error *err) { @@ -831,7 +607,7 @@ void modify_keymap(Buffer buffer, bool is_unmap, String mode, String lhs, String MapArguments parsed_args = MAP_ARGUMENTS_INIT; if (opts) { #define KEY_TO_BOOL(name) \ - parsed_args. name = api_object_to_bool(opts-> name, #name, false, err); \ + parsed_args.name = api_object_to_bool(opts->name, #name, false, err); \ if (ERROR_SET(err)) { \ goto fail_and_free; \ } @@ -966,112 +742,6 @@ bool buf_collect_lines(buf_T *buf, size_t n, int64_t start, bool replace_nl, Arr return true; } -/// Converts from type Object to a VimL value. -/// -/// @param obj Object to convert from. -/// @param tv Conversion result is placed here. On failure member v_type is -/// set to VAR_UNKNOWN (no allocation was made for this variable). -/// returns true if conversion is successful, otherwise false. -bool object_to_vim(Object obj, typval_T *tv, Error *err) -{ - tv->v_type = VAR_UNKNOWN; - tv->v_lock = VAR_UNLOCKED; - - switch (obj.type) { - case kObjectTypeNil: - tv->v_type = VAR_SPECIAL; - tv->vval.v_special = kSpecialVarNull; - break; - - case kObjectTypeBoolean: - tv->v_type = VAR_BOOL; - tv->vval.v_bool = obj.data.boolean? kBoolVarTrue: kBoolVarFalse; - break; - - case kObjectTypeBuffer: - case kObjectTypeWindow: - case kObjectTypeTabpage: - case kObjectTypeInteger: - STATIC_ASSERT(sizeof(obj.data.integer) <= sizeof(varnumber_T), - "Integer size must be <= VimL number size"); - tv->v_type = VAR_NUMBER; - tv->vval.v_number = (varnumber_T)obj.data.integer; - break; - - case kObjectTypeFloat: - tv->v_type = VAR_FLOAT; - tv->vval.v_float = obj.data.floating; - break; - - case kObjectTypeString: - tv->v_type = VAR_STRING; - if (obj.data.string.data == NULL) { - tv->vval.v_string = NULL; - } else { - tv->vval.v_string = xmemdupz(obj.data.string.data, - obj.data.string.size); - } - break; - - case kObjectTypeArray: { - list_T *const list = tv_list_alloc((ptrdiff_t)obj.data.array.size); - - for (uint32_t i = 0; i < obj.data.array.size; i++) { - Object item = obj.data.array.items[i]; - typval_T li_tv; - - if (!object_to_vim(item, &li_tv, err)) { - tv_list_free(list); - return false; - } - - tv_list_append_owned_tv(list, li_tv); - } - tv_list_ref(list); - - tv->v_type = VAR_LIST; - tv->vval.v_list = list; - break; - } - - case kObjectTypeDictionary: { - 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, kErrorTypeValidation, - "Empty dictionary keys aren't allowed"); - // cleanup - tv_dict_free(dict); - return false; - } - - dictitem_T *const di = tv_dict_item_alloc(key.data); - - if (!object_to_vim(item.value, &di->di_tv, err)) { - // cleanup - tv_dict_item_free(di); - tv_dict_free(dict); - return false; - } - - tv_dict_add(dict, di); - } - dict->dv_refcount++; - - tv->v_type = VAR_DICT; - tv->vval.v_dict = dict; - break; - } - default: - abort(); - } - - return true; -} void api_free_string(String value) { @@ -1410,15 +1080,6 @@ ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf) return mappings; } -// Is the Namespace in use? -bool ns_initialized(uint64_t ns) -{ - if (ns < 1) { - return false; - } - return ns < (uint64_t)next_namespace_id; -} - /// Gets the line and column of an extmark. /// /// Extmarks may be queried by position, name or even special names @@ -1607,18 +1268,6 @@ free_exit: return hl_msg; } -const char *describe_ns(NS ns_id) -{ - String name; - handle_T id; - map_foreach(&namespace_ids, name, id, { - if ((NS)id == ns_id && name.size) { - return name.data; - } - }) - return "(UNKNOWN PLUGIN)"; -} - bool api_dict_to_keydict(void *rv, field_hash hashy, Dictionary dict, Error *err) { for (size_t i = 0; i < dict.size; i++) { diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index 08d2c8d90c..6d0aec9c90 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -1,8 +1,6 @@ #ifndef NVIM_API_PRIVATE_HELPERS_H #define NVIM_API_PRIVATE_HELPERS_H -#include <stdbool.h> - #include "nvim/api/private/defs.h" #include "nvim/decoration.h" #include "nvim/ex_eval.h" diff --git a/src/nvim/api/tabpage.h b/src/nvim/api/tabpage.h index a822844af9..2689cf6ae6 100644 --- a/src/nvim/api/tabpage.h +++ b/src/nvim/api/tabpage.h @@ -1,8 +1,6 @@ #ifndef NVIM_API_TABPAGE_H #define NVIM_API_TABPAGE_H -#include <stdint.h> - #include "nvim/api/private/defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 233fd82d3c..c1374ff00e 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -10,6 +10,7 @@ #include "nvim/api/buffer.h" #include "nvim/api/deprecated.h" +#include "nvim/api/private/converter.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" @@ -59,95 +60,6 @@ # include "api/vim.c.generated.h" #endif -void api_vim_free_all_mem(void) -{ - String name; - handle_T id; - map_foreach(&namespace_ids, name, id, { - (void)id; - xfree(name.data); - }) - map_destroy(String, handle_T)(&namespace_ids); -} - -/// Executes Vimscript (multiline block of Ex-commands), like anonymous -/// |:source|. -/// -/// Unlike |nvim_command()| this function supports heredocs, script-scope (s:), -/// etc. -/// -/// On execution error: fails with VimL error, does not update v:errmsg. -/// -/// @see |execute()| -/// @see |nvim_command()| -/// -/// @param src Vimscript code -/// @param output Capture and return all (non-error, non-shell |:!|) output -/// @param[out] err Error details (Vim error), if any -/// @return Output (non-error, non-shell |:!|) if `output` is true, -/// else empty string. -String nvim_exec(String src, Boolean output, Error *err) - FUNC_API_SINCE(7) -{ - const int save_msg_silent = msg_silent; - garray_T *const save_capture_ga = capture_ga; - garray_T capture_local; - if (output) { - ga_init(&capture_local, 1, 80); - capture_ga = &capture_local; - } - - try_start(); - if (output) { - msg_silent++; - } - do_source_str(src.data, "nvim_exec()"); - if (output) { - capture_ga = save_capture_ga; - msg_silent = save_msg_silent; - } - try_end(err); - - if (ERROR_SET(err)) { - goto theend; - } - - if (output && capture_local.ga_len > 1) { - String s = (String){ - .data = capture_local.ga_data, - .size = (size_t)capture_local.ga_len, - }; - // redir usually (except :echon) prepends a newline. - if (s.data[0] == '\n') { - memmove(s.data, s.data + 1, s.size - 1); - s.data[s.size - 1] = '\0'; - s.size = s.size - 1; - } - return s; // Caller will free the memory. - } -theend: - if (output) { - ga_clear(&capture_local); - } - return (String)STRING_INIT; -} - -/// Executes an ex-command. -/// -/// On execution error: fails with VimL error, does not update v:errmsg. -/// -/// @see |nvim_exec()| -/// -/// @param command Ex-command string -/// @param[out] err Error details (Vim error), if any -void nvim_command(String command, Error *err) - FUNC_API_SINCE(1) -{ - try_start(); - do_cmdline_cmd(command.data); - try_end(err); -} - /// Gets a highlight definition by name. /// /// @param name Highlight group name @@ -488,51 +400,6 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Bool return cstr_as_string(ptr); } -/// Evaluates a VimL |expression|. -/// Dictionaries and Lists are recursively expanded. -/// -/// On execution error: fails with VimL error, does not update v:errmsg. -/// -/// @param expr VimL expression string -/// @param[out] err Error details, if any -/// @return Evaluation result or expanded object -Object nvim_eval(String expr, Error *err) - FUNC_API_SINCE(1) -{ - static int recursive = 0; // recursion depth - Object rv = OBJECT_INIT; - - TRY_WRAP({ - // Initialize `force_abort` and `suppress_errthrow` at the top level. - if (!recursive) { - force_abort = false; - suppress_errthrow = false; - current_exception = NULL; - // `did_emsg` is set by emsg(), which cancels execution. - did_emsg = false; - } - recursive++; - try_start(); - - typval_T rettv; - int ok = eval0((char_u *)expr.data, &rettv, NULL, true); - - if (!try_end(err)) { - if (ok == FAIL) { - // Should never happen, try_end() should get the error. #8371 - api_set_error(err, kErrorTypeException, - "Failed to evaluate expression: '%.*s'", 256, expr.data); - } else { - rv = vim_to_object(&rettv); - } - } - - tv_clear(&rettv); - recursive--; - }); - - return rv; -} /// Execute Lua code. Parameters (if any) are available as `...` inside the /// chunk. The chunk can return a value. @@ -573,164 +440,6 @@ Object nvim_notify(String msg, Integer log_level, Dictionary opts, Error *err) return nlua_exec(STATIC_CSTR_AS_STRING("return vim.notify(...)"), args, err); } -/// Calls a VimL function. -/// -/// @param fn Function name -/// @param args Function arguments -/// @param self `self` dict, or NULL for non-dict functions -/// @param[out] err Error details, if any -/// @return Result of the function call -static Object _call_function(String fn, Array args, dict_T *self, Error *err) -{ - static int recursive = 0; // recursion depth - Object rv = OBJECT_INIT; - - if (args.size > MAX_FUNC_ARGS) { - api_set_error(err, kErrorTypeValidation, - "Function called with too many arguments"); - return rv; - } - - // Convert the arguments in args from Object to typval_T values - typval_T vim_args[MAX_FUNC_ARGS + 1]; - size_t i = 0; // also used for freeing the variables - for (; i < args.size; i++) { - if (!object_to_vim(args.items[i], &vim_args[i], err)) { - goto free_vim_args; - } - } - - TRY_WRAP({ - // Initialize `force_abort` and `suppress_errthrow` at the top level. - if (!recursive) { - force_abort = false; - suppress_errthrow = false; - current_exception = NULL; - // `did_emsg` is set by emsg(), which cancels execution. - did_emsg = false; - } - recursive++; - try_start(); - typval_T rettv; - funcexe_T funcexe = FUNCEXE_INIT; - funcexe.firstline = curwin->w_cursor.lnum; - funcexe.lastline = curwin->w_cursor.lnum; - funcexe.evaluate = true; - funcexe.selfdict = self; - // call_func() retval is deceptive, ignore it. Instead we set `msg_list` - // (see above) to capture abort-causing non-exception errors. - (void)call_func((char_u *)fn.data, (int)fn.size, &rettv, (int)args.size, - vim_args, &funcexe); - if (!try_end(err)) { - rv = vim_to_object(&rettv); - } - tv_clear(&rettv); - recursive--; - }); - -free_vim_args: - while (i > 0) { - tv_clear(&vim_args[--i]); - } - - return rv; -} - -/// Calls a VimL function with the given arguments. -/// -/// On execution error: fails with VimL error, does not update v:errmsg. -/// -/// @param fn Function to call -/// @param args Function arguments packed in an Array -/// @param[out] err Error details, if any -/// @return Result of the function call -Object nvim_call_function(String fn, Array args, Error *err) - FUNC_API_SINCE(1) -{ - return _call_function(fn, args, NULL, err); -} - -/// Calls a VimL |Dictionary-function| with the given arguments. -/// -/// On execution error: fails with VimL error, does not update v:errmsg. -/// -/// @param dict Dictionary, or String evaluating to a VimL |self| dict -/// @param fn Name of the function defined on the VimL dict -/// @param args Function arguments packed in an Array -/// @param[out] err Error details, if any -/// @return Result of the function call -Object nvim_call_dict_function(Object dict, String fn, Array args, Error *err) - FUNC_API_SINCE(4) -{ - Object rv = OBJECT_INIT; - - typval_T rettv; - bool mustfree = false; - switch (dict.type) { - case kObjectTypeString: - try_start(); - if (eval0((char_u *)dict.data.string.data, &rettv, NULL, true) == FAIL) { - api_set_error(err, kErrorTypeException, - "Failed to evaluate dict expression"); - } - if (try_end(err)) { - return rv; - } - // Evaluation of the string arg created a new dict or increased the - // refcount of a dict. Not necessary for a RPC dict. - mustfree = true; - break; - case kObjectTypeDictionary: - if (!object_to_vim(dict, &rettv, err)) { - goto end; - } - break; - default: - api_set_error(err, kErrorTypeValidation, - "dict argument type must be String or Dictionary"); - return rv; - } - dict_T *self_dict = rettv.vval.v_dict; - if (rettv.v_type != VAR_DICT || !self_dict) { - api_set_error(err, kErrorTypeValidation, "dict not found"); - goto end; - } - - if (fn.data && fn.size > 0 && dict.type != kObjectTypeDictionary) { - dictitem_T *const di = tv_dict_find(self_dict, fn.data, (ptrdiff_t)fn.size); - if (di == NULL) { - api_set_error(err, kErrorTypeValidation, "Not found: %s", fn.data); - goto end; - } - if (di->di_tv.v_type == VAR_PARTIAL) { - api_set_error(err, kErrorTypeValidation, - "partial function not supported"); - goto end; - } - if (di->di_tv.v_type != VAR_FUNC) { - api_set_error(err, kErrorTypeValidation, "Not a function: %s", fn.data); - goto end; - } - fn = (String) { - .data = (char *)di->di_tv.vval.v_string, - .size = STRLEN(di->di_tv.vval.v_string), - }; - } - - if (!fn.data || fn.size < 1) { - api_set_error(err, kErrorTypeValidation, "Invalid (empty) function name"); - goto end; - } - - rv = _call_function(fn, args, self_dict, err); -end: - if (mustfree) { - tv_clear(&rettv); - } - - return rv; -} - /// Calculates the number of display cells occupied by `text`. /// <Tab> counts as one cell. /// @@ -1248,10 +957,16 @@ fail: /// in a virtual terminal having the intended size. /// /// @param buffer the buffer to use (expected to be empty) -/// @param opts Optional parameters. Reserved for future use. +/// @param opts Optional parameters. +/// - on_input: lua callback for input sent, i e keypresses in terminal +/// mode. Note: keypresses are sent raw as they would be to the pty +/// master end. For instance, a carriage return is sent +/// as a "\r", not as a "\n". |textlock| applies. It is possible +/// to call |nvim_chan_send| directly in the callback however. +/// ["input", term, bufnr, data] /// @param[out] err Error details, if any /// @return Channel id, or 0 on error -Integer nvim_open_term(Buffer buffer, Dictionary opts, Error *err) +Integer nvim_open_term(Buffer buffer, DictionaryOf(LuaRef) opts, Error *err) FUNC_API_SINCE(7) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -1259,13 +974,27 @@ Integer nvim_open_term(Buffer buffer, Dictionary opts, Error *err) return 0; } - if (opts.size > 0) { - api_set_error(err, kErrorTypeValidation, "opts dict isn't empty"); - return 0; + LuaRef cb = LUA_NOREF; + for (size_t i = 0; i < opts.size; i++) { + String k = opts.items[i].key; + Object *v = &opts.items[i].value; + if (strequal("on_input", k.data)) { + if (v->type != kObjectTypeLuaRef) { + api_set_error(err, kErrorTypeValidation, + "%s is not a function", "on_input"); + return 0; + } + cb = v->data.luaref; + v->data.luaref = LUA_NOREF; + break; + } else { + api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); + } } TerminalOptions topts; Channel *chan = channel_alloc(kChannelStreamInternal); + chan->stream.internal.cb = cb; topts.data = chan; // NB: overridden in terminal_check_size if a window is already // displaying the buffer @@ -1277,13 +1006,23 @@ Integer nvim_open_term(Buffer buffer, Dictionary opts, Error *err) Terminal *term = terminal_open(buf, topts); terminal_check_size(term); chan->term = term; - channel_incref(chan); return (Integer)chan->id; } static void term_write(char *buf, size_t size, void *data) { - // TODO(bfredl): lua callback + Channel *chan = data; + LuaRef cb = chan->stream.internal.cb; + if (cb == LUA_NOREF) { + return; + } + FIXED_TEMP_ARRAY(args, 3); + args.items[0] = INTEGER_OBJ((Integer)chan->id); + args.items[1] = BUFFER_OBJ(terminal_buf(chan->term)); + args.items[2] = STRING_OBJ(((String){ .data = buf, .size = size })); + textlock++; + nlua_call_ref(cb, "input", args, false, NULL); + textlock--; } static void term_resize(uint16_t width, uint16_t height, void *data) @@ -1296,6 +1035,8 @@ static void term_close(void *data) Channel *chan = data; terminal_destroy(chan->term); chan->term = NULL; + api_free_luaref(chan->stream.internal.cb); + chan->stream.internal.cb = LUA_NOREF; channel_decref(chan); } @@ -1383,49 +1124,6 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) } } -/// Creates a new \*namespace\* or gets an existing one. -/// -/// Namespaces are used for buffer highlights and virtual text, see -/// |nvim_buf_add_highlight()| and |nvim_buf_set_extmark()|. -/// -/// Namespaces can be named or anonymous. If `name` matches an existing -/// namespace, the associated id is returned. If `name` is an empty string -/// a new, anonymous namespace is created. -/// -/// @param name Namespace name or empty string -/// @return Namespace id -Integer nvim_create_namespace(String name) - FUNC_API_SINCE(5) -{ - handle_T id = map_get(String, handle_T)(&namespace_ids, name); - if (id > 0) { - return id; - } - id = next_namespace_id++; - if (name.size > 0) { - String name_alloc = copy_string(name); - map_put(String, handle_T)(&namespace_ids, name_alloc, id); - } - return (Integer)id; -} - -/// Gets existing, non-anonymous namespaces. -/// -/// @return dict that maps from names to namespace ids. -Dictionary nvim_get_namespaces(void) - FUNC_API_SINCE(5) -{ - Dictionary retval = ARRAY_DICT_INIT; - String name; - handle_T id; - - map_foreach(&namespace_ids, name, id, { - PUT(retval, name.data, INTEGER_OBJ(id)); - }) - - return retval; -} - /// Pastes at cursor, in any mode. /// /// Invokes the `vim.paste` handler, which handles each mode appropriately. @@ -2013,439 +1711,6 @@ theend: return rv; } -typedef struct { - ExprASTNode **node_p; - Object *ret_node_p; -} ExprASTConvStackItem; - -/// @cond DOXYGEN_NOT_A_FUNCTION -typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; -/// @endcond - -/// Parse a VimL expression. -/// -/// @param[in] expr Expression to parse. Always treated as a single line. -/// @param[in] flags Flags: -/// - "m" if multiple expressions in a row are allowed (only -/// the first one will be parsed), -/// - "E" if EOC tokens are not allowed (determines whether -/// they will stop parsing process or be recognized as an -/// operator/space, though also yielding an error). -/// - "l" when needing to start parsing with lvalues for -/// ":let" or ":for". -/// Common flag sets: -/// - "m" to parse like for ":echo". -/// - "E" to parse like for "<C-r>=". -/// - empty string for ":call". -/// - "lm" to parse for ":let". -/// @param[in] highlight If true, return value will also include "highlight" -/// key containing array of 4-tuples (arrays) (Integer, -/// Integer, Integer, String), where first three numbers -/// define the highlighted region and represent line, -/// starting column and ending column (latter exclusive: -/// one should highlight region [start_col, end_col)). -/// -/// @return -/// - AST: top-level dictionary with these keys: -/// - "error": Dictionary with error, present only if parser saw some -/// error. Contains the following keys: -/// - "message": String, error message in printf format, translated. -/// Must contain exactly one "%.*s". -/// - "arg": String, error message argument. -/// - "len": Amount of bytes successfully parsed. With flags equal to "" -/// that should be equal to the length of expr string. -/// (“Successfully parsed” here means “participated in AST -/// creation”, not “till the first error”.) -/// - "ast": AST, either nil or a dictionary with these keys: -/// - "type": node type, one of the value names from ExprASTNodeType -/// stringified without "kExprNode" prefix. -/// - "start": a pair [line, column] describing where node is "started" -/// where "line" is always 0 (will not be 0 if you will be -/// using nvim_parse_viml() on e.g. ":let", but that is not -/// present yet). Both elements are Integers. -/// - "len": “length” of the node. This and "start" are there for -/// debugging purposes primary (debugging parser and providing -/// debug information). -/// - "children": a list of nodes described in top/"ast". There always -/// is zero, one or two children, key will not be present -/// if node has no children. Maximum number of children -/// may be found in node_maxchildren array. -/// - Local values (present only for certain nodes): -/// - "scope": a single Integer, specifies scope for "Option" and -/// "PlainIdentifier" nodes. For "Option" it is one of -/// ExprOptScope values, for "PlainIdentifier" it is one of -/// ExprVarScope values. -/// - "ident": identifier (without scope, if any), present for "Option", -/// "PlainIdentifier", "PlainKey" and "Environment" nodes. -/// - "name": Integer, register name (one character) or -1. Only present -/// for "Register" nodes. -/// - "cmp_type": String, comparison type, one of the value names from -/// ExprComparisonType, stringified without "kExprCmp" -/// prefix. Only present for "Comparison" nodes. -/// - "ccs_strategy": String, case comparison strategy, one of the -/// value names from ExprCaseCompareStrategy, -/// stringified without "kCCStrategy" prefix. Only -/// present for "Comparison" nodes. -/// - "augmentation": String, augmentation type for "Assignment" nodes. -/// Is either an empty string, "Add", "Subtract" or -/// "Concat" for "=", "+=", "-=" or ".=" respectively. -/// - "invert": Boolean, true if result of comparison needs to be -/// inverted. Only present for "Comparison" nodes. -/// - "ivalue": Integer, integer value for "Integer" nodes. -/// - "fvalue": Float, floating-point value for "Float" nodes. -/// - "svalue": String, value for "SingleQuotedString" and -/// "DoubleQuotedString" nodes. -/// @param[out] err Error details, if any -Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, Error *err) - FUNC_API_SINCE(4) FUNC_API_FAST -{ - int pflags = 0; - for (size_t i = 0 ; i < flags.size ; i++) { - switch (flags.data[i]) { - case 'm': - pflags |= kExprFlagsMulti; break; - case 'E': - pflags |= kExprFlagsDisallowEOC; break; - case 'l': - pflags |= kExprFlagsParseLet; break; - case NUL: - api_set_error(err, kErrorTypeValidation, "Invalid flag: '\\0' (%u)", - (unsigned)flags.data[i]); - return (Dictionary)ARRAY_DICT_INIT; - default: - api_set_error(err, kErrorTypeValidation, "Invalid flag: '%c' (%u)", - flags.data[i], (unsigned)flags.data[i]); - return (Dictionary)ARRAY_DICT_INIT; - } - } - ParserLine parser_lines[] = { - { - .data = expr.data, - .size = expr.size, - .allocated = false, - }, - { NULL, 0, false }, - }; - ParserLine *plines_p = parser_lines; - ParserHighlight colors; - kvi_init(colors); - ParserHighlight *const colors_p = (highlight ? &colors : NULL); - ParserState pstate; - viml_parser_init(&pstate, parser_simple_get_line, &plines_p, colors_p); - ExprAST east = viml_pexpr_parse(&pstate, pflags); - - const size_t ret_size = ( - 2 // "ast", "len" - + (size_t)(east.err.msg != NULL) // "error" - + (size_t)highlight // "highlight" - + 0); - Dictionary ret = { - .items = xmalloc(ret_size * sizeof(ret.items[0])), - .size = 0, - .capacity = ret_size, - }; - ret.items[ret.size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ast"), - .value = NIL, - }; - ret.items[ret.size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("len"), - .value = INTEGER_OBJ((Integer)(pstate.pos.line == 1 - ? parser_lines[0].size - : pstate.pos.col)), - }; - if (east.err.msg != NULL) { - Dictionary err_dict = { - .items = xmalloc(2 * sizeof(err_dict.items[0])), - .size = 2, - .capacity = 2, - }; - err_dict.items[0] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("message"), - .value = STRING_OBJ(cstr_to_string(east.err.msg)), - }; - if (east.err.arg == NULL) { - err_dict.items[1] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("arg"), - .value = STRING_OBJ(STRING_INIT), - }; - } else { - err_dict.items[1] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("arg"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(east.err.arg, (size_t)east.err.arg_len), - .size = (size_t)east.err.arg_len, - })), - }; - } - ret.items[ret.size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("error"), - .value = DICTIONARY_OBJ(err_dict), - }; - } - if (highlight) { - Array hl = (Array) { - .items = xmalloc(kv_size(colors) * sizeof(hl.items[0])), - .capacity = kv_size(colors), - .size = kv_size(colors), - }; - for (size_t i = 0 ; i < kv_size(colors) ; i++) { - const ParserHighlightChunk chunk = kv_A(colors, i); - Array chunk_arr = (Array) { - .items = xmalloc(4 * sizeof(chunk_arr.items[0])), - .capacity = 4, - .size = 4, - }; - chunk_arr.items[0] = INTEGER_OBJ((Integer)chunk.start.line); - chunk_arr.items[1] = INTEGER_OBJ((Integer)chunk.start.col); - chunk_arr.items[2] = INTEGER_OBJ((Integer)chunk.end_col); - chunk_arr.items[3] = STRING_OBJ(cstr_to_string(chunk.group)); - hl.items[i] = ARRAY_OBJ(chunk_arr); - } - ret.items[ret.size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("highlight"), - .value = ARRAY_OBJ(hl), - }; - } - kvi_destroy(colors); - - // Walk over the AST, freeing nodes in process. - ExprASTConvStack ast_conv_stack; - kvi_init(ast_conv_stack); - kvi_push(ast_conv_stack, ((ExprASTConvStackItem) { - .node_p = &east.root, - .ret_node_p = &ret.items[0].value, - })); - while (kv_size(ast_conv_stack)) { - ExprASTConvStackItem cur_item = kv_last(ast_conv_stack); - ExprASTNode *const node = *cur_item.node_p; - if (node == NULL) { - assert(kv_size(ast_conv_stack) == 1); - kv_drop(ast_conv_stack, 1); - } else { - if (cur_item.ret_node_p->type == kObjectTypeNil) { - const size_t ret_node_items_size = (size_t)( - 3 // "type", "start" and "len" - + (node->children != NULL) // "children" - + (node->type == kExprNodeOption - || node->type == kExprNodePlainIdentifier) // "scope" - + (node->type == kExprNodeOption - || node->type == kExprNodePlainIdentifier - || node->type == kExprNodePlainKey - || node->type == kExprNodeEnvironment) // "ident" - + (node->type == kExprNodeRegister) // "name" - + (3 // "cmp_type", "ccs_strategy", "invert" - * (node->type == kExprNodeComparison)) - + (node->type == kExprNodeInteger) // "ivalue" - + (node->type == kExprNodeFloat) // "fvalue" - + (node->type == kExprNodeDoubleQuotedString - || node->type == kExprNodeSingleQuotedString) // "svalue" - + (node->type == kExprNodeAssignment) // "augmentation" - + 0); - Dictionary ret_node = { - .items = xmalloc(ret_node_items_size * sizeof(ret_node.items[0])), - .capacity = ret_node_items_size, - .size = 0, - }; - *cur_item.ret_node_p = DICTIONARY_OBJ(ret_node); - } - Dictionary *ret_node = &cur_item.ret_node_p->data.dictionary; - if (node->children != NULL) { - const size_t num_children = 1 + (node->children->next != NULL); - Array children_array = { - .items = xmalloc(num_children * sizeof(children_array.items[0])), - .capacity = num_children, - .size = num_children, - }; - for (size_t i = 0; i < num_children; i++) { - children_array.items[i] = NIL; - } - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("children"), - .value = ARRAY_OBJ(children_array), - }; - kvi_push(ast_conv_stack, ((ExprASTConvStackItem) { - .node_p = &node->children, - .ret_node_p = &children_array.items[0], - })); - } else if (node->next != NULL) { - kvi_push(ast_conv_stack, ((ExprASTConvStackItem) { - .node_p = &node->next, - .ret_node_p = cur_item.ret_node_p + 1, - })); - } else { - kv_drop(ast_conv_stack, 1); - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("type"), - .value = STRING_OBJ(cstr_to_string(east_node_type_tab[node->type])), - }; - Array start_array = { - .items = xmalloc(2 * sizeof(start_array.items[0])), - .capacity = 2, - .size = 2, - }; - start_array.items[0] = INTEGER_OBJ((Integer)node->start.line); - start_array.items[1] = INTEGER_OBJ((Integer)node->start.col); - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("start"), - .value = ARRAY_OBJ(start_array), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("len"), - .value = INTEGER_OBJ((Integer)node->len), - }; - switch (node->type) { - case kExprNodeDoubleQuotedString: - case kExprNodeSingleQuotedString: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("svalue"), - .value = STRING_OBJ(((String) { - .data = node->data.str.value, - .size = node->data.str.size, - })), - }; - break; - case kExprNodeOption: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("scope"), - .value = INTEGER_OBJ(node->data.opt.scope), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ident"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(node->data.opt.ident, - node->data.opt.ident_len), - .size = node->data.opt.ident_len, - })), - }; - break; - case kExprNodePlainIdentifier: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("scope"), - .value = INTEGER_OBJ(node->data.var.scope), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ident"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(node->data.var.ident, - node->data.var.ident_len), - .size = node->data.var.ident_len, - })), - }; - break; - case kExprNodePlainKey: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ident"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(node->data.var.ident, - node->data.var.ident_len), - .size = node->data.var.ident_len, - })), - }; - break; - case kExprNodeEnvironment: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ident"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(node->data.env.ident, - node->data.env.ident_len), - .size = node->data.env.ident_len, - })), - }; - break; - case kExprNodeRegister: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("name"), - .value = INTEGER_OBJ(node->data.reg.name), - }; - break; - case kExprNodeComparison: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("cmp_type"), - .value = STRING_OBJ(cstr_to_string(eltkn_cmp_type_tab[node->data.cmp.type])), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ccs_strategy"), - .value = STRING_OBJ(cstr_to_string(ccs_tab[node->data.cmp.ccs])), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("invert"), - .value = BOOLEAN_OBJ(node->data.cmp.inv), - }; - break; - case kExprNodeFloat: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("fvalue"), - .value = FLOAT_OBJ(node->data.flt.value), - }; - break; - case kExprNodeInteger: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ivalue"), - .value = INTEGER_OBJ((Integer)( - node->data.num.value > API_INTEGER_MAX - ? API_INTEGER_MAX - : (Integer)node->data.num.value)), - }; - break; - case kExprNodeAssignment: { - const ExprAssignmentType asgn_type = node->data.ass.type; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("augmentation"), - .value = STRING_OBJ(asgn_type == kExprAsgnPlain - ? (String)STRING_INIT - : cstr_to_string(expr_asgn_type_tab[asgn_type])), - }; - break; - } - case kExprNodeMissing: - case kExprNodeOpMissing: - case kExprNodeTernary: - case kExprNodeTernaryValue: - case kExprNodeSubscript: - case kExprNodeListLiteral: - case kExprNodeUnaryPlus: - case kExprNodeBinaryPlus: - case kExprNodeNested: - case kExprNodeCall: - case kExprNodeComplexIdentifier: - case kExprNodeUnknownFigure: - case kExprNodeLambda: - case kExprNodeDictLiteral: - case kExprNodeCurlyBracesIdentifier: - case kExprNodeComma: - case kExprNodeColon: - case kExprNodeArrow: - case kExprNodeConcat: - case kExprNodeConcatOrSubscript: - case kExprNodeOr: - case kExprNodeAnd: - case kExprNodeUnaryMinus: - case kExprNodeBinaryMinus: - case kExprNodeNot: - case kExprNodeMultiplication: - case kExprNodeDivision: - case kExprNodeMod: - break; - } - assert(cur_item.ret_node_p->data.dictionary.size - == cur_item.ret_node_p->data.dictionary.capacity); - xfree(*cur_item.node_p); - *cur_item.node_p = NULL; - } - } - } - kvi_destroy(ast_conv_stack); - - assert(ret.size == ret.capacity); - // Should be a no-op actually, leaving it in case non-nodes will need to be - // freed later. - viml_pexpr_free_ast(east); - viml_parser_destroy(&pstate); - return ret; -} - - /// Writes a message to vim output or error buffer. The string is split /// and flushed after each newline. Incomplete lines are kept for writing /// later. @@ -2460,11 +1725,10 @@ 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((char_u *)line_buf); \ + msg(line_buf); \ pos = 0; \ continue; \ } \ - \ line_buf[pos++] = message.data[i]; ++no_wait_return; @@ -2714,96 +1978,6 @@ void nvim__screenshot(String path) ui_call_screenshot(path); } -/// Set or change decoration provider for a namespace -/// -/// This is a very general purpose interface for having lua callbacks -/// being triggered during the redraw code. -/// -/// The expected usage is to set extmarks for the currently -/// redrawn buffer. |nvim_buf_set_extmark| can be called to add marks -/// on a per-window or per-lines basis. Use the `ephemeral` key to only -/// use the mark for the current screen redraw (the callback will be called -/// again for the next redraw ). -/// -/// Note: this function should not be called often. Rather, the callbacks -/// themselves can be used to throttle unneeded callbacks. the `on_start` -/// callback can return `false` to disable the provider until the next redraw. -/// Similarly, return `false` in `on_win` will skip the `on_lines` calls -/// for that window (but any extmarks set in `on_win` will still be used). -/// A plugin managing multiple sources of decoration should ideally only set -/// one provider, and merge the sources internally. You can use multiple `ns_id` -/// for the extmarks set/modified inside the callback anyway. -/// -/// Note: doing anything other than setting extmarks is considered experimental. -/// Doing things like changing options are not expliticly forbidden, but is -/// likely to have unexpected consequences (such as 100% CPU consumption). -/// doing `vim.rpcnotify` should be OK, but `vim.rpcrequest` is quite dubious -/// for the moment. -/// -/// @param ns_id Namespace id from |nvim_create_namespace()| -/// @param opts Callbacks invoked during redraw: -/// - on_start: called first on each screen redraw -/// ["start", tick] -/// - on_buf: called for each buffer being redrawn (before window -/// callbacks) -/// ["buf", bufnr, tick] -/// - on_win: called when starting to redraw a specific window. -/// ["win", winid, bufnr, topline, botline_guess] -/// - on_line: called for each buffer line being redrawn. (The -/// interation with fold lines is subject to change) -/// ["win", winid, bufnr, row] -/// - on_end: called at the end of a redraw cycle -/// ["end", tick] -void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, Error *err) - FUNC_API_SINCE(7) FUNC_API_LUA_ONLY -{ - DecorProvider *p = get_decor_provider((NS)ns_id, true); - assert(p != NULL); - decor_provider_clear(p); - - // regardless of what happens, it seems good idea to redraw - redraw_all_later(NOT_VALID); // TODO(bfredl): too soon? - - struct { - const char *name; - LuaRef *dest; - } cbs[] = { - { "on_start", &p->redraw_start }, - { "on_buf", &p->redraw_buf }, - { "on_win", &p->redraw_win }, - { "on_line", &p->redraw_line }, - { "on_end", &p->redraw_end }, - { "_on_hl_def", &p->hl_def }, - { NULL, NULL }, - }; - - for (size_t i = 0; i < opts.size; i++) { - String k = opts.items[i].key; - Object *v = &opts.items[i].value; - size_t j; - for (j = 0; cbs[j].name && cbs[j].dest; j++) { - if (strequal(cbs[j].name, k.data)) { - if (v->type != kObjectTypeLuaRef) { - api_set_error(err, kErrorTypeValidation, - "%s is not a function", cbs[j].name); - goto error; - } - *(cbs[j].dest) = v->data.luaref; - v->data.luaref = LUA_NOREF; - break; - } - } - if (!cbs[j].name) { - api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); - goto error; - } - } - - p->active = true; - return; -error: - decor_provider_clear(p); -} /// Deletes a uppercase/file named mark. See |mark-motions|. /// @@ -2840,11 +2014,12 @@ Boolean nvim_del_mark(String name, Error *err) /// /// @note fails with error if a lowercase or buffer local named mark is used. /// @param name Mark name +/// @param opts Optional parameters. Reserved for future use. /// @return 4-tuple (row, col, buffer, buffername), (0, 0, 0, '') if the mark is /// not set. /// @see |nvim_buf_set_mark()| /// @see |nvim_del_mark()| -Array nvim_get_mark(String name, Error *err) +Array nvim_get_mark(String name, Dictionary opts, Error *err) FUNC_API_SINCE(8) { Array rv = ARRAY_DICT_INIT; @@ -3008,16 +2183,15 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * int p_crb_save = ewp->w_p_crb; ewp->w_p_crb = false; - int width = build_stl_str_hl( - ewp, - (char_u *)buf, - sizeof(buf), - (char_u *)str.data, - false, - (char_u)fillchar, - maxwidth, - hltab_ptr, - NULL); + int width = build_stl_str_hl(ewp, + (char_u *)buf, + sizeof(buf), + (char_u *)str.data, + false, + (char_u)fillchar, + maxwidth, + hltab_ptr, + NULL); PUT(result, "width", INTEGER_OBJ(width)); diff --git a/src/nvim/api/vim.h b/src/nvim/api/vim.h index 4fd353ce5c..de56c67665 100644 --- a/src/nvim/api/vim.h +++ b/src/nvim/api/vim.h @@ -1,13 +1,7 @@ #ifndef NVIM_API_VIM_H #define NVIM_API_VIM_H -#include <stdint.h> - #include "nvim/api/private/defs.h" -#include "nvim/map.h" - -EXTERN Map(String, handle_T) namespace_ids INIT(= MAP_INIT); -EXTERN handle_T next_namespace_id INIT(= 1); #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/vim.h.generated.h" diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c new file mode 100644 index 0000000000..c516cedaf4 --- /dev/null +++ b/src/nvim/api/vimscript.c @@ -0,0 +1,733 @@ +// 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 <limits.h> +#include <stdlib.h> + +#include "nvim/api/private/converter.h" +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/api/vimscript.h" +#include "nvim/ascii.h" +#include "nvim/eval.h" +#include "nvim/eval/typval.h" +#include "nvim/eval/userfunc.h" +#include "nvim/ex_cmds2.h" +#include "nvim/viml/parser/expressions.h" +#include "nvim/viml/parser/parser.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "api/vimscript.c.generated.h" +#endif + +/// Executes Vimscript (multiline block of Ex-commands), like anonymous +/// |:source|. +/// +/// Unlike |nvim_command()| this function supports heredocs, script-scope (s:), +/// etc. +/// +/// On execution error: fails with VimL error, does not update v:errmsg. +/// +/// @see |execute()| +/// @see |nvim_command()| +/// +/// @param src Vimscript code +/// @param output Capture and return all (non-error, non-shell |:!|) output +/// @param[out] err Error details (Vim error), if any +/// @return Output (non-error, non-shell |:!|) if `output` is true, +/// else empty string. +String nvim_exec(String src, Boolean output, Error *err) + FUNC_API_SINCE(7) +{ + const int save_msg_silent = msg_silent; + garray_T *const save_capture_ga = capture_ga; + garray_T capture_local; + if (output) { + ga_init(&capture_local, 1, 80); + capture_ga = &capture_local; + } + + try_start(); + if (output) { + msg_silent++; + } + do_source_str(src.data, "nvim_exec()"); + if (output) { + capture_ga = save_capture_ga; + msg_silent = save_msg_silent; + } + try_end(err); + + if (ERROR_SET(err)) { + goto theend; + } + + if (output && capture_local.ga_len > 1) { + String s = (String){ + .data = capture_local.ga_data, + .size = (size_t)capture_local.ga_len, + }; + // redir usually (except :echon) prepends a newline. + if (s.data[0] == '\n') { + memmove(s.data, s.data + 1, s.size - 1); + s.data[s.size - 1] = '\0'; + s.size = s.size - 1; + } + return s; // Caller will free the memory. + } +theend: + if (output) { + ga_clear(&capture_local); + } + return (String)STRING_INIT; +} + +/// Executes an ex-command. +/// +/// On execution error: fails with VimL error, does not update v:errmsg. +/// +/// @see |nvim_exec()| +/// +/// @param command Ex-command string +/// @param[out] err Error details (Vim error), if any +void nvim_command(String command, Error *err) + FUNC_API_SINCE(1) +{ + try_start(); + do_cmdline_cmd(command.data); + try_end(err); +} + +/// Evaluates a VimL |expression|. +/// Dictionaries and Lists are recursively expanded. +/// +/// On execution error: fails with VimL error, does not update v:errmsg. +/// +/// @param expr VimL expression string +/// @param[out] err Error details, if any +/// @return Evaluation result or expanded object +Object nvim_eval(String expr, Error *err) + FUNC_API_SINCE(1) +{ + static int recursive = 0; // recursion depth + Object rv = OBJECT_INIT; + + TRY_WRAP({ + // Initialize `force_abort` and `suppress_errthrow` at the top level. + if (!recursive) { + force_abort = false; + suppress_errthrow = false; + current_exception = NULL; + // `did_emsg` is set by emsg(), which cancels execution. + did_emsg = false; + } + recursive++; + try_start(); + + typval_T rettv; + int ok = eval0((char_u *)expr.data, &rettv, NULL, true); + + if (!try_end(err)) { + if (ok == FAIL) { + // Should never happen, try_end() should get the error. #8371 + api_set_error(err, kErrorTypeException, + "Failed to evaluate expression: '%.*s'", 256, expr.data); + } else { + rv = vim_to_object(&rettv); + } + } + + tv_clear(&rettv); + recursive--; + }); + + return rv; +} + +/// Calls a VimL function. +/// +/// @param fn Function name +/// @param args Function arguments +/// @param self `self` dict, or NULL for non-dict functions +/// @param[out] err Error details, if any +/// @return Result of the function call +static Object _call_function(String fn, Array args, dict_T *self, Error *err) +{ + static int recursive = 0; // recursion depth + Object rv = OBJECT_INIT; + + if (args.size > MAX_FUNC_ARGS) { + api_set_error(err, kErrorTypeValidation, + "Function called with too many arguments"); + return rv; + } + + // Convert the arguments in args from Object to typval_T values + typval_T vim_args[MAX_FUNC_ARGS + 1]; + size_t i = 0; // also used for freeing the variables + for (; i < args.size; i++) { + if (!object_to_vim(args.items[i], &vim_args[i], err)) { + goto free_vim_args; + } + } + + TRY_WRAP({ + // Initialize `force_abort` and `suppress_errthrow` at the top level. + if (!recursive) { + force_abort = false; + suppress_errthrow = false; + current_exception = NULL; + // `did_emsg` is set by emsg(), which cancels execution. + did_emsg = false; + } + recursive++; + try_start(); + typval_T rettv; + funcexe_T funcexe = FUNCEXE_INIT; + funcexe.firstline = curwin->w_cursor.lnum; + funcexe.lastline = curwin->w_cursor.lnum; + funcexe.evaluate = true; + funcexe.selfdict = self; + // call_func() retval is deceptive, ignore it. Instead we set `msg_list` + // (see above) to capture abort-causing non-exception errors. + (void)call_func((char_u *)fn.data, (int)fn.size, &rettv, (int)args.size, + vim_args, &funcexe); + if (!try_end(err)) { + rv = vim_to_object(&rettv); + } + tv_clear(&rettv); + recursive--; + }); + +free_vim_args: + while (i > 0) { + tv_clear(&vim_args[--i]); + } + + return rv; +} + +/// Calls a VimL function with the given arguments. +/// +/// On execution error: fails with VimL error, does not update v:errmsg. +/// +/// @param fn Function to call +/// @param args Function arguments packed in an Array +/// @param[out] err Error details, if any +/// @return Result of the function call +Object nvim_call_function(String fn, Array args, Error *err) + FUNC_API_SINCE(1) +{ + return _call_function(fn, args, NULL, err); +} + +/// Calls a VimL |Dictionary-function| with the given arguments. +/// +/// On execution error: fails with VimL error, does not update v:errmsg. +/// +/// @param dict Dictionary, or String evaluating to a VimL |self| dict +/// @param fn Name of the function defined on the VimL dict +/// @param args Function arguments packed in an Array +/// @param[out] err Error details, if any +/// @return Result of the function call +Object nvim_call_dict_function(Object dict, String fn, Array args, Error *err) + FUNC_API_SINCE(4) +{ + Object rv = OBJECT_INIT; + + typval_T rettv; + bool mustfree = false; + switch (dict.type) { + case kObjectTypeString: + try_start(); + if (eval0((char_u *)dict.data.string.data, &rettv, NULL, true) == FAIL) { + api_set_error(err, kErrorTypeException, + "Failed to evaluate dict expression"); + } + if (try_end(err)) { + return rv; + } + // Evaluation of the string arg created a new dict or increased the + // refcount of a dict. Not necessary for a RPC dict. + mustfree = true; + break; + case kObjectTypeDictionary: + if (!object_to_vim(dict, &rettv, err)) { + goto end; + } + break; + default: + api_set_error(err, kErrorTypeValidation, + "dict argument type must be String or Dictionary"); + return rv; + } + dict_T *self_dict = rettv.vval.v_dict; + if (rettv.v_type != VAR_DICT || !self_dict) { + api_set_error(err, kErrorTypeValidation, "dict not found"); + goto end; + } + + if (fn.data && fn.size > 0 && dict.type != kObjectTypeDictionary) { + dictitem_T *const di = tv_dict_find(self_dict, fn.data, (ptrdiff_t)fn.size); + if (di == NULL) { + api_set_error(err, kErrorTypeValidation, "Not found: %s", fn.data); + goto end; + } + if (di->di_tv.v_type == VAR_PARTIAL) { + api_set_error(err, kErrorTypeValidation, + "partial function not supported"); + goto end; + } + if (di->di_tv.v_type != VAR_FUNC) { + api_set_error(err, kErrorTypeValidation, "Not a function: %s", fn.data); + goto end; + } + fn = (String) { + .data = (char *)di->di_tv.vval.v_string, + .size = STRLEN(di->di_tv.vval.v_string), + }; + } + + if (!fn.data || fn.size < 1) { + api_set_error(err, kErrorTypeValidation, "Invalid (empty) function name"); + goto end; + } + + rv = _call_function(fn, args, self_dict, err); +end: + if (mustfree) { + tv_clear(&rettv); + } + + return rv; +} + +typedef struct { + ExprASTNode **node_p; + Object *ret_node_p; +} ExprASTConvStackItem; + +/// @cond DOXYGEN_NOT_A_FUNCTION +typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; +/// @endcond + +/// Parse a VimL expression. +/// +/// @param[in] expr Expression to parse. Always treated as a single line. +/// @param[in] flags Flags: +/// - "m" if multiple expressions in a row are allowed (only +/// the first one will be parsed), +/// - "E" if EOC tokens are not allowed (determines whether +/// they will stop parsing process or be recognized as an +/// operator/space, though also yielding an error). +/// - "l" when needing to start parsing with lvalues for +/// ":let" or ":for". +/// Common flag sets: +/// - "m" to parse like for ":echo". +/// - "E" to parse like for "<C-r>=". +/// - empty string for ":call". +/// - "lm" to parse for ":let". +/// @param[in] highlight If true, return value will also include "highlight" +/// key containing array of 4-tuples (arrays) (Integer, +/// Integer, Integer, String), where first three numbers +/// define the highlighted region and represent line, +/// starting column and ending column (latter exclusive: +/// one should highlight region [start_col, end_col)). +/// +/// @return +/// - AST: top-level dictionary with these keys: +/// - "error": Dictionary with error, present only if parser saw some +/// error. Contains the following keys: +/// - "message": String, error message in printf format, translated. +/// Must contain exactly one "%.*s". +/// - "arg": String, error message argument. +/// - "len": Amount of bytes successfully parsed. With flags equal to "" +/// that should be equal to the length of expr string. +/// (“Successfully parsed” here means “participated in AST +/// creation”, not “till the first error”.) +/// - "ast": AST, either nil or a dictionary with these keys: +/// - "type": node type, one of the value names from ExprASTNodeType +/// stringified without "kExprNode" prefix. +/// - "start": a pair [line, column] describing where node is "started" +/// where "line" is always 0 (will not be 0 if you will be +/// using nvim_parse_viml() on e.g. ":let", but that is not +/// present yet). Both elements are Integers. +/// - "len": “length” of the node. This and "start" are there for +/// debugging purposes primary (debugging parser and providing +/// debug information). +/// - "children": a list of nodes described in top/"ast". There always +/// is zero, one or two children, key will not be present +/// if node has no children. Maximum number of children +/// may be found in node_maxchildren array. +/// - Local values (present only for certain nodes): +/// - "scope": a single Integer, specifies scope for "Option" and +/// "PlainIdentifier" nodes. For "Option" it is one of +/// ExprOptScope values, for "PlainIdentifier" it is one of +/// ExprVarScope values. +/// - "ident": identifier (without scope, if any), present for "Option", +/// "PlainIdentifier", "PlainKey" and "Environment" nodes. +/// - "name": Integer, register name (one character) or -1. Only present +/// for "Register" nodes. +/// - "cmp_type": String, comparison type, one of the value names from +/// ExprComparisonType, stringified without "kExprCmp" +/// prefix. Only present for "Comparison" nodes. +/// - "ccs_strategy": String, case comparison strategy, one of the +/// value names from ExprCaseCompareStrategy, +/// stringified without "kCCStrategy" prefix. Only +/// present for "Comparison" nodes. +/// - "augmentation": String, augmentation type for "Assignment" nodes. +/// Is either an empty string, "Add", "Subtract" or +/// "Concat" for "=", "+=", "-=" or ".=" respectively. +/// - "invert": Boolean, true if result of comparison needs to be +/// inverted. Only present for "Comparison" nodes. +/// - "ivalue": Integer, integer value for "Integer" nodes. +/// - "fvalue": Float, floating-point value for "Float" nodes. +/// - "svalue": String, value for "SingleQuotedString" and +/// "DoubleQuotedString" nodes. +/// @param[out] err Error details, if any +Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, Error *err) + FUNC_API_SINCE(4) FUNC_API_FAST +{ + int pflags = 0; + for (size_t i = 0 ; i < flags.size ; i++) { + switch (flags.data[i]) { + case 'm': + pflags |= kExprFlagsMulti; break; + case 'E': + pflags |= kExprFlagsDisallowEOC; break; + case 'l': + pflags |= kExprFlagsParseLet; break; + case NUL: + api_set_error(err, kErrorTypeValidation, "Invalid flag: '\\0' (%u)", + (unsigned)flags.data[i]); + return (Dictionary)ARRAY_DICT_INIT; + default: + api_set_error(err, kErrorTypeValidation, "Invalid flag: '%c' (%u)", + flags.data[i], (unsigned)flags.data[i]); + return (Dictionary)ARRAY_DICT_INIT; + } + } + ParserLine parser_lines[] = { + { + .data = expr.data, + .size = expr.size, + .allocated = false, + }, + { NULL, 0, false }, + }; + ParserLine *plines_p = parser_lines; + ParserHighlight colors; + kvi_init(colors); + ParserHighlight *const colors_p = (highlight ? &colors : NULL); + ParserState pstate; + viml_parser_init(&pstate, parser_simple_get_line, &plines_p, colors_p); + ExprAST east = viml_pexpr_parse(&pstate, pflags); + + const size_t ret_size = (2 // "ast", "len" + + (size_t)(east.err.msg != NULL) // "error" + + (size_t)highlight // "highlight" + + 0); + Dictionary ret = { + .items = xmalloc(ret_size * sizeof(ret.items[0])), + .size = 0, + .capacity = ret_size, + }; + ret.items[ret.size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ast"), + .value = NIL, + }; + ret.items[ret.size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("len"), + .value = INTEGER_OBJ((Integer)(pstate.pos.line == 1 + ? parser_lines[0].size + : pstate.pos.col)), + }; + if (east.err.msg != NULL) { + Dictionary err_dict = { + .items = xmalloc(2 * sizeof(err_dict.items[0])), + .size = 2, + .capacity = 2, + }; + err_dict.items[0] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("message"), + .value = STRING_OBJ(cstr_to_string(east.err.msg)), + }; + if (east.err.arg == NULL) { + err_dict.items[1] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("arg"), + .value = STRING_OBJ(STRING_INIT), + }; + } else { + err_dict.items[1] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("arg"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(east.err.arg, (size_t)east.err.arg_len), + .size = (size_t)east.err.arg_len, + })), + }; + } + ret.items[ret.size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("error"), + .value = DICTIONARY_OBJ(err_dict), + }; + } + if (highlight) { + Array hl = (Array) { + .items = xmalloc(kv_size(colors) * sizeof(hl.items[0])), + .capacity = kv_size(colors), + .size = kv_size(colors), + }; + for (size_t i = 0 ; i < kv_size(colors) ; i++) { + const ParserHighlightChunk chunk = kv_A(colors, i); + Array chunk_arr = (Array) { + .items = xmalloc(4 * sizeof(chunk_arr.items[0])), + .capacity = 4, + .size = 4, + }; + chunk_arr.items[0] = INTEGER_OBJ((Integer)chunk.start.line); + chunk_arr.items[1] = INTEGER_OBJ((Integer)chunk.start.col); + chunk_arr.items[2] = INTEGER_OBJ((Integer)chunk.end_col); + chunk_arr.items[3] = STRING_OBJ(cstr_to_string(chunk.group)); + hl.items[i] = ARRAY_OBJ(chunk_arr); + } + ret.items[ret.size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("highlight"), + .value = ARRAY_OBJ(hl), + }; + } + kvi_destroy(colors); + + // Walk over the AST, freeing nodes in process. + ExprASTConvStack ast_conv_stack; + kvi_init(ast_conv_stack); + kvi_push(ast_conv_stack, ((ExprASTConvStackItem) { + .node_p = &east.root, + .ret_node_p = &ret.items[0].value, + })); + while (kv_size(ast_conv_stack)) { + ExprASTConvStackItem cur_item = kv_last(ast_conv_stack); + ExprASTNode *const node = *cur_item.node_p; + if (node == NULL) { + assert(kv_size(ast_conv_stack) == 1); + kv_drop(ast_conv_stack, 1); + } else { + if (cur_item.ret_node_p->type == kObjectTypeNil) { + size_t items_size = (size_t)(3 // "type", "start" and "len" + + (node->children != NULL) // "children" + + (node->type == kExprNodeOption + || node->type == kExprNodePlainIdentifier) // "scope" + + (node->type == kExprNodeOption + || node->type == kExprNodePlainIdentifier + || node->type == kExprNodePlainKey + || node->type == kExprNodeEnvironment) // "ident" + + (node->type == kExprNodeRegister) // "name" + + (3 // "cmp_type", "ccs_strategy", "invert" + * (node->type == kExprNodeComparison)) + + (node->type == kExprNodeInteger) // "ivalue" + + (node->type == kExprNodeFloat) // "fvalue" + + (node->type == kExprNodeDoubleQuotedString + || node->type == kExprNodeSingleQuotedString) // "svalue" + + (node->type == kExprNodeAssignment) // "augmentation" + + 0); + Dictionary ret_node = { + .items = xmalloc(items_size * sizeof(ret_node.items[0])), + .capacity = items_size, + .size = 0, + }; + *cur_item.ret_node_p = DICTIONARY_OBJ(ret_node); + } + Dictionary *ret_node = &cur_item.ret_node_p->data.dictionary; + if (node->children != NULL) { + const size_t num_children = 1 + (node->children->next != NULL); + Array children_array = { + .items = xmalloc(num_children * sizeof(children_array.items[0])), + .capacity = num_children, + .size = num_children, + }; + for (size_t i = 0; i < num_children; i++) { + children_array.items[i] = NIL; + } + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("children"), + .value = ARRAY_OBJ(children_array), + }; + kvi_push(ast_conv_stack, ((ExprASTConvStackItem) { + .node_p = &node->children, + .ret_node_p = &children_array.items[0], + })); + } else if (node->next != NULL) { + kvi_push(ast_conv_stack, ((ExprASTConvStackItem) { + .node_p = &node->next, + .ret_node_p = cur_item.ret_node_p + 1, + })); + } else { + kv_drop(ast_conv_stack, 1); + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("type"), + .value = STRING_OBJ(cstr_to_string(east_node_type_tab[node->type])), + }; + Array start_array = { + .items = xmalloc(2 * sizeof(start_array.items[0])), + .capacity = 2, + .size = 2, + }; + start_array.items[0] = INTEGER_OBJ((Integer)node->start.line); + start_array.items[1] = INTEGER_OBJ((Integer)node->start.col); + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("start"), + .value = ARRAY_OBJ(start_array), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("len"), + .value = INTEGER_OBJ((Integer)node->len), + }; + switch (node->type) { + case kExprNodeDoubleQuotedString: + case kExprNodeSingleQuotedString: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("svalue"), + .value = STRING_OBJ(((String) { + .data = node->data.str.value, + .size = node->data.str.size, + })), + }; + break; + case kExprNodeOption: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("scope"), + .value = INTEGER_OBJ(node->data.opt.scope), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ident"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(node->data.opt.ident, + node->data.opt.ident_len), + .size = node->data.opt.ident_len, + })), + }; + break; + case kExprNodePlainIdentifier: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("scope"), + .value = INTEGER_OBJ(node->data.var.scope), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ident"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(node->data.var.ident, + node->data.var.ident_len), + .size = node->data.var.ident_len, + })), + }; + break; + case kExprNodePlainKey: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ident"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(node->data.var.ident, + node->data.var.ident_len), + .size = node->data.var.ident_len, + })), + }; + break; + case kExprNodeEnvironment: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ident"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(node->data.env.ident, + node->data.env.ident_len), + .size = node->data.env.ident_len, + })), + }; + break; + case kExprNodeRegister: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("name"), + .value = INTEGER_OBJ(node->data.reg.name), + }; + break; + case kExprNodeComparison: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("cmp_type"), + .value = STRING_OBJ(cstr_to_string(eltkn_cmp_type_tab[node->data.cmp.type])), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ccs_strategy"), + .value = STRING_OBJ(cstr_to_string(ccs_tab[node->data.cmp.ccs])), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("invert"), + .value = BOOLEAN_OBJ(node->data.cmp.inv), + }; + break; + case kExprNodeFloat: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("fvalue"), + .value = FLOAT_OBJ(node->data.flt.value), + }; + break; + case kExprNodeInteger: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ivalue"), + .value = INTEGER_OBJ((Integer)(node->data.num.value > API_INTEGER_MAX + ? API_INTEGER_MAX + : (Integer)node->data.num.value)), + }; + break; + case kExprNodeAssignment: { + const ExprAssignmentType asgn_type = node->data.ass.type; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("augmentation"), + .value = STRING_OBJ(asgn_type == kExprAsgnPlain + ? (String)STRING_INIT + : cstr_to_string(expr_asgn_type_tab[asgn_type])), + }; + break; + } + case kExprNodeMissing: + case kExprNodeOpMissing: + case kExprNodeTernary: + case kExprNodeTernaryValue: + case kExprNodeSubscript: + case kExprNodeListLiteral: + case kExprNodeUnaryPlus: + case kExprNodeBinaryPlus: + case kExprNodeNested: + case kExprNodeCall: + case kExprNodeComplexIdentifier: + case kExprNodeUnknownFigure: + case kExprNodeLambda: + case kExprNodeDictLiteral: + case kExprNodeCurlyBracesIdentifier: + case kExprNodeComma: + case kExprNodeColon: + case kExprNodeArrow: + case kExprNodeConcat: + case kExprNodeConcatOrSubscript: + case kExprNodeOr: + case kExprNodeAnd: + case kExprNodeUnaryMinus: + case kExprNodeBinaryMinus: + case kExprNodeNot: + case kExprNodeMultiplication: + case kExprNodeDivision: + case kExprNodeMod: + break; + } + assert(cur_item.ret_node_p->data.dictionary.size + == cur_item.ret_node_p->data.dictionary.capacity); + xfree(*cur_item.node_p); + *cur_item.node_p = NULL; + } + } + } + kvi_destroy(ast_conv_stack); + + assert(ret.size == ret.capacity); + // Should be a no-op actually, leaving it in case non-nodes will need to be + // freed later. + viml_pexpr_free_ast(east); + viml_parser_destroy(&pstate); + return ret; +} diff --git a/src/nvim/api/vimscript.h b/src/nvim/api/vimscript.h new file mode 100644 index 0000000000..be808b6b25 --- /dev/null +++ b/src/nvim/api/vimscript.h @@ -0,0 +1,9 @@ +#ifndef NVIM_API_VIMSCRIPT_H +#define NVIM_API_VIMSCRIPT_H + +#include "nvim/api/private/defs.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "api/vimscript.h.generated.h" +#endif +#endif // NVIM_API_VIMSCRIPT_H diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index d8105810aa..ceb7f71423 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -61,36 +61,36 @@ /// @param buffer Buffer to display, or 0 for current buffer /// @param enter Enter the window (make it the current window) /// @param config Map defining the window configuration. Keys: -/// - `relative`: Sets the window layout to "floating", placed at (row,col) +/// - relative: Sets the window layout to "floating", placed at (row,col) /// coordinates relative to: /// - "editor" The global editor grid /// - "win" Window given by the `win` field, or current window. /// - "cursor" Cursor position in current window. -/// - `win`: |window-ID| for relative="win". -/// - `anchor`: Decides which corner of the float to place at (row,col): +/// - win: |window-ID| for relative="win". +/// - anchor: Decides which corner of the float to place at (row,col): /// - "NW" northwest (default) /// - "NE" northeast /// - "SW" southwest /// - "SE" southeast -/// - `width`: Window width (in character cells). Minimum of 1. -/// - `height`: Window height (in character cells). Minimum of 1. -/// - `bufpos`: Places float relative to buffer text (only when +/// - width: Window width (in character cells). Minimum of 1. +/// - height: Window height (in character cells). Minimum of 1. +/// - bufpos: Places float relative to buffer text (only when /// relative="win"). Takes a tuple of zero-indexed [line, column]. /// `row` and `col` if given are applied relative to this /// position, else they default to: /// - `row=1` and `col=0` if `anchor` is "NW" or "NE" /// - `row=0` and `col=0` if `anchor` is "SW" or "SE" /// (thus like a tooltip near the buffer text). -/// - `row`: Row position in units of "screen cell height", may be fractional. -/// - `col`: Column position in units of "screen cell width", may be +/// - row: Row position in units of "screen cell height", may be fractional. +/// - col: Column position in units of "screen cell width", may be /// fractional. -/// - `focusable`: Enable focus by user actions (wincmds, mouse events). +/// - focusable: Enable focus by user actions (wincmds, mouse events). /// Defaults to true. Non-focusable windows can be entered by /// |nvim_set_current_win()|. -/// - `external`: GUI should display the window as an external +/// - external: GUI should display the window as an external /// top-level window. Currently accepts no other positioning /// configuration together with this. -/// - `zindex`: Stacking order. floats with higher `zindex` go on top on +/// - zindex: Stacking order. floats with higher `zindex` go on top on /// floats with lower indices. Must be larger than zero. The /// following screen elements have hard-coded z-indices: /// - 100: insert completion popupmenu @@ -99,7 +99,7 @@ /// The default value for floats are 50. In general, values below 100 are /// recommended, unless there is a good reason to overshadow builtin /// elements. -/// - `style`: Configure the appearance of the window. Currently only takes +/// - style: Configure the appearance of the window. Currently only takes /// one non-empty value: /// - "minimal" Nvim will display the window with many UI options /// disabled. This is useful when displaying a temporary @@ -110,7 +110,7 @@ /// end-of-buffer region is hidden by setting `eob` flag of /// 'fillchars' to a space char, and clearing the /// |EndOfBuffer| region in 'winhighlight'. -/// - `border`: Style of (optional) window border. This can either be a string +/// - border: Style of (optional) window border. This can either be a string /// or an array. The string values are /// - "none": No border (default). /// - "single": A single line box. @@ -134,7 +134,7 @@ /// By default, `FloatBorder` highlight is used, which links to `VertSplit` /// when not defined. It could also be specified by character: /// [ {"+", "MyCorner"}, {"x", "MyBorder"} ]. -/// - `noautocmd`: If true then no buffer-related autocommand events such as +/// - noautocmd: If true then no buffer-related autocommand events such as /// |BufEnter|, |BufLeave| or |BufWinEnter| may fire from /// calling this function. /// diff --git a/src/nvim/api/win_config.h b/src/nvim/api/win_config.h index 9271c35f23..d3e5ede5e9 100644 --- a/src/nvim/api/win_config.h +++ b/src/nvim/api/win_config.h @@ -1,8 +1,6 @@ #ifndef NVIM_API_WIN_CONFIG_H #define NVIM_API_WIN_CONFIG_H -#include <stdint.h> - #include "nvim/api/private/defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/api/window.h b/src/nvim/api/window.h index 632b160e62..0f36c12a9f 100644 --- a/src/nvim/api/window.h +++ b/src/nvim/api/window.h @@ -1,8 +1,6 @@ #ifndef NVIM_API_WINDOW_H #define NVIM_API_WINDOW_H -#include <stdint.h> - #include "nvim/api/private/defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/ascii.h b/src/nvim/ascii.h index 44ed94d2fc..2cabaa43ef 100644 --- a/src/nvim/ascii.h +++ b/src/nvim/ascii.h @@ -10,7 +10,7 @@ // Definitions of various common control characters. #define CharOrd(x) ((uint8_t)(x) < 'a' \ - ? (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') diff --git a/src/nvim/assert.h b/src/nvim/assert.h index fc1a4be164..ad92d9a2af 100644 --- a/src/nvim/assert.h +++ b/src/nvim/assert.h @@ -70,11 +70,11 @@ # if __GNUC__ >= 6 # define STATIC_ASSERT_PRAGMA_START \ - _Pragma("GCC diagnostic push")\ + _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wpedantic\"") # else # define STATIC_ASSERT_PRAGMA_START \ - _Pragma("GCC diagnostic push")\ + _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-pedantic\"") # endif @@ -89,7 +89,7 @@ # undef STATIC_ASSERT_PRAGMA_START # define STATIC_ASSERT_PRAGMA_START \ - _Pragma("clang diagnostic push")\ + _Pragma("clang diagnostic push") \ _Pragma("clang diagnostic ignored \"-Wc11-extensions\"") # undef STATIC_ASSERT_PRAGMA_END @@ -113,14 +113,14 @@ // These can't be used after statements in c89. #ifdef __COUNTER__ # define STATIC_ASSERT_EXPR(e, m) \ - ((enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) }) 0) + ((enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)), }) 0) #else // This can't be used twice on the same line so ensure if using in headers // that the headers are not included twice (by wrapping in #ifndef...#endif) // Note it doesn't cause an issue when used on same line of separate modules // compiled with gcc -combine -fwhole-program. # define STATIC_ASSERT_EXPR(e, m) \ - ((enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }) 0) + ((enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)), }) 0) #endif /// @def STRICT_ADD diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index d991b88131..2d0c0f3fd5 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -313,9 +313,9 @@ static void au_del_group(char_u *name) { int i = au_find_group(name); if (i == AUGROUP_ERROR) { // the group doesn't exist - EMSG2(_("E367: No such group: \"%s\""), name); + semsg(_("E367: No such group: \"%s\""), name); } else if (i == current_augroup) { - EMSG(_("E936: Cannot delete the current group")); + emsg(_("E936: Cannot delete the current group")); } else { event_T event; AutoPat *ap; @@ -372,7 +372,7 @@ void do_augroup(char_u *arg, int del_group) { if (del_group) { if (*arg == NUL) { - EMSG(_(e_argreq)); + emsg(_(e_argreq)); } else { au_del_group(arg); } @@ -469,7 +469,7 @@ static char_u *find_end_event(char_u *arg, int have_group) if (*arg == '*') { if (arg[1] && !ascii_iswhite(arg[1])) { - EMSG2(_("E215: Illegal character after *: %s"), arg); + semsg(_("E215: Illegal character after *: %s"), arg); return NULL; } pat = arg + 1; @@ -477,9 +477,9 @@ static char_u *find_end_event(char_u *arg, int have_group) for (pat = arg; *pat && *pat != '|' && !ascii_iswhite(*pat); pat = p) { if ((int)event_name2nr(pat, &p) >= NUM_EVENTS) { if (have_group) { - EMSG2(_("E216: No such event: %s"), pat); + semsg(_("E216: No such event: %s"), pat); } else { - EMSG2(_("E216: No such group or event: %s"), pat); + semsg(_("E216: No such group or event: %s"), pat); } return NULL; } @@ -651,7 +651,7 @@ void do_autocmd(char_u *arg_in, int forceit) // Check for "++once" flag. if (STRNCMP(cmd, "++once", 6) == 0 && ascii_iswhite(cmd[6])) { if (once) { - EMSG2(_(e_duparg2), "++once"); + semsg(_(e_duparg2), "++once"); } once = true; cmd = skipwhite(cmd + 6); @@ -660,7 +660,7 @@ void do_autocmd(char_u *arg_in, int forceit) // Check for "++nested" flag. if ((STRNCMP(cmd, "++nested", 8) == 0 && ascii_iswhite(cmd[8]))) { if (nested) { - EMSG2(_(e_duparg2), "++nested"); + semsg(_(e_duparg2), "++nested"); } nested = true; cmd = skipwhite(cmd + 8); @@ -669,7 +669,7 @@ void do_autocmd(char_u *arg_in, int forceit) // Check for the old (deprecated) "nested" flag. if (STRNCMP(cmd, "nested", 6) == 0 && ascii_iswhite(cmd[6])) { if (nested) { - EMSG2(_(e_duparg2), "nested"); + semsg(_(e_duparg2), "nested"); } nested = true; cmd = skipwhite(cmd + 6); @@ -691,7 +691,7 @@ void do_autocmd(char_u *arg_in, int forceit) // Print header when showing autocommands. if (!forceit && *cmd == NUL) { // Highlight title - MSG_PUTS_TITLE(_("\n--- Autocommands ---")); + msg_puts_title(_("\n--- Autocommands ---")); } // Loop over the events. @@ -699,7 +699,7 @@ void do_autocmd(char_u *arg_in, int forceit) last_group = AUGROUP_ERROR; // for listing the group name if (*arg == '*' || *arg == NUL || *arg == '|') { if (!forceit && *cmd != NUL) { - EMSG(_(e_cannot_define_autocommands_for_all_events)); + emsg(_(e_cannot_define_autocommands_for_all_events)); } else { for (event_T event = (event_T)0; event < NUM_EVENTS; event = (event_T)(event + 1)) { @@ -899,7 +899,7 @@ static int do_autocmd_event(event_T event, char_u *pat, bool once, int nested, c // refuse to add buffer-local ap if buffer number is invalid if (is_buflocal && (buflocal_nr == 0 || buflist_findnr(buflocal_nr) == NULL)) { - emsgf(_("E680: <buffer=%d>: invalid buffer number "), buflocal_nr); + semsg(_("E680: <buffer=%d>: invalid buffer number "), buflocal_nr); return FAIL; } @@ -974,7 +974,7 @@ int do_doautocmd(char_u *arg, bool do_msg, bool *did_something) group = au_get_grouparg(&arg); if (*arg == '*') { - EMSG(_("E217: Can't execute autocommands for ALL events")); + emsg(_("E217: Can't execute autocommands for ALL events")); return FAIL; } @@ -996,7 +996,7 @@ int do_doautocmd(char_u *arg, bool do_msg, bool *did_something) } if (nothing_done && do_msg) { - MSG(_("No matching autocommands")); + msg(_("No matching autocommands")); } if (did_something != NULL) { *did_something = !nothing_done; @@ -1414,7 +1414,7 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, // Allow nesting of autocommands, but restrict the depth, because it's // possible to create an endless loop. if (nesting == 10) { - EMSG(_("E218: autocommand nesting too deep")); + emsg(_("E218: autocommand nesting too deep")); goto BYPASS_AU; } diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 809aa30692..e9d89c2f91 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -109,11 +109,9 @@ static int read_buffer(int read_stdin, exarg_T *eap, int flags) 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, @@ -164,21 +162,17 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags) long old_tw = curbuf->b_p_tw; int read_fifo = false; - /* - * The 'readonly' flag is only set when BF_NEVERLOADED is being reset. - * When re-entering the same buffer, it should not change, because the - * user may have reset the flag by hand. - */ + // The 'readonly' flag is only set when BF_NEVERLOADED is being reset. + // When re-entering the same buffer, it should not change, because the + // user may have reset the flag by hand. if (readonlymode && curbuf->b_ffname != NULL && (curbuf->b_flags & BF_NEVERLOADED)) { curbuf->b_p_ro = true; } if (ml_open(curbuf) == FAIL) { - /* - * There MUST be a memfile, otherwise we can't do anything - * If we can't create one for the current buffer, take another buffer - */ + // There MUST be a memfile, otherwise we can't do anything + // If we can't create one for the current buffer, take another buffer close_buffer(NULL, curbuf, 0, false); curbuf = NULL; @@ -192,7 +186,7 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags) // If there is no memfile at all, exit. // This is OK, since there are no changes to lose. if (curbuf == NULL) { - EMSG(_("E82: Cannot allocate any buffer, exiting...")); + emsg(_("E82: Cannot allocate any buffer, exiting...")); // Don't try to do any saving, with "curbuf" NULL almost nothing // will work. @@ -200,7 +194,7 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags) getout(2); } - EMSG(_("E83: Cannot allocate buffer, using other one...")); + emsg(_("E83: Cannot allocate buffer, using other one...")); enter_buffer(curbuf); if (old_tw != curbuf->b_p_tw) { check_colorcolumn(curwin); @@ -260,12 +254,10 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags) } else if (read_stdin) { int save_bin = curbuf->b_p_bin; - /* - * First read the text in binary mode into the buffer. - * Then read from that same buffer and append at the end. This makes - * it possible to retry when 'fileformat' or 'fileencoding' was - * guessed wrong. - */ + // First read the text in binary mode into the buffer. + // Then read from that same buffer and append at the end. This makes + // it possible to retry when 'fileformat' or 'fileencoding' was + // guessed wrong. curbuf->b_p_bin = true; retval = readfile(NULL, NULL, (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, NULL, @@ -308,8 +300,8 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags) curbuf->b_flags |= BF_READERR; } - /* Need to update automatic folding. Do this before the autocommands, - * they may use the fold info. */ + // Need to update automatic folding. Do this before the autocommands, + // they may use the fold info. foldUpdateAll(curwin); // need to set w_topline, unless some autocommand already did that. @@ -323,10 +315,8 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags) return FAIL; } - /* - * The autocommands may have changed the current buffer. Apply the - * modelines to the correct buffer, if it still exists and is loaded. - */ + // The autocommands may have changed the current buffer. Apply the + // modelines to the correct buffer, if it still exists and is loaded. if (bufref_valid(&old_curbuf) && old_curbuf.br_buf->b_ml.ml_mfp != NULL) { aco_save_T aco; @@ -335,8 +325,10 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags) do_modelines(0); curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED); - apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, false, curbuf, - &retval); + if ((flags & READ_NOWINENTER) == 0) { + apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, false, curbuf, + &retval); + } // restore curwin/curbuf and a few other things aucmd_restbuf(&aco); @@ -447,7 +439,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last) // 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")); + emsg(_("E937: Attempt to delete a buffer that is in use")); return false; } @@ -474,13 +466,13 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last) if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, false, buf) && !bufref_valid(&bufref)) { // Autocommands deleted the buffer. - EMSG(_(e_auabort)); + emsg(_(e_auabort)); return false; } buf->b_locked--; if (abort_if_last && last_nonfloat(win)) { // Autocommands made this the only window. - EMSG(_(e_auabort)); + emsg(_(e_auabort)); return false; } @@ -491,13 +483,13 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last) if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, false, buf) && !bufref_valid(&bufref)) { // Autocommands deleted the buffer. - EMSG(_(e_auabort)); + emsg(_(e_auabort)); return false; } buf->b_locked--; if (abort_if_last && last_nonfloat(win)) { // Autocommands made this the only window. - EMSG(_(e_auabort)); + emsg(_(e_auabort)); return false; } } @@ -509,7 +501,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last) // 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)) { + if (is_curwin && curwin != the_curwin && win_valid_any_tab(the_curwin)) { block_autocmds(); goto_tabpage_win(the_curtab, the_curwin); unblock_autocmds(); @@ -570,13 +562,11 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last) return false; } - /* - * It's possible that autocommands change curbuf to the one being deleted. - * This might cause the previous curbuf to be deleted unexpectedly. But - * in some cases it's OK to delete the curbuf, because a new one is - * obtained anyway. Therefore only return if curbuf changed to the - * deleted buffer. - */ + // It's possible that autocommands change curbuf to the one being deleted. + // This might cause the previous curbuf to be deleted unexpectedly. But + // in some cases it's OK to delete the curbuf, because a new one is + // obtained anyway. Therefore only return if curbuf changed to the + // deleted buffer. if (buf == curbuf && !is_curbuf) { return false; } @@ -708,7 +698,7 @@ void buf_freeall(buf_T *buf, int flags) // 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)) { + if (is_curwin && curwin != the_curwin && win_valid_any_tab(the_curwin)) { block_autocmds(); goto_tabpage_win(the_curtab, the_curwin); unblock_autocmds(); @@ -717,12 +707,10 @@ void buf_freeall(buf_T *buf, int flags) return; } - /* - * It's possible that autocommands change curbuf to the one being deleted. - * This might cause curbuf to be deleted unexpectedly. But in some cases - * it's OK to delete the curbuf, because a new one is obtained anyway. - * Therefore only return if curbuf changed to the deleted buffer. - */ + // It's possible that autocommands change curbuf to the one being deleted. + // This might cause curbuf to be deleted unexpectedly. But in some cases + // it's OK to delete the curbuf, because a new one is obtained anyway. + // Therefore only return if curbuf changed to the deleted buffer. if (buf == curbuf && !is_curbuf) { return; } @@ -818,7 +806,6 @@ static void free_buffer_stuff(buf_T *buf, int free_flags) uc_clear(&buf->b_ucmds); // clear local user commands buf_delete_signs(buf, (char_u *)"*"); // delete any signs extmark_free_all(buf); // delete any extmarks - clear_virt_lines(buf, -1); map_clear_int(buf, MAP_ALL_MODES, true, false); // clear local mappings map_clear_int(buf, MAP_ALL_MODES, true, true); // clear local abbrevs XFREE_CLEAR(buf->b_start_fenc); @@ -864,8 +851,8 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count) swap_exists_action = SEA_NONE; swap_exists_did_quit = true; - /* Restore the error/interrupt/exception state if not discarded by a - * new aborting error, interrupt, or uncaught exception. */ + // Restore the error/interrupt/exception state if not discarded by a + // new aborting error, interrupt, or uncaught exception. leave_cleanup(&cs); } else { handle_swap_exists(&old_curbuf); @@ -920,8 +907,8 @@ void handle_swap_exists(bufref_T *old_curbuf) } // If "old_curbuf" is NULL we are in big trouble here... - /* Restore the error/interrupt/exception state if not discarded by a - * new aborting error, interrupt, or uncaught exception. */ + // Restore the error/interrupt/exception state if not discarded by a + // new aborting error, interrupt, or uncaught exception. leave_cleanup(&cs); } else if (swap_exists_action == SEA_RECOVER) { // Reset the error/interrupt/exception state here so that @@ -931,12 +918,12 @@ void handle_swap_exists(bufref_T *old_curbuf) // User selected Recover at ATTENTION prompt. msg_scroll = true; ml_recover(false); - MSG_PUTS("\n"); // don't overwrite the last message + msg_puts("\n"); // don't overwrite the last message cmdline_row = msg_row; do_modelines(0); - /* Restore the error/interrupt/exception state if not discarded by a - * new aborting error, interrupt, or uncaught exception. */ + // Restore the error/interrupt/exception state if not discarded by a + // new aborting error, interrupt, or uncaught exception. leave_cleanup(&cs); } swap_exists_action = SEA_NONE; // -V519 @@ -957,11 +944,11 @@ void handle_swap_exists(bufref_T *old_curbuf) /// @param end_bnr buffer nr or last buffer nr in a range /// /// @return error message or NULL -char_u *do_bufdel(int command, char_u *arg, int addr_count, int start_bnr, int end_bnr, int forceit) +char *do_bufdel(int command, char_u *arg, int addr_count, int start_bnr, int end_bnr, int forceit) { int do_current = 0; // delete current buffer? int deleted = 0; // number of buffers deleted - char_u *errormsg = NULL; // return value + char *errormsg = NULL; // return value int bnr; // buffer number char_u *p; @@ -970,7 +957,7 @@ char_u *do_bufdel(int command, char_u *arg, int addr_count, int start_bnr, int e } else { if (addr_count == 2) { if (*arg) { // both range and argument is not allowed - return (char_u *)_(e_trailing); + return _(e_trailing); } bnr = start_bnr; } else { // addr_count == 1 @@ -978,12 +965,10 @@ char_u *do_bufdel(int command, char_u *arg, int addr_count, int start_bnr, int e } for (; !got_int; os_breakcheck()) { - /* - * delete the current buffer last, otherwise when the - * current buffer is deleted, the next buffer becomes - * the current one and will be loaded, which may then - * also be deleted, etc. - */ + // delete the current buffer last, otherwise when the + // current buffer is deleted, the next buffer becomes + // the current one and will be loaded, which may then + // also be deleted, etc. if (bnr == curbuf->b_fnum) { do_current = bnr; } else if (do_buffer(command, DOBUF_FIRST, FORWARD, bnr, @@ -991,9 +976,7 @@ char_u *do_bufdel(int command, char_u *arg, int addr_count, int start_bnr, int e deleted++; } - /* - * find next buffer number to delete/unload - */ + // find next buffer number to delete/unload if (addr_count == 2) { if (++bnr > end_bnr) { break; @@ -1030,26 +1013,17 @@ char_u *do_bufdel(int command, char_u *arg, int addr_count, int start_bnr, int e } else { STRCPY(IObuff, _("E517: No buffers were wiped out")); } - errormsg = IObuff; + errormsg = (char *)IObuff; } else if (deleted >= p_report) { if (command == DOBUF_UNLOAD) { - if (deleted == 1) { - MSG(_("1 buffer unloaded")); - } else { - smsg(_("%d buffers unloaded"), deleted); - } + smsg(NGETTEXT("%d buffer unloaded", "%d buffers unloaded", (unsigned long)deleted), + deleted); } else if (command == DOBUF_DEL) { - if (deleted == 1) { - MSG(_("1 buffer deleted")); - } else { - smsg(_("%d buffers deleted"), deleted); - } + smsg(NGETTEXT("%d buffer deleted", "%d buffers deleted", (unsigned long)deleted), + deleted); } else { - if (deleted == 1) { - MSG(_("1 buffer wiped out")); - } else { - smsg(_("%d buffers wiped out"), deleted); - } + smsg(NGETTEXT("%d buffer wiped out", "%d buffers wiped out", (unsigned long)deleted), + deleted); } } } @@ -1059,7 +1033,6 @@ char_u *do_bufdel(int command, char_u *arg, int addr_count, int start_bnr, int e } - /* * Make the current buffer empty. * Used when it is wiped out and it's the last buffer. @@ -1070,7 +1043,7 @@ static int empty_curbuf(int close_others, int forceit, int action) buf_T *buf = curbuf; if (action == DOBUF_UNLOAD) { - EMSG(_("E90: Cannot unload last buffer")); + emsg(_("E90: Cannot unload last buffer")); return FAIL; } @@ -1143,7 +1116,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) } while (buf != curbuf && !bufIsChanged(buf)); } if (!bufIsChanged(buf)) { - EMSG(_("E84: No modified buffer found")); + emsg(_("E84: No modified buffer found")); return FAIL; } } else if (start == DOBUF_FIRST && count) { // find specified buffer number @@ -1153,8 +1126,8 @@ int do_buffer(int action, int start, int dir, int count, int forceit) } else { bp = NULL; while (count > 0 || (!unload && !buf->b_p_bl && bp != buf)) { - /* remember the buffer where we start, we come back there when all - * buffers are unlisted. */ + // remember the buffer where we start, we come back there when all + // buffers are unlisted. if (bp == NULL) { bp = buf; } @@ -1176,7 +1149,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) } if (bp == buf) { // back where we started, didn't find anything. - EMSG(_("E85: There is no listed buffer")); + emsg(_("E85: There is no listed buffer")); return FAIL; } } @@ -1186,27 +1159,25 @@ int do_buffer(int action, int start, int dir, int count, int forceit) if (start == DOBUF_FIRST) { // don't warn when deleting if (!unload) { - EMSGN(_(e_nobufnr), count); + semsg(_(e_nobufnr), (int64_t)count); } } else if (dir == FORWARD) { - EMSG(_("E87: Cannot go beyond last buffer")); + emsg(_("E87: Cannot go beyond last buffer")); } else { - EMSG(_("E88: Cannot go before first buffer")); + emsg(_("E88: Cannot go before first buffer")); } return FAIL; } - /* - * delete buffer buf from memory and/or the list - */ + // delete buffer "buf" from memory and/or the list 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. */ + // When unloading or deleting a buffer that's already unloaded and + // unlisted: fail silently. if (action != DOBUF_WIPE && buf->b_ml.ml_mfp == NULL && !buf->b_p_bl) { return FAIL; } @@ -1224,9 +1195,9 @@ int do_buffer(int action, int start, int dir, int count, int forceit) return FAIL; } } else { - EMSGN(_("E89: No write since last change for buffer %" PRId64 + semsg(_("E89: No write since last change for buffer %" PRId64 " (add ! to override)"), - buf->b_fnum); + (int64_t)buf->b_fnum); return FAIL; } } @@ -1237,7 +1208,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) return FAIL; } } else { - EMSG2(_("E89: %s will be killed (add ! to override)"), + semsg(_("E89: %s will be killed (add ! to override)"), (char *)buf->b_fname); return FAIL; } @@ -1248,10 +1219,8 @@ int do_buffer(int action, int start, int dir, int count, int forceit) end_visual_mode(); } - /* - * If deleting the last (listed) buffer, make it empty. - * The last (listed) buffer cannot be unloaded. - */ + // If deleting the last (listed) buffer, make it empty. + // The last (listed) buffer cannot be unloaded. bp = NULL; FOR_ALL_BUFFERS(bp2) { if (bp2->b_p_bl && bp2 != buf) { @@ -1263,11 +1232,9 @@ int do_buffer(int action, int start, int dir, int count, int forceit) return empty_curbuf(true, forceit, action); } - /* - * If the deleted buffer is the current one, close the current window - * (unless it's the only window). Repeat this so long as we end up in - * a window with this buffer. - */ + // If the deleted buffer is the current one, close the current window + // (unless it's the only window). Repeat this so long as we end up in + // a window with this buffer. while (buf == curbuf && !(curwin->w_closing || curwin->w_buffer->b_locked > 0) && (!ONE_WINDOW || first_tabpage->tp_next != NULL)) { @@ -1276,9 +1243,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) } } - /* - * If the buffer to be deleted is not the current one, delete it here. - */ + // If the buffer to be deleted is not the current one, delete it here. if (buf != curbuf) { close_windows(buf, false); if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows <= 0) { @@ -1386,14 +1351,12 @@ int do_buffer(int action, int start, int dir, int count, int forceit) } if (buf == NULL) { - /* Autocommands must have wiped out all other buffers. Only option - * now is to make the current buffer empty. */ + // Autocommands must have wiped out all other buffers. Only option + // now is to make the current buffer empty. return empty_curbuf(false, forceit, action); } - /* - * make buf current buffer - */ + // make "buf" the current buffer if (action == DOBUF_SPLIT) { // split window first // If 'switchbuf' contains "useopen": jump to first window containing // "buf" if one exists @@ -1415,9 +1378,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) return OK; } - /* - * Check if the current buffer may be abandoned. - */ + // Check if the current buffer may be abandoned. if (action == DOBUF_GOTO && !can_abandon(curbuf, forceit)) { if ((p_confirm || cmdmod.confirm) && p_write) { bufref_T bufref; @@ -1510,9 +1471,9 @@ void set_curbuf(buf_T *buf, int action) } } } - /* An autocommand may have deleted "buf", already entered it (e.g., when - * it did ":bunload") or aborted the script processing! - * If curwin->w_buffer is null, enter_buffer() will make it valid again */ + // An autocommand may have deleted "buf", already entered it (e.g., when + // it did ":bunload") or aborted the script processing! + // If curwin->w_buffer is null, enter_buffer() will make it valid again if ((buf_valid(buf) && buf != curbuf && !aborting() ) || curwin->w_buffer == NULL) { @@ -1636,9 +1597,9 @@ void no_write_message(void) { if (curbuf->terminal && channel_job_running((uint64_t)curbuf->b_p_channel)) { - EMSG(_("E948: Job still running (add ! to end the job)")); + emsg(_("E948: Job still running (add ! to end the job)")); } else { - EMSG(_("E37: No write since last change (add ! to override)")); + emsg(_("E37: No write since last change (add ! to override)")); } } @@ -1647,9 +1608,9 @@ void no_write_message_nobang(const buf_T *const buf) { if (buf->terminal && channel_job_running((uint64_t)buf->b_p_channel)) { - EMSG(_("E948: Job still running")); + emsg(_("E948: Job still running")); } else { - EMSG(_("E37: No write since last change")); + emsg(_("E37: No write since last change")); } } @@ -1705,11 +1666,10 @@ buf_T *buflist_new(char_u *ffname_arg, char_u *sfname_arg, linenr_T lnum, int fl fname_expand(curbuf, &ffname, &sfname); // will allocate ffname - /* - * If file name already exists in the list, update the entry. - */ - /* We can use inode numbers when the file exists. Works better - * for hard links. */ + // If the file name already exists in the list, update the entry. + + // We can use inode numbers when the file exists. Works better + // for hard links. FileID file_id; bool file_id_valid = (sfname != NULL && os_fileid((char *)sfname, &file_id)); @@ -1833,7 +1793,7 @@ buf_T *buflist_new(char_u *ffname_arg, char_u *sfname_arg, linenr_T lnum, int fl buf->b_fnum = top_file_num++; pmap_put(handle_T)(&buffer_handles, buf->b_fnum, buf); if (top_file_num < 0) { // wrap around (may cause duplicates) - EMSG(_("W14: Warning: List of file names overflow")); + emsg(_("W14: Warning: List of file names overflow")); if (emsg_silent == 0) { ui_flush(); os_delay(3001L, true); // make sure it is noticed @@ -1841,9 +1801,7 @@ buf_T *buflist_new(char_u *ffname_arg, char_u *sfname_arg, linenr_T lnum, int fl top_file_num = 1; } - /* - * Always copy the options from the current buffer. - */ + // Always copy the options from the current buffer. buf_copy_options(buf, BCO_ALWAYS); } @@ -2005,9 +1963,9 @@ int buflist_getfile(int n, linenr_T lnum, int options, int forceit) buf = buflist_findnr(n); if (buf == NULL) { if ((options & GETF_ALT) && n == 0) { - EMSG(_(e_noalt)); + emsg(_(e_noalt)); } else { - EMSGN(_("E92: Buffer %" PRId64 " not found"), n); + semsg(_("E92: Buffer %" PRId64 " not found"), (int64_t)n); } return FAIL; } @@ -2228,8 +2186,8 @@ int buflist_findpat(const char_u *pattern, const char_u *pattern_end, bool unlis && (!diffmode || diff_mode_buf(buf)) && buflist_match(®match, buf, false) != NULL) { if (curtab_only) { - /* Ignore the match if the buffer is not open in - * the current tab. */ + // Ignore the match if the buffer is not open in + // the current tab. bool found_window = false; FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { if (wp->w_buffer == buf) { @@ -2267,9 +2225,9 @@ int buflist_findpat(const char_u *pattern, const char_u *pattern_end, bool unlis } if (match == -2) { - EMSG2(_("E93: More than one match for %s"), pattern); + semsg(_("E93: More than one match for %s"), pattern); } else if (match < 0) { - EMSG2(_("E94: No matching buffer for %s"), pattern); + semsg(_("E94: No matching buffer for %s"), pattern); } return match; } @@ -2321,10 +2279,8 @@ int ExpandBufnames(char_u *pat, int *num_file, char_u ***file, int options) patc = pat; } - /* - * attempt == 0: try match with '\<', match at start of word - * attempt == 1: try match without '\<', match anywhere - */ + // attempt == 0: try match with '\<', match at start of word + // attempt == 1: try match without '\<', match anywhere for (attempt = 0; attempt <= 1; attempt++) { if (attempt > 0 && patc == pat) { break; // there was no anchor, no need to try again @@ -2339,10 +2295,8 @@ int ExpandBufnames(char_u *pat, int *num_file, char_u ***file, int options) return FAIL; } - /* - * round == 1: Count the matches. - * round == 2: Build the array to keep the matches. - */ + // round == 1: Count the matches. + // round == 2: Build the array to keep the matches. for (round = 1; round <= 2; round++) { count = 0; FOR_ALL_BUFFERS(buf) { @@ -2832,11 +2786,9 @@ int setfname(buf_T *buf, char_u *ffname_arg, char_u *sfname_arg, bool message) return FAIL; } - /* - * if the file name is already used in another buffer: - * - if the buffer is loaded, fail - * - if the buffer is not loaded, delete it from the list - */ + // If the file name is already used in another buffer: + // - if the buffer is loaded, fail + // - if the buffer is not loaded, delete it from the list file_id_valid = os_fileid((char *)ffname, &file_id); if (!(buf->b_flags & BF_DUMMY)) { obuf = buflist_findname_file_id(ffname, &file_id, file_id_valid); @@ -2844,7 +2796,7 @@ int setfname(buf_T *buf, char_u *ffname_arg, char_u *sfname_arg, bool message) if (obuf != NULL && obuf != buf) { if (obuf->b_ml.ml_mfp != NULL) { // it's loaded, fail if (message) { - EMSG(_("E95: Buffer with this name already exists")); + emsg(_("E95: Buffer with this name already exists")); } xfree(ffname); return FAIL; @@ -2949,7 +2901,7 @@ char_u *getaltfname(bool errmsg) if (buflist_name_nr(0, &fname, &dummy) == FAIL) { if (errmsg) { - EMSG(_(e_noalt)); + emsg(_(e_noalt)); } return NULL; } @@ -3088,14 +3040,14 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate) { char_u *name; int n; - char_u *p; - char_u *buffer; + char *p; + char *buffer; size_t len; buffer = xmalloc(IOSIZE); if (fullname > 1) { // 2 CTRL-G: include buffer number - vim_snprintf((char *)buffer, IOSIZE, "buf %d: ", curbuf->b_fnum); + vim_snprintf(buffer, IOSIZE, "buf %d: ", curbuf->b_fnum); p = buffer + STRLEN(buffer); } else { p = buffer; @@ -3110,12 +3062,12 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate) } else { name = curbuf->b_ffname; } - home_replace(shorthelp ? curbuf : NULL, name, p, + home_replace(shorthelp ? curbuf : NULL, name, (char_u *)p, (size_t)(IOSIZE - (p - buffer)), true); } bool dontwrite = bt_dontwrite(curbuf); - vim_snprintf_add((char *)buffer, IOSIZE, "\"%s%s%s%s%s%s", + vim_snprintf_add(buffer, IOSIZE, "\"%s%s%s%s%s%s", curbufIsChanged() ? (shortmess(SHM_MOD) ? " [+]" : _(" [Modified]")) : " ", (curbuf->b_flags & BF_NOTEDITED) && !dontwrite @@ -3140,28 +3092,27 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate) (long)curbuf->b_ml.ml_line_count); } if (curbuf->b_ml.ml_flags & ML_EMPTY) { - vim_snprintf_add((char *)buffer, IOSIZE, "%s", _(no_lines_msg)); + vim_snprintf_add(buffer, IOSIZE, "%s", _(no_lines_msg)); } else if (p_ru) { // Current line and column are already on the screen -- webb - if (curbuf->b_ml.ml_line_count == 1) { - vim_snprintf_add((char *)buffer, IOSIZE, _("1 line --%d%%--"), n); - } else { - vim_snprintf_add((char *)buffer, IOSIZE, _("%" PRId64 " lines --%d%%--"), - (int64_t)curbuf->b_ml.ml_line_count, n); - } + vim_snprintf_add(buffer, IOSIZE, + NGETTEXT("%" PRId64 " line --%d%%--", + "%" PRId64 " lines --%d%%--", + (unsigned long)curbuf->b_ml.ml_line_count), + (int64_t)curbuf->b_ml.ml_line_count, n); } else { - vim_snprintf_add((char *)buffer, IOSIZE, + vim_snprintf_add(buffer, IOSIZE, _("line %" PRId64 " of %" PRId64 " --%d%%-- col "), (int64_t)curwin->w_cursor.lnum, (int64_t)curbuf->b_ml.ml_line_count, n); validate_virtcol(); len = STRLEN(buffer); - col_print(buffer + len, IOSIZE - len, + col_print((char_u *)buffer + len, IOSIZE - len, (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1); } - (void)append_arg_number(curwin, buffer, IOSIZE, !shortmess(SHM_FILE)); + (void)append_arg_number(curwin, (char_u *)buffer, IOSIZE, !shortmess(SHM_FILE)); if (dont_truncate) { // Temporarily set msg_scroll to avoid the message being truncated. @@ -3179,7 +3130,7 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate) // before redrawing). // - When the screen was scrolled but there is no wait-return // prompt. - set_keep_msg(p, 0); + set_keep_msg((char_u *)p, 0); } } @@ -3438,7 +3389,7 @@ void free_titles(void) /// be used when printing numbers in the status line. typedef enum { kNumBaseDecimal = 10, - kNumBaseHexadecimal = 16 + kNumBaseHexadecimal = 16, } NumberBase; @@ -3511,7 +3462,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use if (fillchar == 0) { fillchar = ' '; - } else if (mb_char2len(fillchar) > 1) { + } else if (utf_char2len(fillchar) > 1) { // Can't handle a multi-byte fill character yet. fillchar = '-'; } @@ -3699,7 +3650,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use long n = 0; while (group_len >= stl_items[stl_groupitems[groupdepth]].maxwid) { group_len -= ptr2cells(t + n); - n += (*mb_ptr2len)(t + n); + n += utfc_ptr2len(t + n); } // } @@ -5161,9 +5112,9 @@ void ex_buffer_all(exarg_T *eap) swap_exists_action = SEA_NONE; swap_exists_did_quit = true; - /* Restore the error/interrupt/exception state if not - * discarded by a new aborting error, interrupt, or uncaught - * exception. */ + // Restore the error/interrupt/exception state if not + // discarded by a new aborting error, interrupt, or uncaught + // exception. leave_cleanup(&cs); } else { handle_swap_exists(NULL); @@ -5211,7 +5162,6 @@ void ex_buffer_all(exarg_T *eap) } - /* * do_modelines() - process mode lines for the current file * @@ -5437,7 +5387,7 @@ bool bt_dontwrite_msg(const buf_T *const buf) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { if (bt_dontwrite(buf)) { - EMSG(_("E382: Cannot write, 'buftype' option is set")); + emsg(_("E382: Cannot write, 'buftype' option is set")); return true; } return false; diff --git a/src/nvim/buffer.h b/src/nvim/buffer.h index 0484c8550d..9e2ca999e4 100644 --- a/src/nvim/buffer.h +++ b/src/nvim/buffer.h @@ -24,7 +24,7 @@ enum getf_retvalues { GETFILE_NOT_WRITTEN = 2, // "not written" error GETFILE_SAME_FILE = 0, // success, same file GETFILE_OPEN_OTHER = -1, // success, opened another file - GETFILE_UNUSED = 8 + GETFILE_UNUSED = 8, }; // Values for buflist_new() flags diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index a1c5ea6924..bd9c5efa44 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -99,7 +99,7 @@ typedef struct { typedef struct window_S win_T; typedef struct wininfo_S wininfo_T; typedef struct frame_S frame_T; -typedef uint16_t disptick_T; // display tick type +typedef uint64_t disptick_T; // display tick type // for struct memline (it needs memfile_T) #include "nvim/memline_defs.h" @@ -147,8 +147,7 @@ struct buffheader { size_t bh_space; // space in bh_curr for appending }; -typedef struct -{ +typedef struct { buffheader_T sr_redobuff; buffheader_T sr_old_redobuff; } save_redo_T; @@ -388,7 +387,7 @@ struct stl_item { Highlight, TabPage, ClickFunc, - Trunc + Trunc, } type; }; @@ -577,8 +576,8 @@ struct file_buffer { long b_mod_xlines; // number of extra buffer lines inserted; // negative when lines were deleted wininfo_T *b_wininfo; // list of last used info for each window - int b_mod_tick_syn; // last display tick syntax was updated - int b_mod_tick_decor; // last display tick decoration providers + disptick_T b_mod_tick_syn; // last display tick syntax was updated + disptick_T b_mod_tick_decor; // last display tick decoration providers // where invoked long b_mtime; // last change time of original file @@ -867,12 +866,7 @@ struct file_buffer { MarkTree b_marktree[1]; Map(uint64_t, ExtmarkItem) b_extmark_index[1]; Map(uint64_t, ExtmarkNs) b_extmark_ns[1]; // extmark namespaces - - VirtLines b_virt_lines; - uint64_t b_virt_line_mark; - int b_virt_line_pos; - bool b_virt_line_above; - bool b_virt_line_leftcol; + size_t b_virt_line_blocks; // number of virt_line blocks // array of channel_id:s which have asked to receive updates for this // buffer. @@ -1025,8 +1019,7 @@ typedef struct { #define MAXPOSMATCH 8 /// Same as lpos_T, but with additional field len. -typedef struct -{ +typedef struct { linenr_T lnum; ///< line number colnr_T col; ///< column number int len; ///< length: 0 - to the end of line @@ -1035,8 +1028,7 @@ typedef struct /// posmatch_T provides an array for storing match items for matchaddpos() /// function. typedef struct posmatch posmatch_T; -struct posmatch -{ +struct posmatch { llpos_T pos[MAXPOSMATCH]; ///< array of positions int cur; ///< internal position counter linenr_T toplnum; ///< top buffer line @@ -1117,8 +1109,7 @@ typedef struct { // Structure to store last cursor position and topline. Used by check_lnums() // and reset_lnums(). -typedef struct -{ +typedef struct { int w_topline_save; // original topline value int w_topline_corr; // corrected topline value pos_T w_cursor_save; // original cursor position diff --git a/src/nvim/change.c b/src/nvim/change.c index 2450c56838..6ec4979dac 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -63,7 +63,7 @@ void change_warning(buf_T *buf, int col) } msg_source(HL_ATTR(HLF_W)); msg_ext_set_kind("wmsg"); - MSG_PUTS_ATTR(_(w_readonly), HL_ATTR(HLF_W) | MSG_HIST); + msg_puts_attr(_(w_readonly), HL_ATTR(HLF_W) | MSG_HIST); set_vim_var_string(VV_WARNINGMSG, _(w_readonly), -1); msg_clr_eos(); (void)msg_end(); @@ -602,7 +602,7 @@ void ins_char_bytes(char_u *buf, size_t charlen) if (vcol > new_vcol && oldp[col + oldlen] == TAB) { break; } - oldlen += (size_t)(*mb_ptr2len)(oldp + col + oldlen); + oldlen += (size_t)utfc_ptr2len(oldp + col + oldlen); // Deleted a bit too much, insert spaces. if (vcol > new_vcol) { newlen += (size_t)(vcol - new_vcol); @@ -611,7 +611,7 @@ void ins_char_bytes(char_u *buf, size_t charlen) curwin->w_p_list = old_list; } else if (oldp[col] != NUL) { // normal replace - oldlen = (size_t)(*mb_ptr2len)(oldp + col); + oldlen = (size_t)utfc_ptr2len(oldp + col); } @@ -725,7 +725,7 @@ int del_chars(long count, int fixpos) p = get_cursor_pos_ptr(); for (i = 0; i < count && *p != NUL; i++) { - l = (*mb_ptr2len)(p); + l = utfc_ptr2len(p); bytes += l; p += l; } @@ -759,7 +759,7 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine) } // If "count" is negative the caller must be doing something wrong. if (count < 1) { - IEMSGN("E292: Invalid count for del_bytes(): %ld", count); + siemsg("E292: Invalid count for del_bytes(): %ld", (int64_t)count); return FAIL; } @@ -778,7 +778,7 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine) col = n; count = utf_ptr2len(oldp + n); n += count; - } while (UTF_COMPOSINGLIKE(oldp + col, oldp + n)); + } while (utf_composinglike(oldp + col, oldp + n)); fixpos = false; } } @@ -1426,7 +1426,7 @@ int open_line(int dir, int flags, int second_line_indent) int l; for (i = 0; i < lead_len && p[i] != NUL; i += l) { - l = (*mb_ptr2len)(p + i); + l = utfc_ptr2len(p + i); if (vim_strnsize(p, i + l) > repl_size) { break; } @@ -1449,7 +1449,7 @@ int open_line(int dir, int flags, int second_line_indent) lead_len--; memmove(p, p + 1, (size_t)(leader + lead_len - p)); } else { - int l = (*mb_ptr2len)(p); + int l = utfc_ptr2len(p); if (l > 1) { if (ptr2cells(p) > 1) { diff --git a/src/nvim/channel.c b/src/nvim/channel.c index db0a2ff64c..9662f6205f 100644 --- a/src/nvim/channel.c +++ b/src/nvim/channel.c @@ -1,6 +1,7 @@ // 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/api/private/converter.h" #include "nvim/api/private/helpers.h" #include "nvim/api/ui.h" #include "nvim/channel.h" @@ -8,6 +9,7 @@ #include "nvim/eval/encode.h" #include "nvim/event/socket.h" #include "nvim/fileio.h" +#include "nvim/lua/executor.h" #include "nvim/msgpack_rpc/channel.h" #include "nvim/msgpack_rpc/server.h" #include "nvim/os/shell.h" @@ -136,6 +138,8 @@ bool channel_close(uint64_t id, ChannelPart part, const char **error) *error = (const char *)e_invstream; return false; } + api_free_luaref(chan->stream.internal.cb); + chan->stream.internal.cb = LUA_NOREF; break; default: @@ -315,7 +319,7 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout, CallbackReader if (pty) { if (detach) { - EMSG2(_(e_invarg2), "terminal/pty job cannot be detached"); + semsg(_(e_invarg2), "terminal/pty job cannot be detached"); shell_free_argv(argv); if (env) { tv_dict_free(env); @@ -365,7 +369,7 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout, CallbackReader int status = process_spawn(proc, has_in, has_out, has_err); if (status) { - EMSG3(_(e_jobspawn), os_strerror(status), cmd); + semsg(_(e_jobspawn), os_strerror(status), cmd); xfree(cmd); if (proc->env) { tv_dict_free(proc->env); @@ -420,6 +424,7 @@ uint64_t channel_connect(bool tcp, const char *address, bool rpc, CallbackReader // Create a loopback channel. This avoids deadlock if nvim connects to // its own named pipe. channel = channel_alloc(kChannelStreamInternal); + channel->stream.internal.cb = LUA_NOREF; rpc_start(channel); goto end; } @@ -530,7 +535,11 @@ size_t channel_send(uint64_t id, char *data, size_t len, bool data_owned, const goto retfree; } - if (chan->streamtype == kChannelStreamInternal && chan->term) { + if (chan->streamtype == kChannelStreamInternal) { + if (!chan->term) { + *error = _("Can't send data to closed stream"); + goto retfree; + } terminal_receive(chan->term, data, len); written = len; goto retfree; @@ -667,7 +676,7 @@ void channel_reader_callbacks(Channel *chan, CallbackReader *reader) tv_dict_add_list(reader->self, reader->type, strlen(reader->type), data); } else { - EMSG3(_(e_streamkey), reader->type, chan->id); + semsg(_(e_streamkey), reader->type, chan->id); } } else { channel_callback_call(chan, reader); diff --git a/src/nvim/channel.h b/src/nvim/channel.h index 4f51a7fc78..81b75e2d31 100644 --- a/src/nvim/channel.h +++ b/src/nvim/channel.h @@ -17,7 +17,7 @@ typedef enum { kChannelStreamSocket, kChannelStreamStdio, kChannelStreamStderr, - kChannelStreamInternal + kChannelStreamInternal, } ChannelStreamType; typedef enum { @@ -25,7 +25,7 @@ typedef enum { kChannelPartStdout, kChannelPartStderr, kChannelPartRpc, - kChannelPartAll + kChannelPartAll, } ChannelPart; typedef enum { @@ -43,6 +43,10 @@ typedef struct { } StderrState; typedef struct { + LuaRef cb; +} InternalState; + +typedef struct { Callback cb; dict_T *self; garray_T buffer; @@ -74,6 +78,7 @@ struct Channel { Stream socket; StdioPair stdio; StderrState err; + InternalState internal; } stream; bool is_rpc; diff --git a/src/nvim/charset.c b/src/nvim/charset.c index d2f95ad81c..5e18f9d86e 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -281,7 +281,7 @@ void trans_characters(char_u *buf, int bufsize) while (*buf != 0) { // Assume a multi-byte character doesn't need translation. - if ((trs_len = (*mb_ptr2len)(buf)) > 1) { + if ((trs_len = utfc_ptr2len(buf)) > 1) { len -= trs_len; } else { trs = transchar_byte(*buf); @@ -498,7 +498,7 @@ char_u *str_foldcase(char_u *str, int orglen, char_u *buf, int buflen) } // skip to next multi-byte char - i += (*mb_ptr2len)(STR_PTR(i)); + i += utfc_ptr2len(STR_PTR(i)); } @@ -732,7 +732,7 @@ int vim_strnsize(char_u *s, int len) assert(s != NULL); int size = 0; while (*s != NUL && --len >= 0) { - int l = (*mb_ptr2len)(s); + int l = utfc_ptr2len(s); size += ptr2cells(s); s += l; len -= l - 1; @@ -947,7 +947,7 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en if ((!wp->w_p_list || (wp->w_p_lcs_chars.tab1 != NUL)) && !wp->w_p_lbr && *get_showbreak_value(wp) == NUL - && !wp->w_p_bri ) { + && !wp->w_p_bri) { for (;;) { head = 0; c = *ptr; @@ -1311,7 +1311,8 @@ char_u *skiptowhite(const char_u *p) /// @param p /// /// @return Pointer to the next whitespace character. -char_u *skiptowhite_esc(char_u *p) { +char_u *skiptowhite_esc(char_u *p) +{ while (*p != ' ' && *p != '\t' && *p != NUL) { if (((*p == '\\') || (*p == Ctrl_V)) && (*(p + 1) != NUL)) { ++p; diff --git a/src/nvim/context.c b/src/nvim/context.c index 1db7938ef4..614a3ce30e 100644 --- a/src/nvim/context.c +++ b/src/nvim/context.c @@ -3,8 +3,10 @@ // Context: snapshot of the entire editor state as one big object/map +#include "nvim/api/private/converter.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" +#include "nvim/api/vimscript.h" #include "nvim/context.h" #include "nvim/eval/encode.h" #include "nvim/ex_docmd.h" @@ -314,7 +316,7 @@ static inline msgpack_sbuffer array_to_sbuf(Array array) object_to_vim(ARRAY_OBJ(array), &list_tv, &err); if (!encode_vim_list_to_buf(list_tv.vval.v_list, &sbuf.size, &sbuf.data)) { - EMSG(_("E474: Failed to convert list to msgpack string buffer")); + emsg(_("E474: Failed to convert list to msgpack string buffer")); } sbuf.alloc = sbuf.size; diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c index 18cade1052..644bb2c324 100644 --- a/src/nvim/cursor_shape.c +++ b/src/nvim/cursor_shape.c @@ -93,7 +93,7 @@ Array mode_style_array(void) /// @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 *parse_shape_opt(int what) { char_u *modep; char_u *colonp; @@ -126,10 +126,10 @@ char_u *parse_shape_opt(int what) commap = vim_strchr(modep, ','); if (colonp == NULL || (commap != NULL && commap < colonp)) { - return (char_u *)N_("E545: Missing colon"); + return N_("E545: Missing colon"); } if (colonp == modep) { - return (char_u *)N_("E546: Illegal mode"); + return N_("E546: Illegal mode"); } // Repeat for all modes before the colon. @@ -154,7 +154,7 @@ char_u *parse_shape_opt(int what) } if (idx == SHAPE_IDX_COUNT || (shape_table[idx].used_for & what) == 0) { - return (char_u *)N_("E546: Illegal mode"); + return N_("E546: Illegal mode"); } if (len == 2 && modep[0] == 'v' && modep[1] == 'e') { found_ve = true; @@ -189,12 +189,12 @@ char_u *parse_shape_opt(int what) if (len != 0) { p += len; if (!ascii_isdigit(*p)) { - return (char_u *)N_("E548: digit expected"); + return N_("E548: digit expected"); } int n = getdigits_int(&p, false, 0); if (len == 3) { // "ver" or "hor" if (n == 0) { - return (char_u *)N_("E549: Illegal percentage"); + return N_("E549: Illegal percentage"); } if (round == 2) { if (TOLOWER_ASC(i) == 'v') { diff --git a/src/nvim/cursor_shape.h b/src/nvim/cursor_shape.h index 06eaa431a0..93bddd47c7 100644 --- a/src/nvim/cursor_shape.h +++ b/src/nvim/cursor_shape.h @@ -24,13 +24,13 @@ typedef enum { 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 + SHAPE_IDX_COUNT = 17, } ModeShape; typedef enum { SHAPE_BLOCK = 0, ///< block cursor SHAPE_HOR = 1, ///< horizontal bar cursor - SHAPE_VER = 2 ///< vertical bar cursor + SHAPE_VER = 2, ///< vertical bar cursor } CursorShape; #define MSHAPE_NUMBERED 1000 // offset for shapes identified by number diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c index aeaf2555b1..3ac128a20f 100644 --- a/src/nvim/debugger.c +++ b/src/nvim/debugger.c @@ -88,7 +88,7 @@ void do_debug(char_u *cmd) debug_mode = true; if (!debug_did_msg) { - MSG(_("Entering Debug mode. Type \"cont\" to continue.")); + msg(_("Entering Debug mode. Type \"cont\" to continue.")); } if (debug_oldval != NULL) { smsg(_("Oldval = \"%s\""), debug_oldval); @@ -101,7 +101,7 @@ void do_debug(char_u *cmd) debug_newval = NULL; } if (sourcing_name != NULL) { - msg(sourcing_name); + msg((char *)sourcing_name); } if (sourcing_lnum != 0) { smsg(_("line %" PRId64 ": %s"), (int64_t)sourcing_lnum, cmd); @@ -321,7 +321,7 @@ static void do_checkbacktracelevel(void) { if (debug_backtrace_level < 0) { debug_backtrace_level = 0; - MSG(_("frame is zero")); + msg(_("frame is zero")); } else { int max = get_maxbacktrace_level(); if (debug_backtrace_level > max) { @@ -496,7 +496,7 @@ static int dbg_parsearg(char_u *arg, garray_T *gap) bp->dbg_type = DBG_FILE; } else if (gap != &prof_ga && STRNCMP(p, "here", 4) == 0) { if (curbuf->b_ffname == NULL) { - EMSG(_(e_noname)); + emsg(_(e_noname)); return FAIL; } bp->dbg_type = DBG_FILE; @@ -504,7 +504,7 @@ static int dbg_parsearg(char_u *arg, garray_T *gap) } else if (gap != &prof_ga && STRNCMP(p, "expr", 4) == 0) { bp->dbg_type = DBG_EXPR; } else { - EMSG2(_(e_invarg2), p); + semsg(_(e_invarg2), p); return FAIL; } p = skipwhite(p + 4); @@ -523,7 +523,7 @@ static int dbg_parsearg(char_u *arg, garray_T *gap) if ((!here && *p == NUL) || (here && *p != NUL) || (bp->dbg_type == DBG_FUNC && strstr((char *)p, "()") != NULL)) { - EMSG2(_(e_invarg2), arg); + semsg(_(e_invarg2), arg); return FAIL; } @@ -661,7 +661,7 @@ void ex_breakdel(exarg_T *eap) } if (todel < 0) { - EMSG2(_("E161: Breakpoint not found: %s"), eap->arg); + semsg(_("E161: Breakpoint not found: %s"), eap->arg); } else { while (!GA_EMPTY(gap)) { xfree(DEBUGGY(gap, todel).dbg_name); @@ -696,7 +696,7 @@ void ex_breaklist(exarg_T *eap) struct debuggy *bp; if (GA_EMPTY(&dbg_breakp)) { - MSG(_("No breakpoints defined")); + msg(_("No breakpoints defined")); } else { for (int i = 0; i < dbg_breakp.ga_len; i++) { bp = &BREAKP(i); diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index 4e80528c74..c0f3c32f93 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -91,12 +91,31 @@ void decor_redraw(buf_T *buf, int row1, int row2, Decoration *decor) if (kv_size(decor->virt_text)) { redraw_buf_line_later(buf, row1+1); } + + if (kv_size(decor->virt_lines)) { + redraw_buf_line_later(buf, MIN(buf->b_ml.ml_line_count, + row1+1+(decor->virt_lines_above?0:1))); + } +} + +void decor_remove(buf_T *buf, int row, int row2, Decoration *decor) +{ + if (kv_size(decor->virt_lines)) { + assert(buf->b_virt_line_blocks > 0); + buf->b_virt_line_blocks--; + } + decor_redraw(buf, row, row2, decor); + decor_free(decor); } void decor_free(Decoration *decor) { if (decor && !decor->shared) { clear_virttext(&decor->virt_text); + for (size_t i = 0; i < kv_size(decor->virt_lines); i++) { + clear_virttext(&kv_A(decor->virt_lines, i).line); + } + kv_destroy(decor->virt_lines); xfree(decor); } } @@ -118,6 +137,8 @@ Decoration *decor_find_virttext(buf_T *buf, int row, uint64_t ns_id) mtmark_t mark = marktree_itr_current(itr); if (mark.row < 0 || mark.row > row) { break; + } else if (marktree_decor_level(mark.id) < kDecorLevelVisible) { + goto next_mark; } ExtmarkItem *item = map_ref(uint64_t, ExtmarkItem)(buf->b_extmark_index, mark.id, false); @@ -125,6 +146,7 @@ Decoration *decor_find_virttext(buf_T *buf, int row, uint64_t ns_id) && item->decor && kv_size(item->decor->virt_text)) { return item->decor; } +next_mark: marktree_itr_next(buf->b_marktree, itr); } return NULL; @@ -158,21 +180,22 @@ bool decor_redraw_start(buf_T *buf, int top_row, DecorState *state) if (mark.row < 0) { // || mark.row > end_row break; } - if ((mark.row < top_row && mark.id&MARKTREE_END_FLAG)) { + if ((mark.row < top_row && mark.id&MARKTREE_END_FLAG) + || marktree_decor_level(mark.id) < kDecorLevelVisible) { goto next_mark; } - mtpos_t altpos = marktree_lookup(buf->b_marktree, - mark.id^MARKTREE_END_FLAG, NULL); uint64_t start_id = mark.id & ~MARKTREE_END_FLAG; ExtmarkItem *item = map_ref(uint64_t, ExtmarkItem)(buf->b_extmark_index, start_id, false); if (!item || !item->decor) { - // TODO(bfredl): dedicated flag for being a decoration? goto next_mark; } Decoration *decor = item->decor; + mtpos_t altpos = marktree_lookup(buf->b_marktree, + mark.id^MARKTREE_END_FLAG, NULL); + if ((!(mark.id&MARKTREE_END_FLAG) && altpos.row < top_row && !kv_size(decor->virt_text)) || ((mark.id&MARKTREE_END_FLAG) && altpos.row >= top_row)) { @@ -251,21 +274,21 @@ int decor_redraw_col(buf_T *buf, int col, int win_col, bool hidden, DecorState * break; } - if ((mark.id&MARKTREE_END_FLAG)) { - // TODO(bfredl): check decoration flag + if ((mark.id&MARKTREE_END_FLAG) + || marktree_decor_level(mark.id) < kDecorLevelVisible) { goto next_mark; } - mtpos_t endpos = marktree_lookup(buf->b_marktree, - mark.id|MARKTREE_END_FLAG, NULL); ExtmarkItem *item = map_ref(uint64_t, ExtmarkItem)(buf->b_extmark_index, mark.id, false); if (!item || !item->decor) { - // TODO(bfredl): dedicated flag for being a decoration? goto next_mark; } Decoration *decor = item->decor; + mtpos_t endpos = marktree_lookup(buf->b_marktree, + mark.id|MARKTREE_END_FLAG, NULL); + if (endpos.row == -1) { endpos.row = mark.row; endpos.col = mark.col; @@ -414,33 +437,38 @@ void decor_free_all_mem(void) } -int decor_virtual_lines(win_T *wp, linenr_T lnum) +int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines) { buf_T *buf = wp->w_buffer; - if (!buf->b_virt_line_mark) { + if (!buf->b_virt_line_blocks) { + // Only pay for what you use: in case virt_lines feature is not active + // in a buffer, plines do not need to access the marktree at all return 0; } - if (buf->b_virt_line_pos < 0) { - mtpos_t pos = marktree_lookup(buf->b_marktree, buf->b_virt_line_mark, NULL); - if (pos.row < 0) { - buf->b_virt_line_mark = 0; + + int virt_lines = 0; + int row = (int)MAX(lnum - 2, 0); + int end_row = (int)lnum; + MarkTreeIter itr[1] = { 0 }; + marktree_itr_get(buf->b_marktree, row, 0, itr); + while (true) { + mtmark_t mark = marktree_itr_current(itr); + if (mark.row < 0 || mark.row >= end_row) { + break; + } else if (marktree_decor_level(mark.id) < kDecorLevelVirtLine) { + goto next_mark; + } + bool above = mark.row > (int)(lnum - 2); + ExtmarkItem *item = map_ref(uint64_t, ExtmarkItem)(buf->b_extmark_index, mark.id, false); + if (item && item->decor && item->decor->virt_lines_above == above) { + virt_lines += (int)kv_size(item->decor->virt_lines); + if (lines) { + kv_splice(*lines, item->decor->virt_lines); + } } - buf->b_virt_line_pos = pos.row + (buf->b_virt_line_above ? 0 : 1); +next_mark: + marktree_itr_next(buf->b_marktree, itr); } - return (lnum-1 == buf->b_virt_line_pos) ? (int)kv_size(buf->b_virt_lines) : 0; -} - -void clear_virt_lines(buf_T *buf, int row) -{ - if (row > -1) { - redraw_buf_line_later(buf, MIN(buf->b_ml.ml_line_count, - row+1+(buf->b_virt_line_above?0:1))); - } - for (size_t i = 0; i < kv_size(buf->b_virt_lines); i++) { - clear_virttext(&kv_A(buf->b_virt_lines, i)); - } - kv_destroy(buf->b_virt_lines); // re-initializes - buf->b_virt_line_pos = -1; - buf->b_virt_line_mark = 0; + return virt_lines; } diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h index e44fbab0a5..611b4223da 100644 --- a/src/nvim/decoration.h +++ b/src/nvim/decoration.h @@ -24,22 +24,33 @@ typedef enum { kHlModeBlend, } HlMode; -struct Decoration -{ +typedef kvec_t(VirtTextChunk) VirtText; +#define VIRTTEXT_EMPTY ((VirtText)KV_INITIAL_VALUE) + + +typedef kvec_t(struct virt_line { VirtText line; bool left_col; }) VirtLines; + + +struct Decoration { VirtText virt_text; + VirtLines virt_lines; + int hl_id; // highlight group VirtTextPos virt_text_pos; HlMode hl_mode; + + // TODO(bfredl): at some point turn this into FLAGS bool virt_text_hide; bool hl_eol; bool shared; // shared decoration, don't free + bool virt_lines_above; // TODO(bfredl): style, signs, etc DecorPriority priority; int col; // fixed col value, like win_col int virt_text_width; // width of virt_text }; -#define DECORATION_INIT { KV_INITIAL_VALUE, 0, kVTEndOfLine, kHlModeUnknown, \ - false, false, false, DECOR_PRIORITY_BASE, 0, 0 } +#define DECORATION_INIT { KV_INITIAL_VALUE, KV_INITIAL_VALUE, 0, kVTEndOfLine, kHlModeUnknown, \ + false, false, false, false, DECOR_PRIORITY_BASE, 0, 0 } typedef struct { int start_row; @@ -60,9 +71,7 @@ typedef struct { int row; int col_until; int current; - int eol_col; - VirtText *virt_text; } DecorState; typedef struct { diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 3a7bd21c70..4e03f4761c 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -168,7 +168,7 @@ void diff_buf_add(buf_T *buf) } } - EMSGN(_("E96: Cannot diff more than %" PRId64 " buffers"), DB_COUNT); + semsg(_("E96: Cannot diff more than %" PRId64 " buffers"), (int64_t)DB_COUNT); } /// @@ -391,7 +391,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T off = 0; if (last < line2) { - // 2. delete at end of of diff + // 2. delete at end of diff dp->df_count[idx] -= last - lnum_deleted + 1; if ((dp->df_next != NULL) @@ -638,7 +638,8 @@ static int diff_check_sanity(tabpage_T *tp, diff_T *dp) void diff_redraw(bool dofold) { win_T *wp_other = NULL; - bool used_max_fill = false; + bool used_max_fill_other = false; + bool used_max_fill_curwin = false; need_diff_redraw = false; FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { @@ -663,16 +664,24 @@ void diff_redraw(bool dofold) } else if ((n > 0) && (n > wp->w_topfill)) { wp->w_topfill = n; if (wp == curwin) { - used_max_fill = true; + used_max_fill_curwin = true; + } else if (wp_other != NULL) { + used_max_fill_other = true; } } check_topfill(wp, false); } } - if (wp_other != NULL && used_max_fill && curwin->w_p_scb) { - // The current window was set to used the maximum number of filler - // lines, may need to reduce them. - diff_set_topline(wp_other, curwin); + if (wp_other != NULL && curwin->w_p_scb) { + if (used_max_fill_curwin) { + // The current window was set to used the maximum number of filler + // lines, may need to reduce them. + diff_set_topline(wp_other, curwin); + } else if (used_max_fill_other) { + // The other window was set to used the maximum number of filler + // lines, may need to reduce them. + diff_set_topline(curwin, wp_other); + } } } @@ -735,7 +744,7 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din) char_u cbuf[MB_MAXBYTES + 1]; // xdiff doesn't support ignoring case, fold-case the text. - int c = PTR2CHAR(s); + int c = utf_ptr2char(s); c = utf_fold(c); const int orig_len = utfc_ptr2len(s); if (utf_char2bytes(c, cbuf) != orig_len) { @@ -1030,9 +1039,9 @@ static int check_external_diff(diffio_T *diffio) if (!ok) { if (io_error) { - EMSG(_("E810: Cannot read or write temp files")); + emsg(_("E810: Cannot read or write temp files")); } - EMSG(_("E97: Cannot create diffs")); + emsg(_("E97: Cannot create diffs")); diff_a_works = kNone; return FAIL; } @@ -1073,7 +1082,7 @@ static int diff_file_internal(diffio_T *diffio) if (xdl_diff(&diffio->dio_orig.din_mmfile, &diffio->dio_new.din_mmfile, ¶m, &emit_cfg, &emit_cb) < 0) { - EMSG(_("E960: Problem creating the internal diff")); + emsg(_("E960: Problem creating the internal diff")); return FAIL; } return OK; @@ -1216,7 +1225,7 @@ void ex_diffpatch(exarg_T *eap) #ifdef UNIX if (dirbuf[0] != NUL) { if (os_chdir((char *)dirbuf) != 0) { - EMSG(_(e_prev_dir)); + emsg(_(e_prev_dir)); } shorten_fnames(true); } @@ -1235,7 +1244,7 @@ void ex_diffpatch(exarg_T *eap) bool info_ok = os_fileinfo((char *)tmp_new, &file_info); uint64_t filesize = os_fileinfo_size(&file_info); if (!info_ok || filesize == 0) { - EMSG(_("E816: Cannot read patch output")); + emsg(_("E816: Cannot read patch output")); } else { if (curbuf->b_fname != NULL) { newname = vim_strnsave(curbuf->b_fname, STRLEN(curbuf->b_fname) + 4); @@ -1527,7 +1536,7 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout) enum { DIFF_ED, DIFF_UNIFIED, - DIFF_NONE + DIFF_NONE, } diffstyle = DIFF_NONE; if (dout->dout_fname == NULL) { @@ -1535,7 +1544,7 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout) } else { fd = os_fopen((char *)dout->dout_fname, "r"); if (fd == NULL) { - EMSG(_("E98: Cannot read diff output")); + emsg(_("E98: Cannot read diff output")); return; } } @@ -1591,7 +1600,7 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout) } } else { assert(diffstyle == DIFF_UNIFIED); - if (STRNCMP(line, "@@ ", 3) != 0) { + if (STRNCMP(line, "@@ ", 3) != 0) { continue; // not the start of a diff block } if (parse_diff_unified(line, &lnum_orig, &count_orig, @@ -1699,7 +1708,7 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout) notset = false; // "*dp" has been set } - // for remaining diff blocks orig and new are equal +// for remaining diff blocks orig and new are equal while (dp != NULL) { if (notset) { diff_copy_entry(dprev, dp, idx_orig, idx_new); @@ -2488,7 +2497,7 @@ void ex_diffgetput(exarg_T *eap) // Find the current buffer in the list of diff buffers. int idx_cur = diff_buf_idx(curbuf); if (idx_cur == DB_COUNT) { - EMSG(_("E99: Current buffer is not in diff mode")); + emsg(_("E99: Current buffer is not in diff mode")); return; } @@ -2507,9 +2516,9 @@ void ex_diffgetput(exarg_T *eap) if (idx_other == DB_COUNT) { if (found_not_ma) { - EMSG(_("E793: No other buffer in diff mode is modifiable")); + emsg(_("E793: No other buffer in diff mode is modifiable")); } else { - EMSG(_("E100: No other buffer in diff mode")); + emsg(_("E100: No other buffer in diff mode")); } return; } @@ -2520,7 +2529,7 @@ void ex_diffgetput(exarg_T *eap) && (curtab->tp_diffbuf[i] != NULL) && ((eap->cmdidx != CMD_diffput) || MODIFIABLE(curtab->tp_diffbuf[i]))) { - EMSG(_("E101: More than two buffers in diff mode, don't know " + emsg(_("E101: More than two buffers in diff mode, don't know " "which one to use")); return; } @@ -2549,7 +2558,7 @@ void ex_diffgetput(exarg_T *eap) buf = buflist_findnr(i); if (buf == NULL) { - EMSG2(_("E102: Can't find buffer \"%s\""), eap->arg); + semsg(_("E102: Can't find buffer \"%s\""), eap->arg); return; } @@ -2560,7 +2569,7 @@ void ex_diffgetput(exarg_T *eap) idx_other = diff_buf_idx(buf); if (idx_other == DB_COUNT) { - EMSG2(_("E103: Buffer \"%s\" is not in diff mode"), eap->arg); + semsg(_("E103: Buffer \"%s\" is not in diff mode"), eap->arg); return; } } @@ -2601,7 +2610,7 @@ void ex_diffgetput(exarg_T *eap) if (!curbuf->b_changed) { change_warning(curbuf, 0); if (diff_buf_idx(curbuf) != idx_to) { - EMSG(_("E787: Buffer changed unexpectedly")); + emsg(_("E787: Buffer changed unexpectedly")); goto theend; } } @@ -3138,7 +3147,7 @@ static int xdiff_out(void *priv, mmbuffer_t *mb, int nbuf) } // sanity check - if (STRNCMP(mb[0].ptr, "@@ ", 3) != 0) { + if (STRNCMP(mb[0].ptr, "@@ ", 3) != 0) { return 0; } diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c index 0fa6ebcd94..d1dd9b8309 100644 --- a/src/nvim/digraph.c +++ b/src/nvim/digraph.c @@ -1628,18 +1628,18 @@ void putdigraph(char_u *str) char2 = *str++; if (char2 == 0) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } if ((char1 == ESC) || (char2 == ESC)) { - EMSG(_("E104: Escape not allowed in digraph")); + emsg(_("E104: Escape not allowed in digraph")); return; } str = skipwhite(str); if (!ascii_isdigit(*str)) { - EMSG(_(e_number_exp)); + emsg(_(e_number_exp)); return; } int n = getdigits_int(&str, true, 0); @@ -1821,7 +1821,7 @@ typedef struct { /// @return NULL if OK, an error message for failure. This only needs to be /// used when setting the option, not later when the value has already /// been checked. -char_u *keymap_init(void) +char *keymap_init(void) { curbuf->b_kmap_state &= ~KEYMAP_INIT; @@ -1850,7 +1850,7 @@ char_u *keymap_init(void) if (source_runtime(buf, 0) == FAIL) { xfree(buf); - return (char_u *)N_("E544: Keymap file not found"); + return N_("E544: Keymap file not found"); } } xfree(buf); @@ -1873,7 +1873,7 @@ void ex_loadkeymap(exarg_T *eap) char_u *save_cpo = p_cpo; if (!getline_equal(eap->getline, eap->cookie, getsourceline)) { - EMSG(_("E105: Using :loadkeymap not in a sourced file")); + emsg(_("E105: Using :loadkeymap not in a sourced file")); return; } @@ -1908,7 +1908,7 @@ void ex_loadkeymap(exarg_T *eap) || (*kp->from == NUL) || (*kp->to == NUL)) { if (*kp->to == NUL) { - EMSG(_("E791: Empty keymap entry")); + emsg(_("E791: Empty keymap entry")); } xfree(kp->from); xfree(kp->to); diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 3ea7b442c8..ca903fdcf7 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -523,7 +523,7 @@ static int insert_check(VimState *state) did_cursorhold = false; } - // If the cursor was moved we didn't just insert a space */ + // If the cursor was moved we didn't just insert a space if (arrow_used) { s->inserted_space = false; } @@ -708,7 +708,7 @@ static int insert_execute(VimState *state, int key) if (str != NULL) { for (p = str; *p != NUL; MB_PTR_ADV(p)) { - ins_compl_addleader(PTR2CHAR(p)); + ins_compl_addleader(utf_ptr2char(p)); } xfree(str); } else { @@ -835,7 +835,7 @@ static int insert_handle_key(InsertState *s) case Ctrl_C: // End input mode if (s->c == Ctrl_C && cmdwin_type != 0) { - // Close the cmdline window. */ + // Close the cmdline window. cmdwin_result = K_IGNORE; got_int = false; // don't stop executing autocommands et al s->nomove = true; @@ -1283,7 +1283,7 @@ normalchar: if (*str != NUL && stop_arrow() != FAIL) { // Insert the new value of v:char literally. for (p = str; *p != NUL; MB_PTR_ADV(p)) { - s->c = PTR2CHAR(p); + s->c = utf_ptr2char(p); if (s->c == CAR || s->c == K_KENTER || s->c == NL) { ins_eol(s->c); } else { @@ -1398,20 +1398,20 @@ bool edit(int cmdchar, bool startln, long count) // Don't allow inserting in the sandbox. if (sandbox != 0) { - EMSG(_(e_sandbox)); + emsg(_(e_sandbox)); return false; } // Don't allow changes in the buffer while editing the cmdline. The // caller of getcmdline() may get confused. if (textlock != 0) { - EMSG(_(e_secure)); + emsg(_(e_secure)); return false; } // Don't allow recursive insert mode when busy with completion. if (compl_started || compl_busy || pum_visible()) { - EMSG(_(e_secure)); + emsg(_(e_secure)); return false; } @@ -3006,7 +3006,7 @@ static void ins_compl_files(int count, char_u **files, int thesaurus, int flags, msg_hist_off = true; // reset in msg_trunc_attr() vim_snprintf((char *)IObuff, IOSIZE, _("Scanning dictionary: %s"), (char *)files[i]); - (void)msg_trunc_attr(IObuff, true, HL_ATTR(HLF_R)); + (void)msg_trunc_attr((char *)IObuff, true, HL_ATTR(HLF_R)); } if (fp == NULL) { @@ -3330,7 +3330,7 @@ void get_complete_info(list_T *what_list, dict_T *retdict) // Return Insert completion mode name string static char_u *ins_compl_mode(void) { - if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET || ctrl_x_mode == CTRL_X_SCROLL || compl_started) { + if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET || ctrl_x_mode == CTRL_X_SCROLL || compl_started) { return (char_u *)ctrl_x_mode_names[ctrl_x_mode & ~CTRL_X_WANT_IDENT]; } return (char_u *)""; @@ -3548,7 +3548,7 @@ static void ins_compl_addfrommatch(void) } } p += len; - c = PTR2CHAR(p); + c = utf_ptr2char(p); ins_compl_addleader(c); } @@ -3905,7 +3905,6 @@ static buf_T *ins_compl_next_buf(buf_T *buf, int flag) assert(wp); while ((wp = (wp->w_next != NULL ? wp->w_next : firstwin)) != curwin && wp->w_buffer->b_scanned) { - ; } buf = wp->w_buffer; } else { @@ -3918,7 +3917,6 @@ static buf_T *ins_compl_next_buf(buf_T *buf, int flag) : (!buf->b_p_bl || (buf->b_ml.ml_mfp == NULL) != (flag == 'u'))) || buf->b_scanned)) { - ; } } return buf; @@ -3991,13 +3989,13 @@ static void expand_by_function(int type, char_u *base) } if (curwin_save != curwin || curbuf_save != curbuf) { - EMSG(_(e_complwin)); + emsg(_(e_complwin)); goto theend; } curwin->w_cursor = pos; // restore the cursor position validate_cursor(); if (!equalpos(curwin->w_cursor, pos)) { - EMSG(_(e_compldel)); + emsg(_(e_compldel)); goto theend; } @@ -4233,7 +4231,7 @@ static int ins_compl_get_exp(pos_T *ini) : ins_buf->b_sfname == NULL ? ins_buf->b_fname : ins_buf->b_sfname); - (void)msg_trunc_attr(IObuff, true, HL_ATTR(HLF_R)); + (void)msg_trunc_attr((char *)IObuff, true, HL_ATTR(HLF_R)); } else if (*e_cpt == NUL) { break; } else { @@ -4257,7 +4255,7 @@ static int ins_compl_get_exp(pos_T *ini) msg_hist_off = true; // reset in msg_trunc_attr() type = CTRL_X_TAGS; vim_snprintf((char *)IObuff, IOSIZE, "%s", _("Scanning tags.")); - (void)msg_trunc_attr(IObuff, true, HL_ATTR(HLF_R)); + (void)msg_trunc_attr((char *)IObuff, true, HL_ATTR(HLF_R)); } else { type = -1; } @@ -4449,7 +4447,7 @@ static int ins_compl_get_exp(pos_T *ini) // when ADDING, the text before the cursor matches, skip it if ((compl_cont_status & CONT_ADDING) && ins_buf == curbuf && ini->lnum == pos->lnum - && ini->col == pos->col) { + && ini->col == pos->col) { continue; } ptr = ml_get_buf(ins_buf, pos->lnum, false) + pos->col; @@ -4860,7 +4858,7 @@ static int ins_compl_next(int allow_get_expansion, int count, int insert_match, msg_hist_off = true; vim_snprintf((char *)IObuff, IOSIZE, "%s %s%s", lead, s > compl_shown_match->cp_fname ? "<" : "", s); - msg(IObuff); + msg((char *)IObuff); msg_hist_off = false; redraw_cmdline = false; // don't overwrite! } @@ -5124,7 +5122,6 @@ static int ins_complete(int c, bool enable_pum) || ctrl_x_mode == CTRL_X_PATH_DEFINES) { if (!(compl_cont_status & CONT_ADDING)) { while (--startcol >= 0 && vim_isIDc(line[startcol])) { - ; } compl_col += ++startcol; compl_length = curs_col - startcol; @@ -5204,10 +5201,10 @@ static int ins_complete(int c, bool enable_pum) char_u *p = line + startcol; MB_PTR_BACK(line, p); - while (p > line && vim_isfilec(PTR2CHAR(p))) { + while (p > line && vim_isfilec(utf_ptr2char(p))) { MB_PTR_BACK(line, p); } - if (p == line && vim_isfilec(PTR2CHAR(p))) { + if (p == line && vim_isfilec(utf_ptr2char(p))) { startcol = 0; } else { startcol = (int)(p - line) + 1; @@ -5243,7 +5240,7 @@ static int ins_complete(int c, bool enable_pum) // Call 'completefunc' or 'omnifunc' and get pattern length as a string funcname = get_complete_funcname(ctrl_x_mode); if (*funcname == NUL) { - EMSG2(_(e_notset), ctrl_x_mode == CTRL_X_FUNCTION + semsg(_(e_notset), ctrl_x_mode == CTRL_X_FUNCTION ? "completefunc" : "omnifunc"); // restore did_ai, so that adding comment leader works did_ai = save_did_ai; @@ -5264,13 +5261,13 @@ static int ins_complete(int c, bool enable_pum) State = save_State; if (curwin_save != curwin || curbuf_save != curbuf) { - EMSG(_(e_complwin)); + emsg(_(e_complwin)); return FAIL; } curwin->w_cursor = pos; // restore the cursor position validate_cursor(); if (!equalpos(curwin->w_cursor, pos)) { - EMSG(_(e_compldel)); + emsg(_(e_compldel)); return FAIL; } @@ -5808,7 +5805,6 @@ void insertchar(int c, int flags, int second_indent) // Skip white space before the cursor i = curwin->w_cursor.col; while (--i >= 0 && ascii_iswhite(line[i])) { - ; } i++; @@ -6366,8 +6362,8 @@ void auto_format(bool trailblank, bool prev_line) curwin->w_cursor = pos; } - /* With the 'c' flag in 'formatoptions' and 't' missing: only format - * comments. */ + // With the 'c' flag in 'formatoptions' and 't' missing: only format + // comments. if (has_format_option(FO_WRAP_COMS) && !has_format_option(FO_WRAP) && get_leader_len(old, NULL, false, true) == 0) { return; @@ -7041,7 +7037,7 @@ int stuff_inserted(int c, long count, int no_esc) ptr = get_last_insert(); if (ptr == NULL) { - EMSG(_(e_noinstext)); + emsg(_(e_noinstext)); return FAIL; } @@ -7191,7 +7187,7 @@ void replace_push(int c) */ int replace_push_mb(char_u *p) { - int l = (*mb_ptr2len)(p); + int l = utfc_ptr2len(p); int j; for (j = l - 1; j >= 0; --j) { @@ -7347,7 +7343,7 @@ static void replace_do_bs(int limit_col) vcol = start_vcol; for (i = 0; i < ins_len; i++) { vcol += win_chartabsize(curwin, p + i, vcol); - i += (*mb_ptr2len)(p) - 1; + i += utfc_ptr2len(p) - 1; } vcol -= start_vcol; @@ -7393,7 +7389,8 @@ void fixthisline(IndentGetter get_the_indent) } } -void fix_indent(void) { +void fix_indent(void) +{ if (p_paste) { return; } @@ -7641,7 +7638,7 @@ int hkmap(int c) enum { hALEF = 0, BET, GIMEL, DALET, HEI, VAV, ZAIN, HET, TET, IUD, KAFsofit, hKAF, LAMED, MEMsofit, MEM, NUNsofit, NUN, SAMEH, AIN, - PEIsofit, PEI, ZADIsofit, ZADI, KOF, RESH, hSHIN, TAV + PEIsofit, PEI, ZADIsofit, ZADI, KOF, RESH, hSHIN, TAV, }; static char_u map[26] = { (char_u)hALEF /*a*/, (char_u)BET /*b*/, (char_u)hKAF /*c*/, @@ -7989,7 +7986,7 @@ static bool ins_esc(long *count, int cmdchar, bool nomove) if (reg_recording != 0 || restart_edit != NUL) { showmode(); } else if (p_smd) { - MSG(""); + msg(""); } // Exit Insert mode return true; @@ -8602,7 +8599,6 @@ static void ins_mousescroll(int dir) } - static void ins_left(void) { pos_T tpos; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index e6a3901dcf..0123c7265b 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -501,7 +501,7 @@ int var_redir_start(char_u *name, int append) // Catch a bad name early. if (!eval_isnamec1(*name)) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return FAIL; } @@ -521,9 +521,9 @@ int var_redir_start(char_u *name, int append) clear_lval(redir_lval); if (redir_endp != NULL && *redir_endp != NUL) { // Trailing characters are present after the variable name - EMSG(_(e_trailing)); + emsg(_(e_trailing)); } else { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } redir_endp = NULL; // don't store a value, only cleanup var_redir_stop(); @@ -728,7 +728,7 @@ static int eval1_emsg(char_u **arg, typval_T *rettv, bool evaluate) if (!aborting() && did_emsg == did_emsg_before && called_emsg == called_emsg_before) { - emsgf(_(e_invexpr2), start); + semsg(_(e_invexpr2), start); } } return ret; @@ -771,7 +771,7 @@ int eval_expr_typval(const typval_T *expr, typval_T *argv, int argc, typval_T *r } if (*skipwhite(s) != NUL) { // check for trailing chars after expr tv_clear(rettv); - emsgf(_(e_invexpr2), s); + semsg(_(e_invexpr2), s); return FAIL; } } @@ -1029,7 +1029,7 @@ list_T *eval_spell_expr(char_u *badword, char_u *expr) int get_spellword(list_T *const list, const char **ret_word) { if (tv_list_len(list) != 2) { - EMSG(_("E5700: Expression from 'spellsuggest' must yield lists with " + emsg(_("E5700: Expression from 'spellsuggest' must yield lists with " "exactly two values")); return -1; } @@ -1256,7 +1256,7 @@ static list_T *heredoc_get(exarg_T *eap, char_u *cmd) char_u *text_indent = NULL; if (eap->getline == NULL) { - EMSG(_("E991: cannot use =<< here")); + emsg(_("E991: cannot use =<< here")); return NULL; } @@ -1283,16 +1283,16 @@ static list_T *heredoc_get(exarg_T *eap, char_u *cmd) marker = skipwhite(cmd); p = skiptowhite(marker); if (*skipwhite(p) != NUL && *skipwhite(p) != '"') { - EMSG(_(e_trailing)); + emsg(_(e_trailing)); return NULL; } *p = NUL; if (islower(*marker)) { - EMSG(_("E221: Marker cannot start with lower case letter")); + emsg(_("E221: Marker cannot start with lower case letter")); return NULL; } } else { - EMSG(_("E172: Missing marker")); + emsg(_("E172: Missing marker")); return NULL; } @@ -1303,7 +1303,7 @@ static list_T *heredoc_get(exarg_T *eap, char_u *cmd) char_u *theline = eap->getline(NUL, eap->cookie, 0, false); if (theline == NULL) { - EMSG2(_("E990: Missing end marker '%s'"), marker); + semsg(_("E990: Missing end marker '%s'"), marker); break; } @@ -1385,7 +1385,7 @@ static void ex_let_const(exarg_T *eap, const bool is_const) && expr[1] == '=') || STRNCMP(expr, "..=", 3) == 0)) { // ":let" without "=": list variables if (*arg == '[') { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } else if (!ends_excmd(*arg)) { // ":let var1 var2" arg = (char_u *)list_arg_vars(eap, (const char *)arg, &first); @@ -1475,18 +1475,18 @@ static int ex_let_vars(char_u *arg_start, typval_T *tv, int copy, int semicolon, // ":let [v1, v2] = list" or ":for [v1, v2] in listlist" if (tv->v_type != VAR_LIST) { - EMSG(_(e_listreq)); + emsg(_(e_listreq)); return FAIL; } list_T *const l = tv->vval.v_list; const int len = tv_list_len(l); if (semicolon == 0 && var_count < len) { - EMSG(_("E687: Less targets than List items")); + emsg(_("E687: Less targets than List items")); return FAIL; } if (var_count - semicolon > len) { - EMSG(_("E688: More targets than List items")); + emsg(_("E688: More targets than List items")); return FAIL; } // List l may actually be NULL, but it should fail with E688 or even earlier @@ -1555,7 +1555,7 @@ static const char_u *skip_var_list(const char_u *arg, int *var_count, int *semic p = skipwhite(p + 1); // skip whites after '[', ';' or ',' s = skip_var_one(p); if (s == p) { - EMSG2(_(e_invarg2), p); + semsg(_(e_invarg2), p); return NULL; } ++*var_count; @@ -1565,12 +1565,12 @@ static const char_u *skip_var_list(const char_u *arg, int *var_count, int *semic break; } else if (*p == ';') { if (*semicolon == 1) { - EMSG(_("E452: Double ; in list of variables")); + emsg(_("E452: Double ; in list of variables")); return NULL; } *semicolon = 1; } else if (*p != ',') { - EMSG2(_(e_invarg2), p); + semsg(_(e_invarg2), p); return NULL; } } @@ -1690,7 +1690,7 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first) FNE_INCL_BR | FNE_CHECK_START); if (!ascii_iswhite(*arg) && !ends_excmd(*arg)) { emsg_severe = true; - EMSG(_(e_trailing)); + emsg(_(e_trailing)); break; } } else { @@ -1703,7 +1703,7 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first) * curly braces fails overrule the exception error message. */ if (len < 0 && !aborting()) { emsg_severe = true; - EMSG2(_(e_invarg2), arg); + semsg(_(e_invarg2), arg); break; } error = TRUE; @@ -1739,7 +1739,7 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first) case 'l': list_func_vars(first); break; default: - EMSG2(_("E738: Can't list variables for %s"), name); + semsg(_("E738: Can't list variables for %s"), name); } } else { char *const s = encode_tv2echo(&tv, NULL); @@ -1794,7 +1794,7 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv, const bool copy, cons */ if (*arg == '$') { if (is_const) { - EMSG(_("E996: Cannot lock an environment variable")); + emsg(_("E996: Cannot lock an environment variable")); return NULL; } // Find the end of the name. @@ -1802,13 +1802,13 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv, const bool copy, cons char *name = (char *)arg; len = get_env_len((const char_u **)&arg); if (len == 0) { - EMSG2(_(e_invarg2), name - 1); + semsg(_(e_invarg2), name - 1); } else { if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL) { - EMSG2(_(e_letwrong), op); + semsg(_(e_letwrong), op); } else if (endchars != NULL && vim_strchr(endchars, *skipwhite(arg)) == NULL) { - EMSG(_(e_letunexp)); + emsg(_(e_letunexp)); } else if (!check_secure()) { const char c1 = name[len]; name[len] = NUL; @@ -1843,7 +1843,7 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv, const bool copy, cons // ":let &g:option = expr": Set global option value. } else if (*arg == '&') { if (is_const) { - EMSG(_("E996: Cannot lock an option")); + emsg(_("E996: Cannot lock an option")); return NULL; } // Find the end of the name. @@ -1851,7 +1851,7 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv, const bool copy, cons if (p == NULL || (endchars != NULL && vim_strchr(endchars, *skipwhite((const char_u *)p)) == NULL)) { - EMSG(_(e_letunexp)); + emsg(_(e_letunexp)); } else { int opt_type; long numval; @@ -1870,7 +1870,7 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv, const bool copy, cons opt_flags); if ((opt_type == 1 && *op == '.') || (opt_type == 0 && *op != '.')) { - EMSG2(_(e_letwrong), op); + semsg(_(e_letwrong), op); s = NULL; // don't set the value } else { if (opt_type == 1) { // number @@ -1906,15 +1906,15 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv, const bool copy, cons // ":let @r = expr": Set register contents. } else if (*arg == '@') { if (is_const) { - EMSG(_("E996: Cannot lock a register")); + emsg(_("E996: Cannot lock a register")); return NULL; } arg++; if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL) { - emsgf(_(e_letwrong), op); + semsg(_(e_letwrong), op); } else if (endchars != NULL && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) { - EMSG(_(e_letunexp)); + emsg(_(e_letunexp)); } else { char_u *s; @@ -1946,7 +1946,7 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv, const bool copy, cons 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) { - EMSG(_(e_letunexp)); + emsg(_(e_letunexp)); } else { set_var_lval(&lv, p, tv, copy, is_const, (const char *)op); arg_end = p; @@ -1954,7 +1954,7 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv, const bool copy, cons } clear_lval(&lv); } else { - EMSG2(_(e_invarg2), arg); + semsg(_(e_invarg2), arg); } return arg_end; @@ -2018,7 +2018,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co // Don't expand the name when we already know there is an error. if (unlet && !ascii_iswhite(*p) && !ends_excmd(*p) && *p != '[' && *p != '.') { - EMSG(_(e_trailing)); + emsg(_(e_trailing)); return NULL; } @@ -2026,12 +2026,12 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co 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 - * aborting error, an interrupt, or an exception. */ + // Report an invalid expression in braces, unless the + // expression evaluation has been cancelled due to an + // aborting error, an interrupt, or an exception. if (!aborting() && !quiet) { emsg_severe = true; - EMSG2(_(e_invarg2), name); + semsg(_(e_invarg2), name); return NULL; } lp->ll_name_len = 0; @@ -2054,7 +2054,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co (flags & GLV_READ_ONLY) ? NULL : &ht, flags & GLV_NO_AUTOLOAD); if (v == NULL && !quiet) { - emsgf(_("E121: Undefined variable: %.*s"), + semsg(_("E121: Undefined variable: %.*s"), (int)lp->ll_name_len, lp->ll_name); } if (v == NULL) { @@ -2070,13 +2070,13 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co && !(lp->ll_tv->v_type == VAR_DICT && lp->ll_tv->vval.v_dict != NULL) && !(lp->ll_tv->v_type == VAR_BLOB && lp->ll_tv->vval.v_blob != NULL)) { if (!quiet) { - EMSG(_("E689: Can only index a List, Dictionary or Blob")); + emsg(_("E689: Can only index a List, Dictionary or Blob")); } return NULL; } if (lp->ll_range) { if (!quiet) { - EMSG(_("E708: [:] must come last")); + emsg(_("E708: [:] must come last")); } return NULL; } @@ -2089,7 +2089,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co } if (len == 0) { if (!quiet) { - EMSG(_("E713: Cannot use empty key after .")); + emsg(_("E713: Cannot use empty key after .")); } return NULL; } @@ -2116,7 +2116,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co if (*p == ':') { if (lp->ll_tv->v_type == VAR_DICT) { if (!quiet) { - EMSG(_(e_dictrange)); + emsg(_(e_dictrange)); } tv_clear(&var1); return NULL; @@ -2125,7 +2125,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co && !(rettv->v_type == VAR_LIST && rettv->vval.v_list != NULL) && !(rettv->v_type == VAR_BLOB && rettv->vval.v_blob != NULL)) { if (!quiet) { - EMSG(_("E709: [:] requires a List or Blob value")); + emsg(_("E709: [:] requires a List or Blob value")); } tv_clear(&var1); return NULL; @@ -2153,7 +2153,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co if (*p != ']') { if (!quiet) { - EMSG(_(e_missbrac)); + emsg(_(e_missbrac)); } tv_clear(&var1); tv_clear(&var2); @@ -2173,9 +2173,9 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co lp->ll_dict = lp->ll_tv->vval.v_dict; 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 - * g: dictionary). Disallow overwriting a builtin function. */ + // When assigning to a scope dictionary check that a function and + // variable name is valid (only variable name unless it is l: or + // g: dictionary). Disallow overwriting a builtin function. if (rettv != NULL && lp->ll_dict->dv_scope != 0) { int prevval; int wrong; @@ -2201,7 +2201,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co if (lp->ll_di != NULL && tv_is_luafunc(&lp->ll_di->di_tv) && len == -1 && rettv == NULL) { tv_clear(&var1); - EMSG2(e_illvar, "v:['lua']"); + semsg(e_illvar, "v:['lua']"); return NULL; } @@ -2209,7 +2209,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co // Can't add "v:" or "a:" variable. if (lp->ll_dict == &vimvardict || &lp->ll_dict->dv_hashtab == get_funccal_args_ht()) { - EMSG2(_(e_illvar), name); + semsg(_(e_illvar), name); tv_clear(&var1); return NULL; } @@ -2217,7 +2217,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co // Key does not exist in dict: may need to add it. if (*p == '[' || *p == '.' || unlet) { if (!quiet) { - emsgf(_(e_dictkey), key); + semsg(_(e_dictkey), key); } tv_clear(&var1); return NULL; @@ -2253,7 +2253,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co if (lp->ll_n1 < 0 || lp->ll_n1 > bloblen || (lp->ll_range && lp->ll_n1 == bloblen)) { if (!quiet) { - EMSGN(_(e_blobidx), lp->ll_n1); + semsg(_(e_blobidx), (int64_t)lp->ll_n1); } tv_clear(&var2); return NULL; @@ -2263,7 +2263,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co tv_clear(&var2); if (lp->ll_n2 < 0 || lp->ll_n2 >= bloblen || lp->ll_n2 < lp->ll_n1) { if (!quiet) { - EMSGN(_(e_blobidx), lp->ll_n2); + semsg(_(e_blobidx), (int64_t)lp->ll_n2); } return NULL; } @@ -2293,7 +2293,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co if (lp->ll_li == NULL) { tv_clear(&var2); if (!quiet) { - EMSGN(_(e_listidx), lp->ll_n1); + semsg(_(e_listidx), (int64_t)lp->ll_n1); } return NULL; } @@ -2309,7 +2309,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co ni = tv_list_find(lp->ll_list, lp->ll_n2); if (ni == NULL) { if (!quiet) { - EMSGN(_(e_listidx), lp->ll_n2); + semsg(_(e_listidx), (int64_t)lp->ll_n2); } return NULL; } @@ -2322,7 +2322,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co } if (lp->ll_n2 < lp->ll_n1) { if (!quiet) { - EMSGN(_(e_listidx), lp->ll_n2); + semsg(_(e_listidx), (int64_t)lp->ll_n2); } return NULL; } @@ -2367,7 +2367,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, co *endp = NUL; if (lp->ll_blob != NULL) { if (op != NULL && *op != '=') { - EMSG2(_(e_letwrong), op); + semsg(_(e_letwrong), op); return; } if (var_check_lock(lp->ll_blob->bv_lock, lp->ll_name, TV_CSTRING)) { @@ -2380,7 +2380,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, co } if (lp->ll_n2 - lp->ll_n1 + 1 != tv_blob_len(rettv->vval.v_blob)) { - EMSG(_("E972: Blob value does not have the right number of bytes")); + emsg(_("E972: Blob value does not have the right number of bytes")); return; } if (lp->ll_empty2) { @@ -2412,7 +2412,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, co typval_T tv; if (is_const) { - EMSG(_(e_cannot_mod)); + emsg(_(e_cannot_mod)); *endp = cc; return; } @@ -2442,7 +2442,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, co int ll_n1 = lp->ll_n1; if (is_const) { - EMSG(_("E996: Cannot lock a range")); + emsg(_("E996: Cannot lock a range")); return; } @@ -2487,12 +2487,12 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, co lp->ll_n1++; } if (ri != NULL) { - EMSG(_("E710: List value has more items than target")); + emsg(_("E710: List value has more items than target")); } else if (lp->ll_empty2 ? (lp->ll_li != NULL && TV_LIST_ITEM_NEXT(lp->ll_list, lp->ll_li) != NULL) : lp->ll_n1 != lp->ll_n2) { - EMSG(_("E711: List value has not enough items")); + emsg(_("E711: List value has not enough items")); } } else { typval_T oldtv = TV_INITIAL_VALUE; @@ -2500,14 +2500,14 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, co bool watched = tv_dict_is_watched(dict); if (is_const) { - EMSG(_("E996: Cannot lock a list or dict")); + emsg(_("E996: Cannot lock a list or dict")); return; } // Assign to a List or Dictionary item. if (lp->ll_newkey != NULL) { if (op != NULL && *op != '=') { - EMSG2(_(e_letwrong), op); + semsg(_(e_letwrong), op); return; } @@ -2579,7 +2579,7 @@ void *eval_for_line(const char_u *arg, bool *errp, char_u **nextcmdp, int skip) expr = skipwhite(expr); if (expr[0] != 'i' || expr[1] != 'n' || !ascii_iswhite(expr[2])) { - EMSG(_("E690: Missing \"in\" after :for")); + emsg(_("E690: Missing \"in\" after :for")); return fi; } @@ -2613,7 +2613,7 @@ void *eval_for_line(const char_u *arg, bool *errp, char_u **nextcmdp, int skip) } tv_clear(&tv); } else { - EMSG(_(e_listblobreq)); + emsg(_(e_listblobreq)); tv_clear(&tv); } } @@ -2758,8 +2758,8 @@ void set_context_for_expression(expand_T *xp, char_u *arg, cmdidx_T cmdidx) xp->xp_context = EXPAND_EXPRESSION; } } else { - /* Doesn't look like something valid, expand as an expression - * anyway. */ + // Doesn't look like something valid, expand as an expression + // anyway. xp->xp_context = EXPAND_EXPRESSION; } arg = xp->xp_pattern; @@ -2837,7 +2837,7 @@ static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep, ex_unletlock_ lv.ll_tv = NULL; arg++; if (get_env_len((const char_u **)&arg) == 0) { - EMSG2(_(e_invarg2), arg - 1); + semsg(_(e_invarg2), arg - 1); return; } if (!error && !eap->skip && callback(&lv, arg, eap, deep) == FAIL) { @@ -2855,7 +2855,7 @@ static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep, ex_unletlock_ || (!ascii_iswhite(*name_end) && !ends_excmd(*name_end))) { if (name_end != NULL) { emsg_severe = true; - EMSG(_(e_trailing)); + emsg(_(e_trailing)); } if (!(eap->skip || error)) { clear_lval(&lv); @@ -3037,7 +3037,7 @@ int do_unlet(const char *const name, const size_t name_len, const bool forceit) if (forceit) { return OK; } - EMSG2(_("E108: No such variable: \"%s\""), name); + semsg(_("E108: No such variable: \"%s\""), name); return FAIL; } @@ -3065,7 +3065,7 @@ static int do_lock_var(lval_T *lp, char_u *name_end FUNC_ATTR_UNUSED, exarg_T *e if (lp->ll_tv == NULL) { if (*lp->ll_name == '$') { - EMSG2(_(e_lock_unlock), lp->ll_name); + semsg(_(e_lock_unlock), lp->ll_name); ret = FAIL; } else { // Normal name or expanded name. @@ -3078,7 +3078,7 @@ static int do_lock_var(lval_T *lp, char_u *name_end FUNC_ATTR_UNUSED, exarg_T *e && 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. - EMSG2(_(e_lock_unlock), lp->ll_name); + semsg(_(e_lock_unlock), lp->ll_name); ret = FAIL; } else { if (lock) { @@ -3359,7 +3359,7 @@ int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate) // Also check called_emsg for when using assert_fails(). if (!aborting() && did_emsg == did_emsg_before && called_emsg == called_emsg_before) { - emsgf(_(e_invexpr2), arg); + semsg(_(e_invexpr2), arg); } ret = FAIL; } @@ -3421,7 +3421,7 @@ int eval1(char_u **arg, typval_T *rettv, int evaluate) * Check for the ":". */ if ((*arg)[0] != ':') { - EMSG(_("E109: Missing ':' after '?'")); + emsg(_("E109: Missing ':' after '?'")); if (evaluate && result) { tv_clear(rettv); } @@ -3978,7 +3978,7 @@ static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string) ) : f1 / f2); } else { - EMSG(_("E804: Cannot use '%' with Float")); + emsg(_("E804: Cannot use '%' with Float")); return FAIL; } rettv->v_type = VAR_FLOAT; @@ -4107,7 +4107,7 @@ static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string) for (bp = *arg + 2; ascii_isxdigit(bp[0]); bp += 2) { if (!ascii_isxdigit(bp[1])) { if (blob != NULL) { - EMSG(_("E973: Blob literal should have an even number of hex " + emsg(_("E973: Blob literal should have an even number of hex " "characters")); ga_clear(&blob->bv_ga); XFREE_CLEAR(blob); @@ -4130,7 +4130,7 @@ static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string) // decimal, hex or octal number vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, true); if (len == 0) { - EMSG2(_(e_invexpr2), *arg); + semsg(_(e_invexpr2), *arg); ret = FAIL; break; } @@ -4205,7 +4205,7 @@ static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string) if (**arg == ')') { ++*arg; } else if (ret == OK) { - EMSG(_("E110: Missing ')'")); + emsg(_("E110: Missing ')'")); tv_clear(rettv); ret = FAIL; } @@ -4378,9 +4378,9 @@ static int eval_lambda(char_u **const arg, typval_T *const rettv, const bool eva } else if (**arg != '(') { if (verbose) { if (*skipwhite(*arg) == '(') { - EMSG(_(e_nowhitespace)); + emsg(_(e_nowhitespace)); } else { - EMSG2(_(e_missingparen), "lambda"); + semsg(_(e_missingparen), "lambda"); } } tv_clear(rettv); @@ -4431,21 +4431,21 @@ static int eval_method(char_u **const arg, typval_T *const rettv, const bool eva if (len <= 0) { if (verbose) { if (lua_funcname == NULL) { - EMSG(_("E260: Missing name after ->")); + emsg(_("E260: Missing name after ->")); } else { - EMSG2(_(e_invexpr2), name); + semsg(_(e_invexpr2), name); } } ret = FAIL; } else { if (**arg != '(') { if (verbose) { - EMSG2(_(e_missingparen), name); + semsg(_(e_missingparen), name); } ret = FAIL; } else if (ascii_iswhite((*arg)[-1])) { if (verbose) { - EMSG(_(e_nowhitespace)); + emsg(_(e_nowhitespace)); } ret = FAIL; } else if (lua_funcname != NULL) { @@ -4489,18 +4489,18 @@ static int eval_index(char_u **arg, typval_T *rettv, int evaluate, int verbose) case VAR_FUNC: case VAR_PARTIAL: if (verbose) { - EMSG(_("E695: Cannot index a Funcref")); + emsg(_("E695: Cannot index a Funcref")); } return FAIL; case VAR_FLOAT: if (verbose) { - EMSG(_(e_float_as_string)); + emsg(_(e_float_as_string)); } return FAIL; case VAR_BOOL: case VAR_SPECIAL: if (verbose) { - EMSG(_("E909: Cannot index a special variable")); + emsg(_("E909: Cannot index a special variable")); } return FAIL; case VAR_UNKNOWN: @@ -4524,7 +4524,6 @@ static int eval_index(char_u **arg, typval_T *rettv, int evaluate, int verbose) */ key = *arg + 1; for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len) { - ; } if (len == 0) { return FAIL; @@ -4573,7 +4572,7 @@ static int eval_index(char_u **arg, typval_T *rettv, int evaluate, int verbose) // Check for the ']'. if (**arg != ']') { if (verbose) { - EMSG(_(e_missbrac)); + emsg(_(e_missbrac)); } tv_clear(&var1); if (range) { @@ -4681,7 +4680,7 @@ static int eval_index(char_u **arg, typval_T *rettv, int evaluate, int verbose) rettv->v_type = VAR_NUMBER; rettv->vval.v_number = v; } else { - EMSGN(_(e_blobidx), n1); + semsg(_(e_blobidx), (int64_t)n1); } } break; @@ -4695,7 +4694,7 @@ static int eval_index(char_u **arg, typval_T *rettv, int evaluate, int verbose) // list. A list index out of range is an error. if (!range) { if (verbose) { - EMSGN(_(e_listidx), n1); + semsg(_(e_listidx), (int64_t)n1); } return FAIL; } @@ -4730,7 +4729,7 @@ static int eval_index(char_u **arg, typval_T *rettv, int evaluate, int verbose) case VAR_DICT: { if (range) { if (verbose) { - EMSG(_(e_dictrange)); + emsg(_(e_dictrange)); } if (len == -1) { tv_clear(&var1); @@ -4750,7 +4749,7 @@ static int eval_index(char_u **arg, typval_T *rettv, int evaluate, int verbose) (const char *)key, len); if (item == NULL && verbose) { - emsgf(_(e_dictkey), key); + semsg(_(e_dictkey), key); } if (len == -1) { tv_clear(&var1); @@ -4802,7 +4801,7 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval char *option_end = (char *)find_option_end(arg, &opt_flags); if (option_end == NULL) { if (rettv != NULL) { - EMSG2(_("E112: Option name missing: %s"), *arg); + semsg(_("E112: Option name missing: %s"), *arg); } return FAIL; } @@ -4819,7 +4818,7 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval if (opt_type == -3) { // invalid name if (rettv != NULL) { - EMSG2(_("E113: Unknown option: %s"), *arg); + semsg(_("E113: Unknown option: %s"), *arg); } ret = FAIL; } else if (rettv != NULL) { @@ -4872,7 +4871,7 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate) } if (*p != '"') { - EMSG2(_("E114: Missing quote: %s"), *arg); + semsg(_("E114: Missing quote: %s"), *arg); return FAIL; } @@ -4927,9 +4926,9 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate) ++p; nr = (nr << 4) + hex2nr(*p); } - ++p; - /* For "\u" store the number according to - * 'encoding'. */ + p++; + // For "\u" store the number according to + // 'encoding'. if (c != 'X') { name += utf_char2bytes(nr, name); } else { @@ -4970,11 +4969,11 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate) FALLTHROUGH; default: - MB_COPY_CHAR(p, name); + mb_copy_char((const char_u **)&p, &name); break; } } else { - MB_COPY_CHAR(p, name); + mb_copy_char((const char_u **)&p, &name); } } *name = NUL; @@ -5010,7 +5009,7 @@ static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate) } if (*p != '\'') { - EMSG2(_("E115: Missing quote: %s"), *arg); + semsg(_("E115: Missing quote: %s"), *arg); return FAIL; } @@ -5034,7 +5033,7 @@ static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate) } ++p; } - MB_COPY_CHAR(p, str); + mb_copy_char((const char_u **)&p, &str); } *str = NUL; *arg = p + 1; @@ -5105,14 +5104,14 @@ static int get_list_tv(char_u **arg, typval_T *rettv, int evaluate) break; } if (**arg != ',') { - emsgf(_("E696: Missing comma in List: %s"), *arg); + semsg(_("E696: Missing comma in List: %s"), *arg); goto failret; } *arg = skipwhite(*arg + 1); } if (**arg != ']') { - emsgf(_("E697: Missing end of List ']': %s"), *arg); + semsg(_("E697: Missing end of List ']': %s"), *arg); failret: if (evaluate) { tv_list_free(l); @@ -5129,7 +5128,8 @@ failret: } /// @param ic ignore case -bool func_equal(typval_T *tv1, typval_T *tv2, bool ic) { +bool func_equal(typval_T *tv1, typval_T *tv2, bool ic) +{ char_u *s1, *s2; dict_T *d1, *d2; int a1, a2; @@ -5632,7 +5632,6 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, list_stack } - /// Mark all lists and dicts referenced in given mark /// /// @returns true if setting references failed somehow. @@ -5742,7 +5741,7 @@ static int dict_get_tv(char_u **arg, typval_T *rettv, int evaluate, bool literal goto failret; } if (**arg != ':') { - EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg); + semsg(_("E720: Missing colon in Dictionary: %s"), *arg); tv_clear(&tvkey); goto failret; } @@ -5765,7 +5764,7 @@ static int dict_get_tv(char_u **arg, typval_T *rettv, int evaluate, bool literal if (evaluate) { item = tv_dict_find(d, (const char *)key, -1); if (item != NULL) { - EMSG2(_("E721: Duplicate key in Dictionary: \"%s\""), key); + semsg(_("E721: Duplicate key in Dictionary: \"%s\""), key); tv_clear(&tvkey); tv_clear(&tv); goto failret; @@ -5783,14 +5782,14 @@ static int dict_get_tv(char_u **arg, typval_T *rettv, int evaluate, bool literal break; } if (**arg != ',') { - EMSG2(_("E722: Missing comma in Dictionary: %s"), *arg); + semsg(_("E722: Missing comma in Dictionary: %s"), *arg); goto failret; } *arg = skipwhite(*arg + 1); } if (**arg != '}') { - EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg); + semsg(_("E723: Missing end of Dictionary '}': %s"), *arg); failret: if (d != NULL) { tv_dict_free(d); @@ -6352,7 +6351,7 @@ int assert_match_common(typval_T *argvars, assert_type_T atype) const char *const text = tv_get_string_buf_chk(&argvars[1], buf2); if (pat == NULL || text == NULL) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } else if (pattern_match((char_u *)pat, (char_u *)text, false) != (atype == ASSERT_MATCH)) { garray_T ga; @@ -6420,7 +6419,7 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map) return; } } else { - EMSG2(_(e_listdictblobarg), ermsg); + semsg(_(e_listdictblobarg), ermsg); return; } @@ -6483,7 +6482,7 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map) break; } if (tv.v_type != VAR_NUMBER) { - EMSG(_(e_invalblob)); + emsg(_(e_invalblob)); return; } if (map) { @@ -6599,14 +6598,14 @@ void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref, FunPtr } if (s == NULL || *s == NUL || (use_string && ascii_isdigit(*s)) || (is_funcref && trans_name == NULL)) { - emsgf(_(e_invarg2), (use_string + semsg(_(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))) { - emsgf(_("E700: Unknown function: %s"), s); + semsg(_("E700: Unknown function: %s"), s); } else { int dict_idx = 0; int arg_idx = 0; @@ -6642,7 +6641,7 @@ void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref, FunPtr } if (dict_idx > 0) { if (argvars[dict_idx].v_type != VAR_DICT) { - EMSG(_("E922: expected a dict")); + emsg(_("E922: expected a dict")); xfree(name); goto theend; } @@ -6652,7 +6651,7 @@ void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref, FunPtr } if (arg_idx > 0) { if (argvars[arg_idx].v_type != VAR_LIST) { - EMSG(_("E923: Second argument of function() must be " + emsg(_("E923: Second argument of function() must be " "a list or a dict")); xfree(name); goto theend; @@ -6810,7 +6809,7 @@ void get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, typval_T *rettv) qf_get_properties(wp, d, rettv->vval.v_dict); } } else { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); } } } @@ -7015,7 +7014,7 @@ void get_user_input(const typval_T *const argvars, typval_T *const rettv, const char def[1] = { 0 }; if (argvars[0].v_type == VAR_DICT) { if (argvars[1].v_type != VAR_UNKNOWN) { - EMSG(_("E5050: {opts} must be the only argument")); + emsg(_("E5050: {opts} must be the only argument")); return; } dict_T *const dict = argvars[0].vval.v_dict; @@ -7134,7 +7133,7 @@ void get_user_input(const typval_T *const argvars, typval_T *const rettv, const void dict_list(typval_T *const tv, typval_T *const rettv, const DictListType what) { if (tv->v_type != VAR_DICT) { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); return; } if (tv->vval.v_dict == NULL) { @@ -7197,14 +7196,14 @@ char **tv_to_argv(typval_T *cmd_tv, const char **cmd, bool *executable) } if (cmd_tv->v_type != VAR_LIST) { - EMSG2(_(e_invarg2), "expected String or List"); + semsg(_(e_invarg2), "expected String or List"); return NULL; } list_T *argl = cmd_tv->vval.v_list; int argc = tv_list_len(argl); if (!argc) { - EMSG(_(e_invarg)); // List must have at least one item. + emsg(_(e_invarg)); // List must have at least one item. return NULL; } @@ -7214,7 +7213,7 @@ char **tv_to_argv(typval_T *cmd_tv, const char **cmd, bool *executable) if (arg0 && executable) { char buf[IOSIZE]; snprintf(buf, sizeof(buf), "'%s' is not executable", arg0); - EMSG3(_(e_invargNval), "cmd", buf); + semsg(_(e_invargNval), "cmd", buf); *executable = false; } return NULL; @@ -7294,7 +7293,7 @@ int matchadd_dict_arg(typval_T *tv, const char **conceal_char, win_T **win) dictitem_T *di; if (tv->v_type != VAR_DICT) { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); return FAIL; } @@ -7305,7 +7304,7 @@ int matchadd_dict_arg(typval_T *tv, const char **conceal_char, win_T **win) if ((di = tv_dict_find(tv->vval.v_dict, S_LEN("window"))) != NULL) { *win = find_win_by_nr_or_id(&di->di_tv); if (*win == NULL) { - EMSG(_(e_invalwindow)); + emsg(_(e_invalwindow)); return FAIL; } } @@ -7684,7 +7683,7 @@ bool callback_from_typval(Callback *const callback, typval_T *const arg) } if (r == FAIL) { - EMSG(_("E921: Invalid callback argument")); + emsg(_("E921: Invalid callback argument")); return false; } return true; @@ -7968,7 +7967,7 @@ bool write_list(FileDescriptor *const fp, const list_T *const list, const bool b } return true; write_list_error: - emsgf(_(e_write2), os_strerror(error)); + semsg(_(e_write2), os_strerror(error)); return false; } @@ -7996,7 +7995,7 @@ bool write_blob(FileDescriptor *const fp, const blob_T *const blob) } return true; write_blob_error: - EMSG2(_(e_write2), os_strerror(error)); + semsg(_(e_write2), os_strerror(error)); return false; } @@ -8063,7 +8062,7 @@ char *save_tv_as_string(typval_T *tv, ptrdiff_t *const len, bool endnl) *len += 1; } } else { - EMSGN(_(e_nobufnr), tv->vval.v_number); + semsg(_(e_nobufnr), tv->vval.v_number); *len = -1; return NULL; } @@ -8397,7 +8396,7 @@ int get_name_len(const char **const arg, char **alias, bool evaluate, bool verbo // Only give an error when there is something, otherwise it will be // reported at a higher level. if (len == 0 && verbose && **arg != NUL) { - EMSG2(_(e_invexpr2), *arg); + semsg(_(e_invexpr2), *arg); } return len; @@ -8452,7 +8451,7 @@ const char_u *find_name_end(const char_u *arg, const char_u **expr_start, const } } else if (br_nest == 0 && mb_nest == 0 && *p == ':') { // "s:" is start of "s:var", but "n:" is not and can be used in - // slice "[n:]". Also "xx:" is not a namespace. But {ns}: is. */ + // slice "[n:]". Also "xx:" is not a namespace. But {ns}: is. len = (int)(p - arg); if ((len > 1 && p[-1] != '}') || (len == 1 && vim_strchr(namespace_char, *arg) == NULL)) { @@ -8864,7 +8863,7 @@ int get_var_tv(const char *name, int len, typval_T *rettv, dictitem_T **dip, int if (tv == NULL) { if (rettv != NULL && verbose) { - emsgf(_("E121: Undefined variable: %.*s"), len, name); + semsg(_("E121: Undefined variable: %.*s"), len, name); } ret = FAIL; } else if (rettv != NULL) { @@ -9441,7 +9440,7 @@ static void set_var_const(const char *name, const size_t name_len, typval_T *con const bool watched = tv_dict_is_watched(dict); if (ht == NULL || *varname == NUL) { - EMSG2(_(e_illvar), name); + semsg(_(e_illvar), name); return; } v = find_var_in_ht(ht, 0, varname, name_len - (size_t)(varname - name), true); @@ -9458,7 +9457,7 @@ static void set_var_const(const char *name, const size_t name_len, typval_T *con typval_T oldtv = TV_INITIAL_VALUE; if (v != NULL) { if (is_const) { - EMSG(_(e_cannot_mod)); + emsg(_(e_cannot_mod)); return; } @@ -9497,7 +9496,7 @@ static void set_var_const(const char *name, const size_t name_len, typval_T *con } return; } else if (v->di_tv.v_type != tv->v_type) { - EMSG2(_("E963: setting %s to value with wrong type"), name); + semsg(_("E963: setting %s to value with wrong type"), name); return; } } @@ -9509,7 +9508,7 @@ static void set_var_const(const char *name, const size_t name_len, typval_T *con } else { // Add a new variable. // Can't add "v:" or "a:" variable. if (ht == &vimvarht || ht == get_funccal_args_ht()) { - emsgf(_(e_illvar), name); + semsg(_(e_illvar), name); return; } @@ -9597,7 +9596,7 @@ bool var_check_ro(const int flags, const char *name, size_t name_len) name_len = strlen(name); } - emsgf(_(error_message), (int)name_len, name); + semsg(_(error_message), (int)name_len, name); return true; } @@ -9630,7 +9629,7 @@ bool var_check_fixed(const int flags, const char *name, size_t name_len) } else if (name_len == TV_CSTRING) { name_len = strlen(name); } - EMSG3(_("E795: Cannot delete variable %.*s"), (int)name_len, name); + semsg(_("E795: Cannot delete variable %.*s"), (int)name_len, name); return true; } return false; @@ -9652,14 +9651,14 @@ bool var_check_func_name(const char *const name, const bool new_var) 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); + semsg(_("E704: Funcref variable name must start with a capital: %s"), name); 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, false)) { - EMSG2(_("E705: Variable name conflicts with existing function: %s"), + semsg(_("E705: Variable name conflicts with existing function: %s"), name); return false; } @@ -9681,7 +9680,7 @@ bool valid_varname(const char *varname) if (!eval_isnamec1((int)(uint8_t)(*p)) && (p == varname || !ascii_isdigit(*p)) && *p != AUTOLOAD_CHAR) { - emsgf(_(e_illvar), varname); + semsg(_(e_illvar), varname); return false; } } @@ -9712,7 +9711,7 @@ int var_item_copy(const vimconv_T *const conv, typval_T *const from, typval_T *c int ret = OK; if (recurse >= DICT_MAXNEST) { - EMSG(_("E698: variable nested too deep for making a copy")); + emsg(_("E698: variable nested too deep for making a copy")); return FAIL; } ++recurse; @@ -9814,7 +9813,7 @@ void ex_echo(exarg_T *eap) // exception. if (!aborting() && did_emsg == did_emsg_before && called_emsg == called_emsg_before) { - EMSG2(_(e_invexpr2), p); + semsg(_(e_invexpr2), p); } need_clr_eos = false; break; @@ -9825,12 +9824,12 @@ void ex_echo(exarg_T *eap) if (!eap->skip) { if (atstart) { atstart = false; - /* Call msg_start() after eval1(), evaluating the expression - * may cause a message to appear. */ + // Call msg_start() after eval1(), evaluating the expression + // may cause a message to appear. if (eap->cmdidx == CMD_echo) { - /* Mark the saved text as finishing the line, so that what - * follows is displayed on a new line when scrolling back - * at the more prompt. */ + // Mark the saved text as finishing the line, so that what + // follows is displayed on a new line when scrolling back + // at the more prompt. msg_sb_eol(); msg_start(); } @@ -9928,13 +9927,13 @@ void ex_execute(exarg_T *eap) if (eap->cmdidx == CMD_echomsg) { msg_ext_set_kind("echomsg"); - MSG_ATTR(ga.ga_data, echo_attr); + msg_attr(ga.ga_data, echo_attr); ui_flush(); } else if (eap->cmdidx == CMD_echoerr) { // We don't want to abort following commands, restore did_emsg. save_did_emsg = did_emsg; msg_ext_set_kind("echoerr"); - EMSG((char_u *)ga.ga_data); + emsg(ga.ga_data); if (!force_abort) { did_emsg = save_did_emsg; } @@ -10434,10 +10433,10 @@ void option_last_set_msg(LastSet last_set) bool should_free; char_u *p = get_scriptname(last_set, &should_free); verbose_enter(); - MSG_PUTS(_("\n\tLast set from ")); - MSG_PUTS(p); + msg_puts(_("\n\tLast set from ")); + msg_puts((char *)p); if (last_set.script_ctx.sc_lnum > 0) { - MSG_PUTS(_(line_msg)); + msg_puts(_(line_msg)); msg_outnum((long)last_set.script_ctx.sc_lnum); } if (should_free) { @@ -10837,7 +10836,7 @@ bool common_job_callbacks(dict_T *vopts, CallbackReader *on_stdout, CallbackRead Callback *on_exit) { if (tv_dict_get_callback(vopts, S_LEN("on_stdout"), &on_stdout->cb) - &&tv_dict_get_callback(vopts, S_LEN("on_stderr"), &on_stderr->cb) + && tv_dict_get_callback(vopts, S_LEN("on_stderr"), &on_stderr->cb) && tv_dict_get_callback(vopts, S_LEN("on_exit"), on_exit)) { on_stdout->buffered = tv_dict_get_number(vopts, "stdout_buffered"); on_stderr->buffered = tv_dict_get_number(vopts, "stderr_buffered"); @@ -10865,9 +10864,9 @@ Channel *find_job(uint64_t id, bool show_error) || process_is_stopped(&data->stream.proc)) { if (show_error) { if (data && data->streamtype != kChannelStreamProc) { - EMSG(_(e_invchanjob)); + emsg(_(e_invchanjob)); } else { - EMSG(_(e_invchan)); + emsg(_(e_invchan)); } } return NULL; @@ -10883,7 +10882,7 @@ void script_host_eval(char *name, typval_T *argvars, typval_T *rettv) } if (argvars[0].v_type != VAR_STRING) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -10897,7 +10896,7 @@ void script_host_eval(char *name, typval_T *argvars, typval_T *rettv) typval_T eval_call_provider(char *provider, char *method, list_T *arguments, bool discard) { if (!eval_has_provider(provider)) { - emsgf("E319: No \"%s\" provider found. Run \":checkhealth provider\"", + semsg("E319: No \"%s\" provider found. Run \":checkhealth provider\"", provider); return (typval_T){ .v_type = VAR_NUMBER, @@ -10989,7 +10988,7 @@ bool eval_has_provider(const char *feat) // Show a hint if Call() is defined but g:loaded_xx_provider is missing. snprintf(buf, sizeof(buf), "provider#%s#Call", name); if (!!find_func((char_u *)buf) && p_lpl) { - emsgf("provider: %s: missing required variable g:loaded_%s_provider", + semsg("provider: %s: missing required variable g:loaded_%s_provider", name, name); } return false; @@ -11004,7 +11003,7 @@ bool eval_has_provider(const char *feat) // Call() must be defined if provider claims to be working. snprintf(buf, sizeof(buf), "provider#%s#Call", name); if (!find_func((char_u *)buf)) { - emsgf("provider: %s: g:loaded_%s_provider=2 but %s is not defined", + semsg("provider: %s: g:loaded_%s_provider=2 but %s is not defined", name, name, buf); ok = false; } @@ -11034,13 +11033,13 @@ void ex_checkhealth(exarg_T *eap) if (!found) { const char *vimruntime_env = os_getenv("VIMRUNTIME"); if (vimruntime_env == NULL) { - EMSG(_("E5009: $VIMRUNTIME is empty or unset")); + emsg(_("E5009: $VIMRUNTIME is empty or unset")); } else { bool rtp_ok = NULL != strstr((char *)p_rtp, vimruntime_env); if (rtp_ok) { - EMSG2(_("E5009: Invalid $VIMRUNTIME: %s"), vimruntime_env); + semsg(_("E5009: Invalid $VIMRUNTIME: %s"), vimruntime_env); } else { - EMSG(_("E5009: Invalid 'runtimepath'")); + emsg(_("E5009: Invalid 'runtimepath'")); } } return; @@ -11129,9 +11128,9 @@ int typval_compare(typval_T *typ1, typval_T *typ2, exprtype_T type, bool ic) } else if (typ1->v_type != typ2->v_type || (type != EXPR_EQUAL && type != EXPR_NEQUAL)) { if (typ1->v_type != typ2->v_type) { - EMSG(_("E977: Can only compare Blob with Blob")); + emsg(_("E977: Can only compare Blob with Blob")); } else { - EMSG(_(e_invalblob)); + emsg(_(e_invalblob)); } tv_clear(typ1); return FAIL; @@ -11152,9 +11151,9 @@ int typval_compare(typval_T *typ1, typval_T *typ2, exprtype_T type, bool ic) } else if (typ1->v_type != typ2->v_type || (type != EXPR_EQUAL && type != EXPR_NEQUAL)) { if (typ1->v_type != typ2->v_type) { - EMSG(_("E691: Can only compare List with List")); + emsg(_("E691: Can only compare List with List")); } else { - EMSG(_("E692: Invalid operation for List")); + emsg(_("E692: Invalid operation for List")); } tv_clear(typ1); return FAIL; @@ -11175,9 +11174,9 @@ int typval_compare(typval_T *typ1, typval_T *typ2, exprtype_T type, bool ic) } else if (typ1->v_type != typ2->v_type || (type != EXPR_EQUAL && type != EXPR_NEQUAL)) { if (typ1->v_type != typ2->v_type) { - EMSG(_("E735: Can only compare Dictionary with Dictionary")); + emsg(_("E735: Can only compare Dictionary with Dictionary")); } else { - EMSG(_("E736: Invalid operation for Dictionary")); + emsg(_("E736: Invalid operation for Dictionary")); } tv_clear(typ1); return FAIL; @@ -11191,7 +11190,7 @@ int typval_compare(typval_T *typ1, typval_T *typ2, exprtype_T type, bool ic) } else if (tv_is_func(*typ1) || tv_is_func(*typ2)) { if (type != EXPR_EQUAL && type != EXPR_NEQUAL && type != EXPR_IS && type != EXPR_ISNOT) { - EMSG(_("E694: Invalid operation for Funcrefs")); + emsg(_("E694: Invalid operation for Funcrefs")); tv_clear(typ1); return FAIL; } diff --git a/src/nvim/eval.h b/src/nvim/eval.h index 3d656656de..d34348a274 100644 --- a/src/nvim/eval.h +++ b/src/nvim/eval.h @@ -70,7 +70,7 @@ typedef struct lval_S { typedef enum { VAR_FLAVOUR_DEFAULT = 1, // doesn't start with uppercase VAR_FLAVOUR_SESSION = 2, // starts with uppercase, some lower - VAR_FLAVOUR_SHADA = 4 // all uppercase + VAR_FLAVOUR_SHADA = 4, // all uppercase } var_flavour_T; /// Defines for Vim variables diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index c8734c9b9c..5008945f09 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -118,7 +118,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, ValuesStack *const stack if (last_container.container.v_type == VAR_LIST) { if (tv_list_len(last_container.container.vval.v_list) != 0 && !obj.didcomma) { - EMSG2(_("E474: Expected comma before list item: %s"), val_location); + semsg(_("E474: Expected comma before list item: %s"), val_location); tv_clear(&obj.val); return FAIL; } @@ -126,7 +126,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, ValuesStack *const stack tv_list_append_owned_tv(last_container.container.vval.v_list, obj.val); } else if (last_container.stack_index == kv_size(*stack) - 2) { if (!obj.didcolon) { - EMSG2(_("E474: Expected colon before dictionary value: %s"), + semsg(_("E474: Expected colon before dictionary value: %s"), val_location); tv_clear(&obj.val); return FAIL; @@ -153,13 +153,13 @@ static inline int json_decoder_pop(ValuesStackItem obj, ValuesStack *const stack } else { // Object with key only if (!obj.is_special_string && obj.val.v_type != VAR_STRING) { - EMSG2(_("E474: Expected string key: %s"), *pp); + semsg(_("E474: Expected string key: %s"), *pp); 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); + semsg(_("E474: Expected comma before dictionary key: %s"), val_location); tv_clear(&obj.val); return FAIL; } @@ -330,21 +330,21 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, if (*p == '\\') { p++; if (p == e) { - emsgf(_("E474: Unfinished escape sequence: %.*s"), + semsg(_("E474: Unfinished escape sequence: %.*s"), (int)buf_len, buf); goto parse_json_string_fail; } switch (*p) { case 'u': if (p + 4 >= e) { - emsgf(_("E474: Unfinished unicode escape sequence: %.*s"), + semsg(_("E474: Unfinished unicode escape sequence: %.*s"), (int)buf_len, buf); goto parse_json_string_fail; } else if (!ascii_isxdigit(p[1]) || !ascii_isxdigit(p[2]) || !ascii_isxdigit(p[3]) || !ascii_isxdigit(p[4])) { - emsgf(_("E474: Expected four hex digits after \\u: %.*s"), + semsg(_("E474: Expected four hex digits after \\u: %.*s"), LENP(p - 1, e)); goto parse_json_string_fail; } @@ -365,14 +365,14 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, p++; break; default: - emsgf(_("E474: Unknown escape sequence: %.*s"), LENP(p - 1, e)); + semsg(_("E474: Unknown escape sequence: %.*s"), LENP(p - 1, e)); goto parse_json_string_fail; } } else { uint8_t p_byte = (uint8_t)*p; // unescaped = %x20-21 / %x23-5B / %x5D-10FFFF if (p_byte < 0x20) { - emsgf(_("E474: ASCII control characters cannot be present " + semsg(_("E474: ASCII control characters cannot be present " "inside string: %.*s"), LENP(p, e)); goto parse_json_string_fail; } @@ -385,10 +385,10 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, // The only exception is U+00C3 which is represented as 0xC3 0x83. if (ch >= 0x80 && p_byte == ch && !(ch == 0xC3 && p + 1 < e && (uint8_t)p[1] == 0x83)) { - emsgf(_("E474: Only UTF-8 strings allowed: %.*s"), LENP(p, e)); + semsg(_("E474: Only UTF-8 strings allowed: %.*s"), LENP(p, e)); goto parse_json_string_fail; } else if (ch > 0x10FFFF) { - emsgf(_("E474: Only UTF-8 code points up to U+10FFFF " + semsg(_("E474: Only UTF-8 code points up to U+10FFFF " "are allowed to appear unescaped: %.*s"), LENP(p, e)); goto parse_json_string_fail; } @@ -399,7 +399,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, } } if (p == e || *p != '"') { - emsgf(_("E474: Expected string end: %.*s"), (int)buf_len, buf); + semsg(_("E474: Expected string end: %.*s"), (int)buf_len, buf); goto parse_json_string_fail; } if (len == 0) { @@ -546,7 +546,7 @@ static inline int parse_json_number(const char *const buf, const size_t buf_len, p++; } if (p != ints + 1 && *ints == '0') { - emsgf(_("E474: Leading zeroes are not allowed: %.*s"), LENP(s, e)); + semsg(_("E474: Leading zeroes are not allowed: %.*s"), LENP(s, e)); goto parse_json_number_fail; } if (p >= e || p == ints) { @@ -575,13 +575,13 @@ static inline int parse_json_number(const char *const buf, const size_t buf_len, } parse_json_number_check: if (p == ints) { - emsgf(_("E474: Missing number after minus sign: %.*s"), LENP(s, e)); + semsg(_("E474: Missing number after minus sign: %.*s"), LENP(s, e)); goto parse_json_number_fail; } else if (p == fracs || (fracs != NULL && exps_s == fracs + 1)) { - emsgf(_("E474: Missing number after decimal dot: %.*s"), LENP(s, e)); + semsg(_("E474: Missing number after decimal dot: %.*s"), LENP(s, e)); goto parse_json_number_fail; } else if (p == exps) { - emsgf(_("E474: Missing exponent: %.*s"), LENP(s, e)); + semsg(_("E474: Missing exponent: %.*s"), LENP(s, e)); goto parse_json_number_fail; } typval_T tv = { @@ -593,7 +593,7 @@ parse_json_number_check: // Convert floating-point number const size_t num_len = string2float(s, &tv.vval.v_float); if (exp_num_len != num_len) { - emsgf(_("E685: internal error: while converting number \"%.*s\" " + semsg(_("E685: internal error: while converting number \"%.*s\" " "to float string2float consumed %zu bytes in place of %zu"), (int)exp_num_len, s, num_len, exp_num_len); } @@ -604,7 +604,7 @@ parse_json_number_check: int num_len; vim_str2nr((char_u *)s, NULL, &num_len, 0, &nr, NULL, (int)(p - s), true); if ((int)exp_num_len != num_len) { - emsgf(_("E685: internal error: while converting number \"%.*s\" " + semsg(_("E685: internal error: while converting number \"%.*s\" " "to integer vim_str2nr consumed %i bytes in place of %zu"), (int)exp_num_len, s, num_len, exp_num_len); } @@ -656,7 +656,7 @@ int json_decode_string(const char *const buf, const size_t buf_len, typval_T *co p++; } if (p == e) { - EMSG(_("E474: Attempt to decode a blank string")); + emsg(_("E474: Attempt to decode a blank string")); return FAIL; } int ret = OK; @@ -673,26 +673,26 @@ json_decode_string_cycle_start: case '}': case ']': { if (kv_size(container_stack) == 0) { - emsgf(_("E474: No container to close: %.*s"), LENP(p, e)); + semsg(_("E474: No container to close: %.*s"), LENP(p, e)); goto json_decode_string_fail; } ContainerStackItem last_container = kv_last(container_stack); if (*p == '}' && last_container.container.v_type != VAR_DICT) { - emsgf(_("E474: Closing list with curly bracket: %.*s"), LENP(p, e)); + semsg(_("E474: Closing list with curly bracket: %.*s"), LENP(p, e)); goto json_decode_string_fail; } else if (*p == ']' && last_container.container.v_type != VAR_LIST) { - emsgf(_("E474: Closing dictionary with square bracket: %.*s"), + semsg(_("E474: Closing dictionary with square bracket: %.*s"), LENP(p, e)); goto json_decode_string_fail; } else if (didcomma) { - emsgf(_("E474: Trailing comma: %.*s"), LENP(p, e)); + semsg(_("E474: Trailing comma: %.*s"), LENP(p, e)); goto json_decode_string_fail; } else if (didcolon) { - emsgf(_("E474: Expected value after colon: %.*s"), LENP(p, e)); + semsg(_("E474: Expected value after colon: %.*s"), LENP(p, e)); goto json_decode_string_fail; } else if (last_container.stack_index != kv_size(stack) - 1) { assert(last_container.stack_index < kv_size(stack) - 1); - emsgf(_("E474: Expected value: %.*s"), LENP(p, e)); + semsg(_("E474: Expected value: %.*s"), LENP(p, e)); goto json_decode_string_fail; } if (kv_size(stack) == 1) { @@ -711,19 +711,19 @@ json_decode_string_cycle_start: } case ',': { if (kv_size(container_stack) == 0) { - emsgf(_("E474: Comma not inside container: %.*s"), LENP(p, e)); + semsg(_("E474: Comma not inside container: %.*s"), LENP(p, e)); goto json_decode_string_fail; } ContainerStackItem last_container = kv_last(container_stack); if (didcomma) { - emsgf(_("E474: Duplicate comma: %.*s"), LENP(p, e)); + semsg(_("E474: Duplicate comma: %.*s"), LENP(p, e)); goto json_decode_string_fail; } else if (didcolon) { - emsgf(_("E474: Comma after colon: %.*s"), LENP(p, e)); + semsg(_("E474: Comma after colon: %.*s"), LENP(p, e)); goto json_decode_string_fail; } else if (last_container.container.v_type == VAR_DICT && last_container.stack_index != kv_size(stack) - 1) { - emsgf(_("E474: Using comma in place of colon: %.*s"), LENP(p, e)); + semsg(_("E474: Using comma in place of colon: %.*s"), LENP(p, e)); goto json_decode_string_fail; } else if (last_container.special_val == NULL ? (last_container.container.v_type == VAR_DICT @@ -731,7 +731,7 @@ json_decode_string_cycle_start: : (tv_list_len(last_container.container.vval.v_list) == 0)) : (tv_list_len(last_container.special_val) == 0)) { - emsgf(_("E474: Leading comma: %.*s"), LENP(p, e)); + semsg(_("E474: Leading comma: %.*s"), LENP(p, e)); goto json_decode_string_fail; } didcomma = true; @@ -739,21 +739,21 @@ json_decode_string_cycle_start: } case ':': { if (kv_size(container_stack) == 0) { - emsgf(_("E474: Colon not inside container: %.*s"), LENP(p, e)); + semsg(_("E474: Colon not inside container: %.*s"), LENP(p, e)); goto json_decode_string_fail; } ContainerStackItem last_container = kv_last(container_stack); if (last_container.container.v_type != VAR_DICT) { - emsgf(_("E474: Using colon not in dictionary: %.*s"), LENP(p, e)); + semsg(_("E474: Using colon not in dictionary: %.*s"), LENP(p, e)); goto json_decode_string_fail; } else if (last_container.stack_index != kv_size(stack) - 2) { - emsgf(_("E474: Unexpected colon: %.*s"), LENP(p, e)); + semsg(_("E474: Unexpected colon: %.*s"), LENP(p, e)); goto json_decode_string_fail; } else if (didcomma) { - emsgf(_("E474: Colon after comma: %.*s"), LENP(p, e)); + semsg(_("E474: Colon after comma: %.*s"), LENP(p, e)); goto json_decode_string_fail; } else if (didcolon) { - emsgf(_("E474: Duplicate colon: %.*s"), LENP(p, e)); + semsg(_("E474: Duplicate colon: %.*s"), LENP(p, e)); goto json_decode_string_fail; } didcolon = true; @@ -766,7 +766,7 @@ json_decode_string_cycle_start: continue; case 'n': if ((p + 3) >= e || strncmp(p + 1, "ull", 3) != 0) { - emsgf(_("E474: Expected null: %.*s"), LENP(p, e)); + semsg(_("E474: Expected null: %.*s"), LENP(p, e)); goto json_decode_string_fail; } p += 3; @@ -778,7 +778,7 @@ json_decode_string_cycle_start: break; case 't': if ((p + 3) >= e || strncmp(p + 1, "rue", 3) != 0) { - emsgf(_("E474: Expected true: %.*s"), LENP(p, e)); + semsg(_("E474: Expected true: %.*s"), LENP(p, e)); goto json_decode_string_fail; } p += 3; @@ -790,7 +790,7 @@ json_decode_string_cycle_start: break; case 'f': if ((p + 4) >= e || strncmp(p + 1, "alse", 4) != 0) { - emsgf(_("E474: Expected false: %.*s"), LENP(p, e)); + semsg(_("E474: Expected false: %.*s"), LENP(p, e)); goto json_decode_string_fail; } p += 4; @@ -874,7 +874,7 @@ json_decode_string_cycle_start: break; } default: - emsgf(_("E474: Unidentified byte: %.*s"), LENP(p, e)); + semsg(_("E474: Unidentified byte: %.*s"), LENP(p, e)); goto json_decode_string_fail; } didcomma = false; @@ -893,7 +893,7 @@ json_decode_string_after_cycle: case CAR: break; default: - emsgf(_("E474: Trailing characters: %.*s"), LENP(p, e)); + semsg(_("E474: Trailing characters: %.*s"), LENP(p, e)); goto json_decode_string_fail; } } @@ -901,7 +901,7 @@ json_decode_string_after_cycle: *rettv = kv_pop(stack).val; goto json_decode_string_ret; } - emsgf(_("E474: Unexpected end of input: %.*s"), (int)buf_len, buf); + semsg(_("E474: Unexpected end of input: %.*s"), (int)buf_len, buf); json_decode_string_fail: ret = FAIL; while (kv_size(stack)) { diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index 2d4d9fdea9..b457353838 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -197,7 +197,7 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack, } } } - emsgf(msg, _(objname), (kv_size(*mpstack) == 0 + semsg(msg, _(objname), (kv_size(*mpstack) == 0 ? _("itself") : (char *)msg_ga.ga_data)); ga_clear(&msg_ga); @@ -381,7 +381,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s } else { \ ga_concat(gap, "function("); \ TYPVAL_ENCODE_CONV_STRING(tv, fun_, strlen(fun_)); \ - }\ + } \ } while (0) #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) \ @@ -448,7 +448,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s /* Only give this message once for a recursive call to avoid */ \ /* flooding the user with errors. */ \ did_echo_string_emsg = true; \ - EMSG(_("E724: unable to correctly dump variable " \ + emsg(_("E724: unable to correctly dump variable " \ "with self-referencing container")); \ } \ char ebuf[NUMBUFLEN + 7]; \ @@ -528,7 +528,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s /* Only give this message once for a recursive call to avoid */ \ /* flooding the user with errors. */ \ did_echo_string_emsg = true; \ - EMSG(_("E724: unable to correctly dump variable " \ + emsg(_("E724: unable to correctly dump variable " \ "with self-referencing container")); \ } \ } while (0) @@ -558,11 +558,11 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s const float_T flt_ = (flt); \ switch (xfpclassify(flt_)) { \ case FP_NAN: { \ - EMSG(_("E474: Unable to represent NaN value in JSON")); \ + emsg(_("E474: Unable to represent NaN value in JSON")); \ return FAIL; \ } \ case FP_INFINITE: { \ - EMSG(_("E474: Unable to represent infinity in JSON")); \ + emsg(_("E474: Unable to represent infinity in JSON")); \ return FAIL; \ } \ default: { \ @@ -630,14 +630,14 @@ static inline int convert_to_json_string(garray_T *const gap, const char *const break; default: if (ch > 0x7F && shift == 1) { - emsgf(_("E474: String \"%.*s\" contains byte that does not start " + semsg(_("E474: String \"%.*s\" contains byte that does not start " "any UTF-8 character"), (int)(utf_len - (i - shift)), utf_buf + i - shift); xfree(tofree); return FAIL; } else if ((SURROGATE_HI_START <= ch && ch <= SURROGATE_HI_END) || (SURROGATE_LO_START <= ch && ch <= SURROGATE_LO_END)) { - emsgf(_("E474: UTF-8 string contains code point which belongs " + semsg(_("E474: UTF-8 string contains code point which belongs " "to a surrogate pair: %.*s"), (int)(utf_len - (i - shift)), utf_buf + i - shift); xfree(tofree); @@ -719,7 +719,7 @@ static inline int convert_to_json_string(garray_T *const gap, const char *const #define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) \ do { \ xfree(buf); \ - EMSG(_("E474: Unable to convert EXT string to JSON")); \ + emsg(_("E474: Unable to convert EXT string to JSON")); \ return FAIL; \ } while (0) @@ -792,7 +792,7 @@ bool encode_check_json_key(const typval_T *const tv) #define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, key) \ do { \ if (!encode_check_json_key(&key)) { \ - EMSG(_("E474: Invalid key in special dictionary")); \ + emsg(_("E474: Invalid key in special dictionary")); \ goto label; \ } \ } while (0) diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c index 8eceda84cf..ed4f36f4c7 100644 --- a/src/nvim/eval/executor.c +++ b/src/nvim/eval/executor.c @@ -144,6 +144,6 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, const char *cons } } - EMSG2(_(e_letwrong), op); + semsg(_(e_letwrong), op); return FAIL; } diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 946bde060d..1d9ebdb596 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4,6 +4,7 @@ #include <float.h> #include <math.h> +#include "nvim/api/private/converter.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" #include "nvim/ascii.h" @@ -277,12 +278,12 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) Object result = fn(VIML_INTERNAL_CALL, args, &err); if (ERROR_SET(&err)) { - emsgf_multiline((const char *)e_api_error, err.msg); + semsg_multiline((const char *)e_api_error, err.msg); goto end; } if (!object_to_vim(result, rettv, &err)) { - EMSG2(_("Error converting the call result: %s"), err.msg); + semsg(_("Error converting the call result: %s"), err.msg); } end: @@ -339,7 +340,7 @@ static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } } else { - EMSG(_(e_listblobreq)); + emsg(_(e_listblobreq)); } } @@ -737,7 +738,8 @@ static void buf_win_common(typval_T *argvars, typval_T *rettv, bool get_nr) } /// "bufwinid(nr)" function -static void f_bufwinid(typval_T *argvars, typval_T *rettv, FunPtr fptr) { +static void f_bufwinid(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ buf_win_common(argvars, rettv, false); } @@ -812,7 +814,7 @@ buf_T *get_buf_arg(typval_T *arg) buf = tv_get_buf(arg, false); emsg_off--; if (buf == NULL) { - EMSG2(_("E158: Invalid buffer name: %s"), tv_get_string(arg)); + semsg(_("E158: Invalid buffer name: %s"), tv_get_string(arg)); } return buf; } @@ -874,7 +876,7 @@ static void f_byteidxcomp(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[1].v_type != VAR_LIST) { - EMSG(_(e_listreq)); + emsg(_(e_listreq)); return; } if (argvars[1].vval.v_list == NULL) { @@ -903,7 +905,7 @@ static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[2].v_type != VAR_UNKNOWN) { if (argvars[2].v_type != VAR_DICT) { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); return; } selfdict = argvars[2].vval.v_dict; @@ -935,7 +937,7 @@ static void f_chanclose(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type != VAR_NUMBER || (argvars[1].v_type != VAR_STRING && argvars[1].v_type != VAR_UNKNOWN)) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -951,14 +953,14 @@ static void f_chanclose(typval_T *argvars, typval_T *rettv, FunPtr fptr) } else if (!strcmp(stream, "rpc")) { part = kChannelPartRpc; } else { - EMSG2(_("Invalid channel stream \"%s\""), stream); + semsg(_("Invalid channel stream \"%s\""), stream); return; } } const char *error; rettv->vval.v_number = channel_close(argvars[0].vval.v_number, part, &error); if (!rettv->vval.v_number) { - EMSG(error); + emsg(error); } } @@ -974,7 +976,7 @@ static void f_chansend(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type != VAR_NUMBER || argvars[1].v_type == VAR_UNKNOWN) { // First argument is the channel id and second is the data to write - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -999,7 +1001,7 @@ static void f_chansend(typval_T *argvars, typval_T *rettv, FunPtr fptr) const char *error = NULL; rettv->vval.v_number = channel_send(id, input, input_len, true, &error); if (error) { - EMSG(error); + emsg(error); } } @@ -1026,7 +1028,7 @@ static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr) || argvars[1].v_type != VAR_NUMBER || (argvars[2].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_NUMBER)) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -1040,7 +1042,7 @@ static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr) countcc = (int)tv_get_number(&argvars[2]); } if (countcc < 0 || countcc > 1) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -1128,7 +1130,7 @@ static win_T *get_optional_window(typval_T *argvars, int idx) if (argvars[idx].v_type != VAR_UNKNOWN) { win = find_win_by_nr_or_id(&argvars[idx]); if (win == NULL) { - EMSG(_(e_invalwindow)); + emsg(_(e_invalwindow)); return NULL; } } @@ -1178,7 +1180,7 @@ static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr) - curwin->w_cursor.coladd))) { int l; - if (*p != NUL && p[(l = (*mb_ptr2len)(p))] == NUL) { + if (*p != NUL && p[(l = utfc_ptr2len(p))] == NUL) { col += l; } } @@ -1194,7 +1196,7 @@ static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if ((State & INSERT) == 0) { - EMSG(_("E785: complete() can only be used in Insert mode")); + emsg(_("E785: complete() can only be used in Insert mode")); return; } @@ -1205,7 +1207,7 @@ static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[1].v_type != VAR_LIST) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -1247,7 +1249,7 @@ static void f_complete_info(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type != VAR_UNKNOWN) { if (argvars[0].v_type != VAR_LIST) { - EMSG(_(e_listreq)); + emsg(_(e_listreq)); return; } what_list = argvars[0].vval.v_list; @@ -1370,7 +1372,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (!error) { li = tv_list_find(l, idx); if (li == NULL) { - EMSGN(_(e_listidx), idx); + semsg(_(e_listidx), (int64_t)idx); } } } @@ -1393,7 +1395,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) if ((d = argvars[0].vval.v_dict) != NULL) { if (argvars[2].v_type != VAR_UNKNOWN) { if (argvars[3].v_type != VAR_UNKNOWN) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } } @@ -1408,7 +1410,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } } else { - EMSG2(_(e_listdictarg), "count()"); + semsg(_(e_listdictarg), "count()"); } rettv->vval.v_number = n; } @@ -1445,13 +1447,13 @@ static void f_ctxget(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type == VAR_NUMBER) { index = argvars[0].vval.v_number; } else if (argvars[0].v_type != VAR_UNKNOWN) { - EMSG2(_(e_invarg2), "expected nothing or a Number as an argument"); + semsg(_(e_invarg2), "expected nothing or a Number as an argument"); return; } Context *ctx = ctx_get(index); if (ctx == NULL) { - EMSG3(_(e_invargNval), "index", "out of bounds"); + semsg(_(e_invargNval), "index", "out of bounds"); return; } @@ -1466,7 +1468,7 @@ static void f_ctxget(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_ctxpop(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (!ctx_restore(NULL, kCtxAll)) { - EMSG(_("Context stack is empty")); + emsg(_("Context stack is empty")); } } @@ -1495,7 +1497,7 @@ static void f_ctxpush(typval_T *argvars, typval_T *rettv, FunPtr fptr) } }); } else if (argvars[0].v_type != VAR_UNKNOWN) { - EMSG2(_(e_invarg2), "expected nothing or a List as an argument"); + semsg(_(e_invarg2), "expected nothing or a List as an argument"); return; } ctx_save(NULL, types); @@ -1505,7 +1507,7 @@ static void f_ctxpush(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_ctxset(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[0].v_type != VAR_DICT) { - EMSG2(_(e_invarg2), "expected dictionary as first argument"); + semsg(_(e_invarg2), "expected dictionary as first argument"); return; } @@ -1513,13 +1515,13 @@ static void f_ctxset(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[1].v_type == VAR_NUMBER) { index = argvars[1].vval.v_number; } else if (argvars[1].v_type != VAR_UNKNOWN) { - EMSG2(_(e_invarg2), "expected nothing or a Number as second argument"); + semsg(_(e_invarg2), "expected nothing or a Number as second argument"); return; } Context *ctx = ctx_get(index); if (ctx == NULL) { - EMSG3(_(e_invargNval), "index", "out of bounds"); + semsg(_(e_invargNval), "index", "out of bounds"); return; } @@ -1566,7 +1568,7 @@ static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr) colnr_T curswant = -1; if (list2fpos(argvars, &pos, NULL, &curswant) == FAIL) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -1613,7 +1615,7 @@ static void f_debugbreak(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = FAIL; pid = (int)tv_get_number(&argvars[0]); if (pid == 0) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } else { #ifdef WIN32 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); @@ -1638,7 +1640,7 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr) noref = tv_get_number_chk(&argvars[1], NULL); } if (noref < 0 || noref > 1) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } else { var_item_copy(NULL, &argvars[0], rettv, true, (noref == 0 ? get_copyID() @@ -1656,7 +1658,7 @@ static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr) const char *const name = tv_get_string(&argvars[0]); if (*name == NUL) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -1678,7 +1680,7 @@ static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr) // delete a directory recursively rettv->vval.v_number = delete_recursive(name); } else { - emsgf(_(e_invexpr2), flags); + semsg(_(e_invexpr2), flags); } } @@ -1690,17 +1692,17 @@ static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[0].v_type != VAR_DICT) { - emsgf(_(e_invarg2), "dict"); + semsg(_(e_invarg2), "dict"); return; } 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); + semsg(_(e_readonlyvar), (int)arg_errmsg_len, arg_errmsg); return; } if (argvars[1].v_type != VAR_STRING && argvars[1].v_type != VAR_NUMBER) { - emsgf(_(e_invarg2), "key"); + semsg(_(e_invarg2), "key"); return; } @@ -1712,7 +1714,7 @@ static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr) Callback callback; if (!callback_from_typval(&callback, &argvars[2])) { - emsgf(_(e_invarg2), "funcref"); + semsg(_(e_invarg2), "funcref"); return; } @@ -1728,12 +1730,12 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[0].v_type != VAR_DICT) { - emsgf(_(e_invarg2), "dict"); + semsg(_(e_invarg2), "dict"); return; } if (argvars[2].v_type != VAR_FUNC && argvars[2].v_type != VAR_STRING) { - emsgf(_(e_invarg2), "funcref"); + semsg(_(e_invarg2), "funcref"); return; } @@ -1749,7 +1751,7 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) 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"); + emsg("Couldn't find a watcher matching key and callback"); } callback_free(&callback); @@ -1811,7 +1813,7 @@ static void f_deletebufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (wp->w_buffer == buf) { if (wp->w_cursor.lnum > last) { wp->w_cursor.lnum -= count; - } else if (wp->w_cursor.lnum> first) { + } else if (wp->w_cursor.lnum > first) { wp->w_cursor.lnum = first; } if (wp->w_cursor.lnum > wp->w_buffer->b_ml.ml_line_count) { @@ -2037,13 +2039,13 @@ static void f_eval(typval_T *argvars, typval_T *rettv, FunPtr fptr) 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); + semsg(_(e_invexpr2), expr_start); } need_clr_eos = false; rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; } else if (*s != NUL) { - EMSG(_(e_trailing)); + emsg(_(e_trailing)); } } @@ -2201,7 +2203,7 @@ static void f_win_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "exepath()" function static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - if (tv_check_for_string(&argvars[0]) == FAIL) { + if (tv_check_for_nonempty_string(&argvars[0]) == FAIL) { return; } @@ -2261,7 +2263,7 @@ static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) { size_t len; - char_u *errormsg; + char *errormsg; int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND; expand_T xpc; bool error = false; @@ -2346,7 +2348,7 @@ static void f_menu_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) // Expand all the special characters in a command string. static void f_expandcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *errormsg = NULL; + char *errormsg = NULL; rettv->v_type = VAR_STRING; char_u *cmdstr = (char_u *)xstrdup(tv_get_string(&argvars[0])); @@ -2362,7 +2364,7 @@ static void f_expandcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr) expand_filename(&eap, &cmdstr, &errormsg); if (errormsg != NULL && *errormsg != NUL) { - EMSG(errormsg); + emsg(errormsg); } rettv->vval.v_string = cmdstr; } @@ -2376,7 +2378,7 @@ static void f_flatten(typval_T *argvars, typval_T *rettv, FunPtr fptr) bool error = false; if (argvars[0].v_type != VAR_LIST) { - EMSG2(_(e_listarg), "flatten()"); + semsg(_(e_listarg), "flatten()"); return; } @@ -2388,7 +2390,7 @@ static void f_flatten(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } if (maxdepth < 0) { - EMSG(_("E900: maxdepth must be non-negative number")); + emsg(_("E900: maxdepth must be non-negative number")); return; } } @@ -2430,7 +2432,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) } else { item = tv_list_find(l1, before); if (item == NULL) { - EMSGN(_(e_listidx), before); + semsg(_(e_listidx), (int64_t)before); return; } } @@ -2469,7 +2471,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } if (i == 3) { - EMSG2(_(e_invarg2), action); + semsg(_(e_invarg2), action); return; } } @@ -2479,7 +2481,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_copy(&argvars[0], rettv); } } else { - EMSG2(_(e_listdictarg), "extend()"); + semsg(_(e_listdictarg), "extend()"); } } @@ -2661,9 +2663,9 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr) 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) { + if (fname == NULL) { fname = NULL; - } else { + } else if (mods != NULL && *mods != NUL) { len = strlen(fname); size_t usedlen = 0; if (*mods != NUL) { @@ -2926,7 +2928,7 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_list_append_tv(rettv->vval.v_list, &pt->pt_argv[i]); } } else { - EMSG2(_(e_invarg2), what); + semsg(_(e_invarg2), what); } // When {what} == "dict" and pt->pt_dict == NULL, evaluate the @@ -2936,7 +2938,7 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } } else { - EMSG2(_(e_listdictblobarg), "get()"); + semsg(_(e_listdictblobarg), "get()"); } if (tv == NULL) { @@ -3359,10 +3361,10 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr) expand_T xpc; bool filtered = false; int options = WILD_SILENT | WILD_USE_NL | WILD_ADD_SLASH - | WILD_NO_BEEP; + | WILD_NO_BEEP | WILD_HOME_REPLACE; if (argvars[1].v_type != VAR_STRING) { - EMSG2(_(e_invarg2), "type must be a string"); + semsg(_(e_invarg2), "type must be a string"); return; } const char *const type = tv_get_string(&argvars[1]); @@ -3381,7 +3383,7 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[0].v_type != VAR_STRING) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -3396,7 +3398,7 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr) xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); xpc.xp_context = cmdcomplete_str_to_type(type); if (xpc.xp_context == EXPAND_NOTHING) { - EMSG2(_(e_invarg2), type); + semsg(_(e_invarg2), type); return; } @@ -3465,13 +3467,13 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) break; } if (argvars[i].v_type != VAR_NUMBER) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } scope_number[i] = argvars[i].vval.v_number; // It is an error for the scope number to be less than `-1`. if (scope_number[i] < -1) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } // Use the narrowest scope the user requested @@ -3492,7 +3494,7 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (scope_number[kCdScopeTabpage] > 0) { tp = find_tabpage(scope_number[kCdScopeTabpage]); if (!tp) { - EMSG(_("E5000: Cannot find tab number.")); + emsg(_("E5000: Cannot find tab number.")); return; } } @@ -3500,14 +3502,14 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) // Find the window in `tp` by number, `NULL` if none. if (scope_number[kCdScopeWindow] >= 0) { if (scope_number[kCdScopeTabpage] < 0) { - EMSG(_("E5001: Higher scope cannot be -1 if lower scope is >= 0.")); + emsg(_("E5001: Higher scope cannot be -1 if lower scope is >= 0.")); return; } if (scope_number[kCdScopeWindow] > 0) { win = find_win_by_nr(&argvars[0], tp); if (!win) { - EMSG(_("E5002: Cannot find window number.")); + emsg(_("E5002: Cannot find window number.")); return; } } @@ -4148,12 +4150,12 @@ static void f_wait(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = -1; if (argvars[0].v_type != VAR_NUMBER) { - EMSG2(_(e_invargval), "1"); + semsg(_(e_invargval), "1"); return; } if ((argvars[2].v_type != VAR_NUMBER && argvars[2].v_type != VAR_UNKNOWN) || (argvars[2].v_type == VAR_NUMBER && argvars[2].vval.v_number <= 0)) { - EMSG2(_(e_invargval), "3"); + semsg(_(e_invargval), "3"); return; } @@ -4260,7 +4262,7 @@ static void f_win_splitmove(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (wp == NULL || targetwin == NULL || wp == targetwin || !win_valid(wp) || !win_valid(targetwin) || win_valid_floating(wp) || win_valid_floating(targetwin)) { - EMSG(_(e_invalwindow)); + emsg(_(e_invalwindow)); rettv->vval.v_number = -1; return; } @@ -4270,7 +4272,7 @@ static void f_win_splitmove(typval_T *argvars, typval_T *rettv, FunPtr fptr) dictitem_T *di; if (argvars[2].v_type != VAR_DICT || argvars[2].vval.v_dict == NULL) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -4552,9 +4554,6 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) "windows", "winaltkeys", "writebackup", -#if defined(HAVE_WSL) - "wsl", -#endif "nvim", }; @@ -4601,6 +4600,8 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) n = syntax_present(curwin); } else if (STRICMP(name, "clipboard_working") == 0) { n = eval_has_provider("clipboard"); + } else if (STRICMP(name, "wsl") == 0) { + n = has_wsl(); #ifdef UNIX } else if (STRICMP(name, "unnamedplus") == 0) { n = eval_has_provider("clipboard"); @@ -4615,13 +4616,27 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = n; } -/* - * "has_key()" function - */ +static bool has_wsl(void) +{ + static TriState has_wsl = kNone; + if (has_wsl == kNone) { + Error err = ERROR_INIT; + Object o = nlua_exec(STATIC_CSTR_AS_STRING("return vim.loop.os_uname()['release']:lower()" + ":match('microsoft') and true or false"), + (Array)ARRAY_DICT_INIT, &err); + assert(!ERROR_SET(&err)); + assert(o.type == kObjectTypeBoolean); + has_wsl = o.data.boolean ? kTrue : kFalse; + api_free_object(o); + } + return has_wsl == kTrue; +} + +/// "has_key()" function static void f_has_key(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[0].v_type != VAR_DICT) { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); return; } if (argvars[0].vval.v_dict == NULL) { @@ -4668,12 +4683,12 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr) break; } if (argvars[i].v_type != VAR_NUMBER) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } scope_number[i] = argvars[i].vval.v_number; if (scope_number[i] < -1) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } // Use the narrowest scope the user requested @@ -4694,7 +4709,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (scope_number[kCdScopeTabpage] > 0) { tp = find_tabpage(scope_number[kCdScopeTabpage]); if (!tp) { - EMSG(_("E5000: Cannot find tab number.")); + emsg(_("E5000: Cannot find tab number.")); return; } } @@ -4702,14 +4717,14 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr) // Find the window in `tp` by number, `NULL` if none. if (scope_number[kCdScopeWindow] >= 0) { if (scope_number[kCdScopeTabpage] < 0) { - EMSG(_("E5001: Higher scope cannot be -1 if lower scope is >= 0.")); + emsg(_("E5001: Higher scope cannot be -1 if lower scope is >= 0.")); return; } if (scope_number[kCdScopeWindow] > 0) { win = find_win_by_nr(&argvars[0], tp); if (!win) { - EMSG(_("E5002: Cannot find window number.")); + emsg(_("E5002: Cannot find window number.")); return; } } @@ -4958,7 +4973,7 @@ static void f_index(typval_T *argvars, typval_T *rettv, FunPtr fptr) } return; } else if (argvars[0].v_type != VAR_LIST) { - EMSG(_(e_listblobreq)); + emsg(_(e_listblobreq)); return; } list_T *const l = argvars[0].vval.v_list; @@ -5020,7 +5035,7 @@ static void f_inputlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) int mouse_used; if (argvars[0].v_type != VAR_LIST) { - EMSG2(_(e_listarg), "inputlist()"); + semsg(_(e_listarg), "inputlist()"); return; } @@ -5105,7 +5120,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; // type error; errmsg already given } if (before < 0 || before > len) { - EMSG2(_(e_invarg2), tv_get_string(&argvars[2])); + semsg(_(e_invarg2), tv_get_string(&argvars[2])); return; } } @@ -5114,7 +5129,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } if (val < 0 || val > 255) { - EMSG2(_(e_invarg2), tv_get_string(&argvars[1])); + semsg(_(e_invarg2), tv_get_string(&argvars[1])); return; } @@ -5126,7 +5141,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_copy(&argvars[0], rettv); } else if (argvars[0].v_type != VAR_LIST) { - EMSG2(_(e_listblobarg), "insert()"); + semsg(_(e_listblobarg), "insert()"); } else if (!var_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), N_("insert() argument"), TV_TRANSLATE)) { long before = 0; @@ -5142,7 +5157,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (before != tv_list_len(l)) { item = tv_list_find(l, before); if (item == NULL) { - EMSGN(_(e_listidx), before); + semsg(_(e_listidx), (int64_t)before); l = NULL; } } @@ -5192,7 +5207,7 @@ static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr) FNE_CHECK_START); if (end != NULL && lv.ll_name != NULL) { if (*end != NUL) { - EMSG(_(e_trailing)); + emsg(_(e_trailing)); } else { if (lv.ll_tv == NULL) { di = find_var(lv.ll_name, lv.ll_name_len, NULL, true); @@ -5205,9 +5220,9 @@ static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr) || tv_islocked(&di->di_tv)); } } else if (lv.ll_range) { - EMSG(_("E786: Range not allowed")); + emsg(_("E786: Range not allowed")); } else if (lv.ll_newkey != NULL) { - EMSG2(_(e_dictkey), lv.ll_newkey); + semsg(_(e_dictkey), lv.ll_newkey); } else if (lv.ll_list != NULL) { // List item. rettv->vval.v_number = tv_islocked(TV_LIST_ITEM_TV(lv.ll_li)); @@ -5267,7 +5282,7 @@ static void f_jobpid(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[0].v_type != VAR_NUMBER) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -5293,7 +5308,7 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type != VAR_NUMBER || argvars[1].v_type != VAR_NUMBER || argvars[2].v_type != VAR_NUMBER) { // job id, width, height - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -5304,7 +5319,7 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (data->stream.proc.type != kProcessTypePty) { - EMSG(_(e_channotpty)); + emsg(_(e_channotpty)); return; } @@ -5447,7 +5462,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[1].v_type != VAR_DICT && argvars[1].v_type != VAR_UNKNOWN) { // Wrong argument types - EMSG2(_(e_invarg2), "expected dictionary"); + semsg(_(e_invarg2), "expected dictionary"); shell_free_argv(argv); return; } @@ -5481,19 +5496,19 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) } else if (!strncmp(s, "pipe", NUMBUFLEN)) { // Nothing to do, default value } else { - EMSG3(_(e_invargNval), "stdin", s); + semsg(_(e_invargNval), "stdin", s); } } if (pty && rpc) { - EMSG2(_(e_invarg2), "job cannot have both 'pty' and 'rpc' options set"); + semsg(_(e_invarg2), "job cannot have both 'pty' and 'rpc' options set"); shell_free_argv(argv); return; } #ifdef WIN32 if (pty && overlapped) { - EMSG2(_(e_invarg2), + semsg(_(e_invarg2), "job cannot have both 'pty' and 'overlapped' options set"); shell_free_argv(argv); return; @@ -5505,7 +5520,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) cwd = new_cwd; // The new cwd must be a directory. if (!os_isdir_executable((const char *)cwd)) { - EMSG2(_(e_invarg2), "expected valid directory"); + semsg(_(e_invarg2), "expected valid directory"); shell_free_argv(argv); return; } @@ -5513,7 +5528,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) job_env = tv_dict_find(job_opts, S_LEN("env")); if (job_env && job_env->di_tv.v_type != VAR_DICT) { - EMSG2(_(e_invarg2), "env"); + semsg(_(e_invarg2), "env"); shell_free_argv(argv); return; } @@ -5560,7 +5575,7 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type != VAR_NUMBER) { // Only argument is the job id - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -5577,7 +5592,7 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) process_stop(&data->stream.proc); rettv->vval.v_number = 1; if (error) { - EMSG(error); + emsg(error); } } @@ -5592,7 +5607,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[0].v_type != VAR_LIST || (argvars[1].v_type != VAR_NUMBER && argvars[1].v_type != VAR_UNKNOWN)) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -5686,7 +5701,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_join(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[0].v_type != VAR_LIST) { - EMSG(_(e_listreq)); + emsg(_(e_listreq)); return; } const char *const sep = (argvars[1].v_type == VAR_UNKNOWN @@ -5715,7 +5730,7 @@ static void f_json_decode(typval_T *argvars, typval_T *rettv, FunPtr fptr) size_t len; if (argvars[0].v_type == VAR_LIST) { if (!encode_vim_list_to_buf(argvars[0].vval.v_list, &len, &tofree)) { - EMSG(_("E474: Failed to convert list to string")); + emsg(_("E474: Failed to convert list to string")); return; } s = tofree; @@ -5732,7 +5747,7 @@ static void f_json_decode(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } if (json_decode_string(s, len, rettv) == FAIL) { - emsgf(_("E474: Failed to parse %.*s"), (int)len, s); + semsg(_("E474: Failed to parse %.*s"), (int)len, s); rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; } @@ -5796,7 +5811,7 @@ static void f_len(typval_T *argvars, typval_T *rettv, FunPtr fptr) case VAR_FLOAT: case VAR_PARTIAL: case VAR_FUNC: - EMSG(_("E701: Invalid type for len()")); + emsg(_("E701: Invalid type for len()")); break; } } @@ -5837,7 +5852,7 @@ static void libcall_common(typval_T *argvars, typval_T *rettv, int out_type) str_out, &int_out); if (!success) { - EMSG2(_(e_libcall), funcname); + semsg(_(e_libcall), funcname); return; } @@ -5935,7 +5950,7 @@ static void f_list2str(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; if (argvars[0].v_type != VAR_LIST) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -6196,7 +6211,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, idx++; } else { startcol = (colnr_T)(regmatch.startp[0] - + (*mb_ptr2len)(regmatch.startp[0]) - str); + + utfc_ptr2len(regmatch.startp[0]) - str); if (startcol > (colnr_T)len || str + startcol <= regmatch.startp[0]) { match = false; break; @@ -6323,7 +6338,7 @@ static void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } if (id >= 1 && id <= 3) { - EMSGN(_("E798: ID is reserved for \":match\": %" PRId64), id); + semsg(_("E798: ID is reserved for \":match\": %" PRId64), (int64_t)id); return; } @@ -6341,7 +6356,7 @@ static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[1].v_type != VAR_LIST) { - EMSG2(_(e_listarg), "matchaddpos()"); + semsg(_(e_listarg), "matchaddpos()"); return; } @@ -6373,7 +6388,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); + semsg(_("E798: ID is reserved for \"match\": %" PRId64), (int64_t)id); return; } @@ -6492,7 +6507,7 @@ static void max_min(const typval_T *const tv, typval_T *const rettv, const bool } }); } else { - EMSG2(_(e_listdictarg), domax ? "max()" : "min()"); + semsg(_(e_listdictarg), domax ? "max()" : "min()"); return; } rettv->vval.v_number = n; @@ -6548,7 +6563,7 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) char *failed_dir; int ret = os_mkdir_recurse(dir, prot, &failed_dir); if (ret != 0) { - EMSG3(_(e_mkdir), failed_dir, os_strerror(ret)); + semsg(_(e_mkdir), failed_dir, os_strerror(ret)); xfree(failed_dir); rettv->vval.v_number = FAIL; return; @@ -6581,7 +6596,7 @@ static void f_msgpackdump(typval_T *argvars, typval_T *rettv, FunPtr fptr) FUNC_ATTR_NONNULL_ALL { if (argvars[0].v_type != VAR_LIST) { - EMSG2(_(e_listarg), "msgpackdump()"); + semsg(_(e_listarg), "msgpackdump()"); return; } list_T *const list = argvars[0].vval.v_list; @@ -6614,21 +6629,21 @@ static int msgpackparse_convert_item(const msgpack_object data, const msgpack_un { switch (result) { case MSGPACK_UNPACK_PARSE_ERROR: - EMSG2(_(e_invarg2), "Failed to parse msgpack string"); + semsg(_(e_invarg2), "Failed to parse msgpack string"); return FAIL; case MSGPACK_UNPACK_NOMEM_ERROR: - EMSG(_(e_outofmem)); + emsg(_(e_outofmem)); return FAIL; case MSGPACK_UNPACK_CONTINUE: if (fail_if_incomplete) { - EMSG2(_(e_invarg2), "Incomplete msgpack string"); + semsg(_(e_invarg2), "Incomplete msgpack string"); return FAIL; } return NOTDONE; case MSGPACK_UNPACK_SUCCESS: { typval_T tv = { .v_type = VAR_UNKNOWN }; if (msgpack_to_vim(data, &tv) == FAIL) { - EMSG2(_(e_invarg2), "Failed to convert msgpack string"); + semsg(_(e_invarg2), "Failed to convert msgpack string"); return FAIL; } tv_list_append_owned_tv(ret_list, tv); @@ -6646,27 +6661,27 @@ static void msgpackparse_unpack_list(const list_T *const list, list_T *const ret return; } if (TV_LIST_ITEM_TV(tv_list_first(list))->v_type != VAR_STRING) { - EMSG2(_(e_invarg2), "List item is not a string"); + semsg(_(e_invarg2), "List item is not a string"); return; } ListReaderState lrstate = encode_init_lrstate(list); msgpack_unpacker *const unpacker = msgpack_unpacker_new(IOSIZE); if (unpacker == NULL) { - EMSG(_(e_outofmem)); + emsg(_(e_outofmem)); return; } msgpack_unpacked unpacked; msgpack_unpacked_init(&unpacked); do { if (!msgpack_unpacker_reserve_buffer(unpacker, IOSIZE)) { - EMSG(_(e_outofmem)); + emsg(_(e_outofmem)); goto end; } size_t read_bytes; const int rlret = encode_read_from_list(&lrstate, msgpack_unpacker_buffer(unpacker), IOSIZE, &read_bytes); if (rlret == FAIL) { - EMSG2(_(e_invarg2), "List item is not a string"); + semsg(_(e_invarg2), "List item is not a string"); goto end; } msgpack_unpacker_buffer_consumed(unpacker, read_bytes); @@ -6720,7 +6735,7 @@ static void f_msgpackparse(typval_T *argvars, typval_T *rettv, FunPtr fptr) FUNC_ATTR_NONNULL_ALL { if (argvars[0].v_type != VAR_LIST && argvars[0].v_type != VAR_BLOB) { - EMSG2(_(e_listblobarg), "msgpackparse()"); + semsg(_(e_listblobarg), "msgpackparse()"); return; } list_T *const ret_list = tv_list_alloc_ret(rettv, kListLenMayKnow); @@ -6767,11 +6782,11 @@ static void f_nr2char(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } if (num < 0) { - EMSG(_("E5070: Character number must not be less than zero")); + emsg(_("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)"), + semsg(_("E5071: Character number must not be greater than INT_MAX (%i)"), INT_MAX); return; } @@ -7033,9 +7048,9 @@ static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; // Type error; errmsg already given. } if (stride == 0) { - EMSG(_("E726: Stride is zero")); + emsg(_("E726: Stride is zero")); } else if (stride > 0 ? end + 1 < start : end - 1 > start) { - EMSG(_("E727: Start past end")); + emsg(_("E727: Start past end")); } else { tv_list_alloc_ret(rettv, (end - start) / stride); for (i = start; stride > 0 ? i <= end : i >= end; i += stride) { @@ -7163,18 +7178,18 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) const char *const fname = tv_get_string(&argvars[0]); if (os_isdir((const char_u *)fname)) { - EMSG2(_(e_isadir2), fname); + semsg(_(e_isadir2), fname); return; } if (*fname == NUL || (fd = os_fopen(fname, READBIN)) == NULL) { - EMSG2(_(e_notopen), *fname == NUL ? _("<empty>") : fname); + semsg(_(e_notopen), *fname == NUL ? _("<empty>") : fname); return; } if (blob) { tv_blob_alloc_ret(rettv); if (!read_blob(fd, rettv->vval.v_blob)) { - EMSG2(_(e_notread), fname); + semsg(_(e_notread), fname); // An empty blob is returned on error. tv_blob_free(rettv->vval.v_blob); rettv->vval.v_blob = NULL; @@ -7492,14 +7507,14 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type == VAR_DICT) { if (argvars[2].v_type != VAR_UNKNOWN) { - EMSG2(_(e_toomanyarg), "remove()"); + semsg(_(e_toomanyarg), "remove()"); } else if ((d = argvars[0].vval.v_dict) != NULL && !var_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE)) { const char *key = tv_get_string_chk(&argvars[1]); if (key != NULL) { di = tv_dict_find(d, key, -1); if (di == NULL) { - EMSG2(_(e_dictkey), key); + semsg(_(e_dictkey), key); } 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; @@ -7529,7 +7544,7 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) idx = len + idx; } if (idx < 0 || idx >= len) { - EMSGN(_(e_blobidx), idx); + semsg(_(e_blobidx), (int64_t)idx); return; } if (argvars[2].v_type == VAR_UNKNOWN) { @@ -7549,7 +7564,7 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) end = len + end; } if (end >= len || idx > end) { - EMSGN(_(e_blobidx), end); + semsg(_(e_blobidx), (int64_t)end); return; } blob_T *const blob = tv_blob_alloc(); @@ -7568,7 +7583,7 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } } else if (argvars[0].v_type != VAR_LIST) { - EMSG2(_(e_listdictblobarg), "remove()"); + semsg(_(e_listdictblobarg), "remove()"); } else if (!var_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), arg_errmsg, TV_TRANSLATE)) { bool error = false; @@ -7577,7 +7592,7 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (error) { // Type error: do nothing, errmsg already given. } else if ((item = tv_list_find(l, idx)) == NULL) { - EMSGN(_(e_listidx), idx); + semsg(_(e_listidx), (int64_t)idx); } else { if (argvars[2].v_type == VAR_UNKNOWN) { // Remove one item, return its value. @@ -7590,7 +7605,7 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (error) { // Type error: do nothing. } else if ((item2 = tv_list_find(l, end)) == NULL) { - EMSGN(_(e_listidx), end); + semsg(_(e_listidx), (int64_t)end); } else { int cnt = 0; @@ -7601,7 +7616,7 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } if (li == NULL) { // Didn't find "item2" after "item". - EMSG(_(e_invrange)); + emsg(_(e_invrange)); } else { tv_list_move_items(l, item, item2, tv_list_alloc_ret(rettv, cnt), cnt); @@ -7723,7 +7738,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (limit-- == 0) { xfree(p); xfree(remain); - EMSG(_("E655: Too many symbolic links (cycle?)")); + emsg(_("E655: Too many symbolic links (cycle?)")); rettv->vval.v_string = NULL; xfree(buf); return; @@ -7852,7 +7867,7 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr) } tv_blob_set_ret(rettv, b); } else if (argvars[0].v_type != VAR_LIST) { - EMSG2(_(e_listblobarg), "reverse()"); + semsg(_(e_listblobarg), "reverse()"); } else { list_T *const l = argvars[0].vval.v_list; if (!var_check_lock(tv_list_locked(l), N_("reverse() argument"), @@ -7919,7 +7934,7 @@ static int get_search_arg(typval_T *varp, int *flagsp) } } if (mask == 0) { - emsgf(_(e_invarg2), flags); + semsg(_(e_invarg2), flags); dir = 0; } else { *flagsp |= mask; @@ -7991,7 +8006,7 @@ 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), tv_get_string(&argvars[1])); + semsg(_(e_invarg2), tv_get_string(&argvars[1])); goto theend; } @@ -8044,12 +8059,12 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[0].v_type != VAR_NUMBER || argvars[0].vval.v_number < 0) { - EMSG2(_(e_invarg2), "Channel id must be a positive integer"); + semsg(_(e_invarg2), "Channel id must be a positive integer"); return; } if (argvars[1].v_type != VAR_STRING) { - EMSG2(_(e_invarg2), "Event type must be a string"); + semsg(_(e_invarg2), "Event type must be a string"); return; } @@ -8061,7 +8076,7 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (!rpc_send_event((uint64_t)argvars[0].vval.v_number, tv_get_string(&argvars[1]), args)) { - EMSG2(_(e_invarg2), "Channel doesn't exist"); + semsg(_(e_invarg2), "Channel doesn't exist"); return; } @@ -8080,12 +8095,12 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[0].v_type != VAR_NUMBER || argvars[0].vval.v_number <= 0) { - EMSG2(_(e_invarg2), "Channel id must be a positive integer"); + semsg(_(e_invarg2), "Channel id must be a positive integer"); return; } if (argvars[1].v_type != VAR_STRING) { - EMSG2(_(e_invarg2), "Method name must be a string"); + semsg(_(e_invarg2), "Method name must be a string"); return; } @@ -8147,10 +8162,10 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) } msg_ext_set_kind("rpc_error"); if (name) { - emsgf_multiline("Error invoking '%s' on channel %" PRIu64 " (%s):\n%s", + semsg_multiline("Error invoking '%s' on channel %" PRIu64 " (%s):\n%s", method, chan_id, name, err.msg); } else { - emsgf_multiline("Error invoking '%s' on channel %" PRIu64 ":\n%s", + semsg_multiline("Error invoking '%s' on channel %" PRIu64 ":\n%s", method, chan_id, err.msg); } @@ -8158,7 +8173,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (!object_to_vim(result, rettv, &err)) { - EMSG2(_("Error converting the call result: %s"), err.msg); + semsg(_("Error converting the call result: %s"), err.msg); } end: @@ -8179,7 +8194,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type != VAR_STRING || (argvars[1].v_type != VAR_LIST && argvars[1].v_type != VAR_UNKNOWN)) { // Wrong argument types - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -8192,7 +8207,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) int i = 0; TV_LIST_ITER_CONST(args, arg, { if (TV_LIST_ITEM_TV(arg)->v_type != VAR_STRING) { - emsgf(_("E5010: List item %d of the second argument is not a string"), + semsg(_("E5010: List item %d of the second argument is not a string"), i); return; } @@ -8201,7 +8216,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[0].vval.v_string == NULL || argvars[0].vval.v_string[0] == NUL) { - EMSG(_(e_api_spawn_failed)); + emsg(_(e_api_spawn_failed)); return; } @@ -8245,7 +8260,7 @@ static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type != VAR_NUMBER) { // Wrong argument types - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -8258,7 +8273,7 @@ static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = channel_close(argvars[0].vval.v_number, kChannelPartRpc, &error); if (!rettv->vval.v_number) { - EMSG(error); + emsg(error); } } } @@ -8445,7 +8460,7 @@ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) // 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), tv_get_string(&argvars[3])); + semsg(_(e_invarg2), tv_get_string(&argvars[3])); goto theend; } @@ -8464,19 +8479,19 @@ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) if (skip->v_type != VAR_FUNC && skip->v_type != VAR_PARTIAL && skip->v_type != VAR_STRING) { - emsgf(_(e_invarg2), tv_get_string(&argvars[4])); + semsg(_(e_invarg2), tv_get_string(&argvars[4])); goto theend; // Type error. } if (argvars[5].v_type != VAR_UNKNOWN) { lnum_stop = tv_get_number_chk(&argvars[5], NULL); if (lnum_stop < 0) { - emsgf(_(e_invarg2), tv_get_string(&argvars[5])); + semsg(_(e_invarg2), tv_get_string(&argvars[5])); goto theend; } if (argvars[6].v_type != VAR_UNKNOWN) { time_limit = tv_get_number_chk(&argvars[6], NULL); if (time_limit < 0) { - emsgf(_(e_invarg2), tv_get_string(&argvars[6])); + semsg(_(e_invarg2), tv_get_string(&argvars[6])); goto theend; } } @@ -8741,7 +8756,7 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) // 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)); + emsg(_(e_invarg)); return; } else { address = xstrdup(tv_get_string(argvars)); @@ -8754,7 +8769,7 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) xfree(address); if (result != 0) { - EMSG2("Failed to start server: %s", + semsg("Failed to start server: %s", result > 0 ? "Unknown system error" : uv_strerror(result)); return; } @@ -8780,7 +8795,7 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[0].v_type != VAR_STRING) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -8859,7 +8874,7 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) dictitem_T *di; if (argvars[0].v_type != VAR_DICT) { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); return; } @@ -8926,7 +8941,7 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } if (strlen(mode_str) != 9) { - EMSG2(_(e_invarg2), mode_str); + semsg(_(e_invarg2), mode_str); return; } @@ -8977,10 +8992,10 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) typval_T *list_arg = &args[0]; if (list_arg->v_type != VAR_LIST) { - EMSG(_(e_listreq)); + emsg(_(e_listreq)); return; } else if (recursive != 0) { - EMSG(_(e_au_recursive)); + emsg(_(e_au_recursive)); return; } @@ -8989,7 +9004,7 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) // Option argument was not given. goto skip_args; } else if (action_arg->v_type != VAR_STRING) { - EMSG(_(e_stringreq)); + emsg(_(e_stringreq)); return; } const char *const act = tv_get_string_chk(action_arg); @@ -8997,7 +9012,7 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) && act[1] == NUL) { action = *act; } else { - EMSG2(_(e_invact), act); + semsg(_(e_invact), act); return; } @@ -9014,7 +9029,7 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) } else if (what_arg->v_type == VAR_DICT && what_arg->vval.v_dict != NULL) { what = what_arg->vval.v_dict; } else { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); return; } @@ -9057,7 +9072,7 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = -1; if (argvars[0].v_type != VAR_LIST) { - EMSG(_(e_listreq)); + emsg(_(e_listreq)); return; } if (win == NULL) { @@ -9071,7 +9086,7 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) TV_LIST_ITER_CONST(l, li, { if (TV_LIST_ITEM_TV(li)->v_type != VAR_DICT || (d = TV_LIST_ITEM_TV(li)->vval.v_dict) == NULL) { - emsgf(_("E474: List item %d is either not a dictionary " + semsg(_("E474: List item %d is either not a dictionary " "or an empty one"), li_idx); return; } @@ -9080,7 +9095,7 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) || tv_dict_find(d, S_LEN("pos1")) != NULL) && tv_dict_find(d, S_LEN("priority")) != NULL && tv_dict_find(d, S_LEN("id")) != NULL)) { - emsgf(_("E474: List item %d is missing one of the required keys"), + semsg(_("E474: List item %d is missing one of the required keys"), li_idx); return; } @@ -9182,7 +9197,7 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = 0; } } else { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } } } @@ -9272,7 +9287,7 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) const int ret = get_yank_type((char_u **)&stropt, &yank_type, &block_len); if (ret == FAIL || *(++stropt) != NUL) { - EMSG2(_(e_invargval), "value"); + semsg(_(e_invargval), "value"); return; } } @@ -9293,7 +9308,7 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) bool set_unnamed = false; if (argvars[2].v_type != VAR_UNKNOWN) { if (yank_type != kMTUnknown) { - EMSG2(_(e_toomanyarg), "setreg"); + semsg(_(e_toomanyarg), "setreg"); return; } @@ -9433,7 +9448,7 @@ static void f_settagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr) // second argument: dict with items to set in the tag stack if (argvars[1].v_type != VAR_DICT) { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); return; } d = argvars[1].vval.v_dict; @@ -9455,11 +9470,11 @@ static void f_settagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr) && actstr[1] == NUL) { action = *actstr; } else { - EMSG2(_(e_invact2), actstr); + semsg(_(e_invact2), actstr); return; } } else { - EMSG(_(e_stringreq)); + emsg(_(e_stringreq)); return; } @@ -9542,7 +9557,7 @@ static void f_sign_define(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[1].v_type != VAR_UNKNOWN && argvars[1].v_type != VAR_DICT) { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); return; } @@ -9588,7 +9603,7 @@ static void f_sign_getplaced(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[1].v_type != VAR_UNKNOWN) { if (argvars[1].v_type != VAR_DICT || ((dict = argvars[1].vval.v_dict) == NULL)) { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); return; } if ((di = tv_dict_find(dict, "lnum", -1)) != NULL) { @@ -9639,7 +9654,7 @@ static void f_sign_jump(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } if (sign_id <= 0) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -9676,7 +9691,7 @@ static void f_sign_place(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[4].v_type != VAR_UNKNOWN && (argvars[4].v_type != VAR_DICT || ((dict = argvars[4].vval.v_dict) == NULL))) { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); return; } @@ -9692,7 +9707,7 @@ static void f_sign_placelist(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_list_alloc_ret(rettv, kListLenMayKnow); if (argvars[0].v_type != VAR_LIST) { - EMSG(_(e_listreq)); + emsg(_(e_listreq)); return; } @@ -9702,7 +9717,7 @@ static void f_sign_placelist(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (TV_LIST_ITEM_TV(li)->v_type == VAR_DICT) { sign_id = sign_place_from_dict(NULL, NULL, NULL, NULL, TV_LIST_ITEM_TV(li)->vval.v_dict); } else { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); } tv_list_append_number(rettv->vval.v_list, sign_id); }); @@ -9748,13 +9763,13 @@ static void f_sign_unplace(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = -1; if (argvars[0].v_type != VAR_STRING) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } if (argvars[1].v_type != VAR_UNKNOWN) { if (argvars[1].v_type != VAR_DICT) { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); return; } dict = argvars[1].vval.v_dict; @@ -9771,7 +9786,7 @@ static void f_sign_unplacelist(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_list_alloc_ret(rettv, kListLenMayKnow); if (argvars[0].v_type != VAR_LIST) { - EMSG(_(e_listreq)); + emsg(_(e_listreq)); return; } @@ -9780,7 +9795,7 @@ static void f_sign_unplacelist(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (TV_LIST_ITEM_TV(li)->v_type == VAR_DICT) { retval = sign_unplace_from_dict(NULL, TV_LIST_ITEM_TV(li)->vval.v_dict); } else { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); } tv_list_append_number(rettv->vval.v_list, retval); }); @@ -9801,12 +9816,12 @@ static void f_simplify(typval_T *argvars, typval_T *rettv, FunPtr fptr) 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)); + 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"); + semsg(_(e_invarg2), "expected dictionary"); return; } @@ -9819,7 +9834,7 @@ static void f_sockconnect(typval_T *argvars, typval_T *rettv, FunPtr fptr) } else if (strcmp(mode, "pipe") == 0) { tcp = false; } else { - EMSG2(_(e_invarg2), "invalid mode"); + semsg(_(e_invarg2), "invalid mode"); return; } @@ -9842,7 +9857,7 @@ static void f_sockconnect(typval_T *argvars, typval_T *rettv, FunPtr fptr) uint64_t id = channel_connect(tcp, address, rpc, on_data, 50, &error); if (error) { - EMSG2(_("connection failed: %s"), error); + semsg(_("connection failed: %s"), error); } rettv->vval.v_number = (varnumber_T)id; @@ -10051,7 +10066,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) : N_("uniq() argument")); if (argvars[0].v_type != VAR_LIST) { - EMSG2(_(e_listarg), sort ? "sort()" : "uniq()"); + semsg(_(e_listarg), sort ? "sort()" : "uniq()"); } else { list_T *const l = argvars[0].vval.v_list; if (var_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE)) { @@ -10091,7 +10106,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) } else if (argvars[1].v_type != VAR_NUMBER) { info.item_compare_func = tv_get_string(&argvars[1]); } else if (i != 0) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); goto theend; } if (info.item_compare_func != NULL) { @@ -10120,7 +10135,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) if (argvars[2].v_type != VAR_UNKNOWN) { // optional third argument: {dict} if (argvars[2].v_type != VAR_DICT) { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); goto theend; } info.item_compare_selfdict = argvars[2].vval.v_dict; @@ -10139,7 +10154,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) : item_compare2_not_keeping_zero), &info.item_compare_func_err); if (info.item_compare_func_err) { - EMSG(_("E702: Sort compare function failed")); + emsg(_("E702: Sort compare function failed")); } } else { ListSorter item_compare_func_ptr; @@ -10159,7 +10174,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) listitem_T *const prev_li = TV_LIST_ITEM_PREV(l, li); if (item_compare_func_ptr(&prev_li, &li) == 0) { if (info.item_compare_func_err) { // -V547 - EMSG(_("E882: Uniq compare function failed")); + emsg(_("E882: Uniq compare function failed")); break; } li = tv_list_item_remove(l, li); @@ -10187,7 +10202,7 @@ static void f_sort(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_stdioopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[0].v_type != VAR_DICT) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -10208,7 +10223,7 @@ static void f_stdioopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) const char *error; uint64_t id = channel_from_stdio(rpc, on_stdin, &error); if (!id) { - EMSG2(e_stdiochan2, error); + semsg(e_stdiochan2, error); } @@ -10261,7 +10276,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (*curwin->w_s->b_p_spl == NUL) { - EMSG(_(e_no_spell)); + emsg(_(e_no_spell)); curwin->w_p_spell = wo_spell_save; return; } @@ -10323,7 +10338,7 @@ static void f_spellsuggest(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (*curwin->w_s->b_p_spl == NUL) { - EMSG(_(e_no_spell)); + emsg(_(e_no_spell)); curwin->w_p_spell = wo_spell_save; return; } @@ -10425,7 +10440,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) col = 0; } else { // Don't get stuck at the same match. - col = (*mb_ptr2len)(regmatch.endp[0]); + col = utfc_ptr2len(regmatch.endp[0]); } str = (const char *)regmatch.endp[0]; } @@ -10459,7 +10474,7 @@ static void f_stdpath(typval_T *argvars, typval_T *rettv, FunPtr fptr) } else if (strequal(p, "data_dirs")) { get_xdg_var_list(kXDGDataDirs, rettv); } else { - EMSG2(_("E6100: \"%s\" is not a valid stdpath"), p); + semsg(_("E6100: \"%s\" is not a valid stdpath"), p); } } @@ -10502,7 +10517,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[1].v_type != VAR_UNKNOWN) { base = tv_get_number(&argvars[1]); if (base != 2 && base != 8 && base != 10 && base != 16) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } if (argvars[2].v_type != VAR_UNKNOWN && tv_get_number(&argvars[2])) { @@ -10613,7 +10628,7 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) break; } charidx--; - byteidx += MB_CPTR2LEN((const char_u *)str + byteidx); + byteidx += utf_ptr2len((const char_u *)str + byteidx); } } @@ -10682,7 +10697,7 @@ static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr) skipcc = tv_get_number_chk(&argvars[1], NULL); } if (skipcc < 0 || skipcc > 1) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } else { func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv; while (*s != NUL) { @@ -10730,7 +10745,7 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (!error) { if (nchar > 0) { while (nchar > 0 && (size_t)nbyte < slen) { - nbyte += MB_CPTR2LEN((const char_u *)p + nbyte); + nbyte += utf_ptr2len((const char_u *)p + nbyte); nchar--; } } else { @@ -10746,7 +10761,7 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (off < 0) { len += 1; } else { - len += (size_t)MB_CPTR2LEN((const char_u *)p + off); + len += utf_ptr2len((const char_u *)p + off); } charlen--; } @@ -10918,7 +10933,7 @@ static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (no < 0 || no >= NSUBEXP) { - emsgf(_("E935: invalid submatch number: %d"), no); + semsg(_("E935: invalid submatch number: %d"), no); return; } int retList = 0; @@ -11220,7 +11235,7 @@ static void f_tabpagenr(typval_T *argvars, typval_T *rettv, FunPtr fptr) ? tabpage_index(lastused_tabpage) : nr; } else { - EMSG2(_(e_invexpr2), arg); + semsg(_(e_invexpr2), arg); } } } else { @@ -11230,7 +11245,6 @@ static void f_tabpagenr(typval_T *argvars, typval_T *rettv, FunPtr fptr) } - /* * Common code for tabpagewinnr() and winnr(). */ @@ -11279,7 +11293,7 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar) } if (invalid_arg) { - EMSG2(_(e_invexpr2), arg); + semsg(_(e_invexpr2), arg); nr = 0; } } @@ -11371,7 +11385,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (curbuf->b_changed) { - EMSG(_("Can only call this function in an unmodified buffer")); + emsg(_("Can only call this function in an unmodified buffer")); return; } @@ -11385,7 +11399,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[1].v_type != VAR_DICT && argvars[1].v_type != VAR_UNKNOWN) { // Wrong argument type - EMSG2(_(e_invarg2), "expected dictionary"); + semsg(_(e_invarg2), "expected dictionary"); shell_free_argv(argv); return; } @@ -11408,7 +11422,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) cwd = new_cwd; // The new cwd must be a directory. if (!os_isdir_executable(cwd)) { - EMSG2(_(e_invarg2), "expected valid directory"); + semsg(_(e_invarg2), "expected valid directory"); shell_free_argv(argv); return; } @@ -11416,7 +11430,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) job_env = tv_dict_find(job_opts, S_LEN("env")); if (job_env && job_env->di_tv.v_type != VAR_DICT) { - EMSG2(_(e_invarg2), "env"); + semsg(_(e_invarg2), "env"); shell_free_argv(argv); return; } @@ -11499,7 +11513,7 @@ static void f_timer_info(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[0].v_type != VAR_UNKNOWN) { if (argvars[0].v_type != VAR_NUMBER) { - EMSG(_(e_number_exp)); + emsg(_(e_number_exp)); return; } tv_list_alloc_ret(rettv, 1); @@ -11516,7 +11530,7 @@ static void f_timer_info(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_timer_pause(typval_T *argvars, typval_T *unused, FunPtr fptr) { if (argvars[0].v_type != VAR_NUMBER) { - EMSG(_(e_number_exp)); + emsg(_(e_number_exp)); return; } int paused = (bool)tv_get_number(&argvars[1]); @@ -11543,7 +11557,7 @@ 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), tv_get_string(&argvars[2])); + semsg(_(e_invarg2), tv_get_string(&argvars[2])); return; } dictitem_T *const di = tv_dict_find(dict, S_LEN("repeat")); @@ -11568,7 +11582,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_timer_stop(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[0].v_type != VAR_NUMBER) { - EMSG(_(e_number_exp)); + emsg(_(e_number_exp)); return; } @@ -11682,7 +11696,7 @@ static void f_tr(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_string = ga.ga_data; return; error: - EMSG2(_(e_invarg2), fromstr); + semsg(_(e_invarg2), fromstr); ga_clear(&ga); return; } @@ -11716,7 +11730,7 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } if (dir < 0 || dir > 2) { - emsgf(_(e_invarg2), tv_get_string(&argvars[2])); + semsg(_(e_invarg2), tv_get_string(&argvars[2])); return; } } @@ -11725,14 +11739,14 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (dir == 0 || dir == 1) { // Trim leading characters while (*head != NUL) { - c1 = PTR2CHAR(head); + c1 = utf_ptr2char(head); if (mask == NULL) { if (c1 > ' ' && c1 != 0xa0) { break; } } else { for (p = mask; *p != NUL; MB_PTR_ADV(p)) { - if (c1 == PTR2CHAR(p)) { + if (c1 == utf_ptr2char(p)) { break; } } @@ -11750,14 +11764,14 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr) for (; tail > head; tail = prev) { prev = tail; MB_PTR_BACK(head, prev); - c1 = PTR2CHAR(prev); + c1 = utf_ptr2char(prev); if (mask == NULL) { if (c1 > ' ' && c1 != 0xa0) { break; } } else { for (p = mask; *p != NUL; MB_PTR_ADV(p)) { - if (c1 == PTR2CHAR(p)) { + if (c1 == utf_ptr2char(p)) { break; } } @@ -12076,7 +12090,7 @@ static void f_winrestview(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type != VAR_DICT || (dict = argvars[0].vval.v_dict) == NULL) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } else { dictitem_T *di; if ((di = tv_dict_find(dict, S_LEN("lnum"))) != NULL) { @@ -12183,7 +12197,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr) } }); } else if (argvars[0].v_type != VAR_BLOB) { - EMSG2(_(e_invarg2), + semsg(_(e_invarg2), _("writefile() first argument must be a List or a Blob")); return; } @@ -12208,7 +12222,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr) do_fsync = false; break; default: // Using %s, p and not %c, *p to preserve multibyte characters - emsgf(_("E5060: Unknown flag: %s"), p); + semsg(_("E5060: Unknown flag: %s"), p); return; } } @@ -12222,11 +12236,11 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr) FileDescriptor fp; int error; if (*fname == NUL) { - EMSG(_("E482: Can't open file with an empty name")); + 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"), + semsg(_("E482: Can't open file %s for writing: %s"), fname, os_strerror(error)); } else { bool write_ok; @@ -12239,7 +12253,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = 0; } if ((error = file_close(&fp, do_fsync)) != 0) { - emsgf(_("E80: Error when closing file %s: %s"), + semsg(_("E80: Error when closing file %s: %s"), fname, os_strerror(error)); } } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 6300ce6150..3e37e8cbb6 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -63,7 +63,7 @@ void list_write_log(const char *const fname) FileDescriptor fp; const int fo_ret = file_open(&fp, fname, kFileCreate|kFileAppend, 0600); if (fo_ret != 0) { - emsgf(_("E5142: Failed to open file %s: %s"), fname, os_strerror(fo_ret)); + semsg(_("E5142: Failed to open file %s: %s"), fname, os_strerror(fo_ret)); return; } for (ListLog *chunk = list_log_first; chunk != NULL;) { @@ -85,7 +85,7 @@ void list_write_log(const char *const fname) sizeof(chunk->entries[0]) * (chunk->size - i)); chunk->size -= i; } - emsgf(_("E5143: Failed to write to file %s: %s"), + semsg(_("E5143: Failed to write to file %s: %s"), fname, os_strerror((int)fw_ret)); return; } @@ -96,7 +96,7 @@ void list_write_log(const char *const fname) } const int fc_ret = file_close(&fp, true); if (fc_ret != 0) { - emsgf(_("E5144: Failed to close file %s: %s"), fname, os_strerror(fc_ret)); + semsg(_("E5144: Failed to close file %s: %s"), fname, os_strerror(fc_ret)); } } @@ -1041,7 +1041,7 @@ const char *tv_list_find_str(list_T *const l, const int n) { const listitem_T *const li = tv_list_find(l, n); if (li == NULL) { - EMSG2(_(e_listidx), (int64_t)n); + semsg(_(e_listidx), (int64_t)n); return NULL; } return tv_get_string(TV_LIST_ITEM_TV(li)); @@ -1399,7 +1399,7 @@ void tv_dict_item_remove(dict_T *const dict, dictitem_T *const item) { hashitem_T *const hi = hash_find(&dict->dv_hashtab, item->di_key); if (HASHITEM_EMPTY(hi)) { - emsgf(_(e_intern2), "tv_dict_item_remove()"); + semsg(_(e_intern2), "tv_dict_item_remove()"); } else { hash_remove(&dict->dv_hashtab, hi); } @@ -1687,7 +1687,7 @@ bool tv_dict_get_callback(dict_T *const d, const char *const key, const ptrdiff_ } if (!tv_is_func(di->di_tv) && di->di_tv.v_type != VAR_STRING) { - EMSG(_("E6000: Argument is not a function or function name")); + emsg(_("E6000: Argument is not a function or function name")); return false; } @@ -1961,7 +1961,7 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action NULL); } } else if (*action == 'e') { - emsgf(_("E737: Key already exists: %s"), di2->di_key); + semsg(_("E737: Key already exists: %s"), di2->di_key); break; } else if (*action == 'f' && di2 != di1) { typval_T oldtv; @@ -2599,7 +2599,7 @@ void tv_copy(const typval_T *const from, typval_T *const to) } break; case VAR_UNKNOWN: - emsgf(_(e_intern2), "tv_copy(UNKNOWN)"); + semsg(_(e_intern2), "tv_copy(UNKNOWN)"); break; } } @@ -2620,7 +2620,7 @@ void tv_item_lock(typval_T *const tv, const int deep, const bool lock, const boo static int recurse = 0; if (recurse >= DICT_MAXNEST) { - EMSG(_("E743: variable nested too deep for (un)lock")); + emsg(_("E743: variable nested too deep for (un)lock")); return; } if (deep == 0) { @@ -2778,7 +2778,7 @@ bool var_check_lock(VarLockStatus lock, const char *name, size_t name_len) name_len = strlen(name); } - emsgf(_(error_message), (int)name_len, name); + semsg(_(error_message), (int)name_len, name); return true; } @@ -2896,29 +2896,29 @@ bool tv_check_str_or_nr(const typval_T *const tv) case VAR_STRING: return true; case VAR_FLOAT: - EMSG(_("E805: Expected a Number or a String, Float found")); + emsg(_("E805: Expected a Number or a String, Float found")); return false; case VAR_PARTIAL: case VAR_FUNC: - EMSG(_("E703: Expected a Number or a String, Funcref found")); + emsg(_("E703: Expected a Number or a String, Funcref found")); return false; case VAR_LIST: - EMSG(_("E745: Expected a Number or a String, List found")); + emsg(_("E745: Expected a Number or a String, List found")); return false; case VAR_DICT: - EMSG(_("E728: Expected a Number or a String, Dictionary found")); + emsg(_("E728: Expected a Number or a String, Dictionary found")); return false; case VAR_BLOB: - EMSG(_("E974: Expected a Number or a String, Blob found")); + emsg(_("E974: Expected a Number or a String, Blob found")); return false; case VAR_BOOL: - EMSG(_("E5299: Expected a Number or a String, Boolean found")); + emsg(_("E5299: Expected a Number or a String, Boolean found")); return false; case VAR_SPECIAL: - EMSG(_("E5300: Expected a Number or a String")); + emsg(_("E5300: Expected a Number or a String")); return false; case VAR_UNKNOWN: - EMSG2(_(e_intern2), "tv_check_str_or_nr(UNKNOWN)"); + semsg(_(e_intern2), "tv_check_str_or_nr(UNKNOWN)"); return false; } abort(); @@ -2963,7 +2963,7 @@ bool tv_check_num(const typval_T *const tv) case VAR_FLOAT: case VAR_BLOB: case VAR_UNKNOWN: - EMSG(_(num_errors[tv->v_type])); + emsg(_(num_errors[tv->v_type])); return false; } abort(); @@ -3008,7 +3008,7 @@ bool tv_check_str(const typval_T *const tv) case VAR_FLOAT: case VAR_BLOB: case VAR_UNKNOWN: - EMSG(_(str_errors[tv->v_type])); + emsg(_(str_errors[tv->v_type])); return false; } abort(); @@ -3055,7 +3055,7 @@ varnumber_T tv_get_number_chk(const typval_T *const tv, bool *const ret_error) case VAR_DICT: case VAR_BLOB: case VAR_FLOAT: - EMSG(_(num_errors[tv->v_type])); + emsg(_(num_errors[tv->v_type])); break; case VAR_NUMBER: return tv->vval.v_number; @@ -3072,7 +3072,7 @@ varnumber_T tv_get_number_chk(const typval_T *const tv, bool *const ret_error) case VAR_SPECIAL: return 0; case VAR_UNKNOWN: - emsgf(_(e_intern2), "tv_get_number(UNKNOWN)"); + semsg(_(e_intern2), "tv_get_number(UNKNOWN)"); break; } if (ret_error != NULL) { @@ -3119,41 +3119,53 @@ float_T tv_get_float(const typval_T *const tv) return tv->vval.v_float; case VAR_PARTIAL: case VAR_FUNC: - EMSG(_("E891: Using a Funcref as a Float")); + emsg(_("E891: Using a Funcref as a Float")); break; case VAR_STRING: - EMSG(_("E892: Using a String as a Float")); + emsg(_("E892: Using a String as a Float")); break; case VAR_LIST: - EMSG(_("E893: Using a List as a Float")); + emsg(_("E893: Using a List as a Float")); break; case VAR_DICT: - EMSG(_("E894: Using a Dictionary as a Float")); + emsg(_("E894: Using a Dictionary as a Float")); break; case VAR_BOOL: - EMSG(_("E362: Using a boolean value as a Float")); + emsg(_("E362: Using a boolean value as a Float")); break; case VAR_SPECIAL: - EMSG(_("E907: Using a special value as a Float")); + emsg(_("E907: Using a special value as a Float")); break; case VAR_BLOB: - EMSG(_("E975: Using a Blob as a Float")); + emsg(_("E975: Using a Blob as a Float")); break; case VAR_UNKNOWN: - emsgf(_(e_intern2), "tv_get_float(UNKNOWN)"); + semsg(_(e_intern2), "tv_get_float(UNKNOWN)"); break; } return 0; } -// Give an error and return FAIL unless "tv" is a non-empty string. +// Give an error and return FAIL unless "tv" is a string. int tv_check_for_string(const typval_T *const tv) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE { - if (tv->v_type != VAR_STRING - || tv->vval.v_string == NULL - || *tv->vval.v_string == NUL) { - EMSG(_(e_stringreq)); + if (tv->v_type != VAR_STRING) { + emsg(_(e_stringreq)); + return FAIL; + } + return OK; +} + +// Give an error and return FAIL unless "tv" is a non-empty string. +int tv_check_for_nonempty_string(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (tv_check_for_string(tv) == FAIL) { + return FAIL; + } + if (tv->vval.v_string == NULL || *tv->vval.v_string == NUL) { + emsg(_(e_non_empty_string_required)); return FAIL; } return OK; @@ -3195,7 +3207,7 @@ const char *tv_get_string_buf_chk(const typval_T *const tv, char *const buf) case VAR_FLOAT: case VAR_BLOB: case VAR_UNKNOWN: - EMSG(_(str_errors[tv->v_type])); + emsg(_(str_errors[tv->v_type])); return false; } return NULL; diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index a28feffd0b..69732f1a7d 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -30,7 +30,7 @@ typedef uint64_t uvarnumber_T; typedef double float_T; /// Refcount for dict or list that should not be freed -enum { DO_NOT_FREE_CNT = (INT_MAX / 2) }; +enum { DO_NOT_FREE_CNT = (INT_MAX / 2), }; /// Additional values for tv_list_alloc() len argument enum ListLenSpecials { @@ -831,7 +831,7 @@ extern bool tv_in_free_unref_items; /// @param li Name of the variable with current listitem_T entry. /// @param code Cycle body. #define TV_LIST_ITER(l, li, code) \ - _TV_LIST_ITER_MOD(, l, li, code) + _TV_LIST_ITER_MOD( , l, li, code) /// Iterate over a list /// @@ -893,7 +893,7 @@ static inline bool tv_get_float_chk(const typval_T *const tv, REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT; // FIXME circular dependency, cannot import message.h. -bool emsgf(const char *const fmt, ...); +bool semsg(const char *const fmt, ...); /// Get the float value /// @@ -913,7 +913,7 @@ static inline bool tv_get_float_chk(const typval_T *const tv, float_T *const ret *ret_f = (float_T)tv->vval.v_number; return true; } - emsgf("%s", _("E808: Number or Float required")); + semsg("%s", _("E808: Number or Float required")); return false; } diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index f4393a79dc..6fe75e5e1f 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -103,7 +103,7 @@ static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, i || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0) || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0)) { if (!skip) { - EMSG2(_("E125: Illegal argument: %s"), arg); + semsg(_("E125: Illegal argument: %s"), arg); } break; } @@ -116,7 +116,7 @@ static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, i // 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); + semsg(_("E853: Duplicate argument name: %s"), arg); xfree(arg); goto err_ret; } @@ -151,7 +151,7 @@ static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, i mustend = true; } } else if (any_default) { - EMSG(_("E989: Non-default argument follows default argument")); + emsg(_("E989: Non-default argument follows default argument")); mustend = true; } if (*p == ',') { @@ -163,7 +163,7 @@ static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, i p = skipwhite(p); if (mustend && *p != endchar) { if (!skip) { - EMSG2(_(e_invarg2), *argp); + semsg(_(e_invarg2), *argp); } break; } @@ -395,7 +395,7 @@ void emsg_funcname(char *ermsg, const char_u *name) p = (char_u *)name; } - EMSG2(_(ermsg), p); + semsg(_(ermsg), p); if (p != name) { xfree(p); @@ -829,7 +829,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett // If depth of calling is getting too high, don't execute the function if (depth >= p_mfd) { - EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'")); + emsg(_("E132: Function call depth is higher than 'maxfuncdepth'")); rettv->v_type = VAR_NUMBER; rettv->vval.v_number = -1; return; @@ -1244,7 +1244,7 @@ void save_funccal(funccal_entry_T *entry) void restore_funccal(void) { if (funccal_stack == NULL) { - IEMSG("INTERNAL: restore_funccal()"); + iemsg("INTERNAL: restore_funccal()"); } else { current_funccal = funccal_stack->top_funccal; funccal_stack = funccal_stack->next; @@ -1360,7 +1360,7 @@ int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict TV_LIST_ITER(args->vval.v_list, item, { if (argc == MAX_FUNC_ARGS - (partial == NULL ? 0 : partial->pt_argc)) { - EMSG(_("E699: Too many arguments")); + emsg(_("E699: Too many arguments")); goto func_call_skip_call; } // Make a copy of each argument. This is needed to be able to set @@ -1635,11 +1635,11 @@ static void list_func_head(ufunc_T *fp, int indent, bool force) { msg_start(); if (indent) { - MSG_PUTS(" "); + msg_puts(" "); } - MSG_PUTS(force ? "function! " : "function "); + msg_puts(force ? "function! " : "function "); if (fp->uf_name[0] == K_SPECIAL) { - MSG_PUTS_ATTR("<SNR>", HL_ATTR(HLF_8)); + msg_puts_attr("<SNR>", HL_ATTR(HLF_8)); msg_puts((const char *)fp->uf_name + 3); } else { msg_puts((const char *)fp->uf_name); @@ -1720,8 +1720,8 @@ char_u *trans_function_name(char_u **pp, bool skip, int flags, funcdict_T *fdp, 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". */ + // 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((const char *)start); if (lead > 2) { start += lead; @@ -1732,7 +1732,7 @@ char_u *trans_function_name(char_u **pp, bool skip, int flags, funcdict_T *fdp, lead > 2 ? 0 : FNE_CHECK_START); if (end == start) { if (!skip) { - EMSG(_("E129: Function name required")); + emsg(_("E129: Function name required")); } goto theend; } @@ -1744,7 +1744,7 @@ char_u *trans_function_name(char_u **pp, bool skip, int flags, funcdict_T *fdp, */ if (!aborting()) { if (end != NULL) { - emsgf(_(e_invarg2), start); + semsg(_(e_invarg2), start); } } else { *pp = (char_u *)find_name_end(start, NULL, NULL, FNE_INCL_BR); @@ -1767,7 +1767,7 @@ char_u *trans_function_name(char_u **pp, bool skip, int flags, funcdict_T *fdp, if (is_luafunc(lv.ll_tv->vval.v_partial) && *end == '.') { len = check_luafunc_name((const char *)end+1, true); if (len == 0) { - EMSG2(e_invexpr2, "v:lua"); + semsg(e_invexpr2, "v:lua"); goto theend; } name = xmallocz(len); @@ -1784,7 +1784,7 @@ char_u *trans_function_name(char_u **pp, bool skip, int flags, funcdict_T *fdp, if (!skip && !(flags & TFN_QUIET) && (fdp == NULL || lv.ll_dict == NULL || fdp->fd_newkey == NULL)) { - EMSG(_(e_funcref)); + emsg(_(e_funcref)); } else { *pp = (char_u *)end; } @@ -1862,7 +1862,7 @@ char_u *trans_function_name(char_u **pp, bool skip, int flags, funcdict_T *fdp, || eval_fname_sid((const char *)(*pp))) { // It's "s:" or "<SID>". if (current_sctx.sc_sid <= 0) { - EMSG(_(e_usingsid)); + emsg(_(e_usingsid)); goto theend; } sid_buf_len = snprintf(sid_buf, sizeof(sid_buf), @@ -1871,7 +1871,7 @@ char_u *trans_function_name(char_u **pp, bool skip, int flags, funcdict_T *fdp, } } 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"), + semsg(_("E128: Function name must start with a capital or \"s:\": %s"), start); goto theend; } @@ -1880,7 +1880,7 @@ char_u *trans_function_name(char_u **pp, bool skip, int flags, funcdict_T *fdp, 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); + semsg(_("E884: Function name cannot contain a colon: %s"), start); goto theend; } } @@ -2025,7 +2025,7 @@ void ex_function(exarg_T *eap) */ if (!aborting()) { if (fudi.fd_newkey != NULL) { - EMSG2(_(e_dictkey), fudi.fd_newkey); + semsg(_(e_dictkey), fudi.fd_newkey); } xfree(fudi.fd_newkey); return; @@ -2047,7 +2047,7 @@ void ex_function(exarg_T *eap) // if (!paren) { if (!ends_excmd(*skipwhite(p))) { - EMSG(_(e_trailing)); + emsg(_(e_trailing)); goto ret_free; } eap->nextcmd = check_nextcmd(p); @@ -2093,7 +2093,7 @@ void ex_function(exarg_T *eap) p = skipwhite(p); if (*p != '(') { if (!eap->skip) { - EMSG2(_("E124: Missing '(': %s"), eap->arg); + semsg(_("E124: Missing '(': %s"), eap->arg); goto ret_free; } // attempt to continue by skipping some text @@ -2126,7 +2126,7 @@ void ex_function(exarg_T *eap) } // Disallow using the g: dict. if (fudi.fd_dict != NULL && fudi.fd_dict->dv_scope == VAR_DEF_SCOPE) { - EMSG(_("E862: Cannot use g: here")); + emsg(_("E862: Cannot use g: here")); } } @@ -2171,7 +2171,7 @@ void ex_function(exarg_T *eap) if (*p == '\n') { line_arg = p + 1; } else if (*p != NUL && *p != '"' && !eap->skip && !did_emsg) { - EMSG(_(e_trailing)); + emsg(_(e_trailing)); } /* @@ -2183,7 +2183,7 @@ void ex_function(exarg_T *eap) // need to skip the body to be able to find what follows. if (!eap->skip && !eap->forceit) { if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL) { - EMSG(_(e_funcdict)); + emsg(_(e_funcdict)); } else if (name != NULL && find_func(name) != NULL) { emsg_funcname(e_funcexts, name); } @@ -2234,7 +2234,7 @@ void ex_function(exarg_T *eap) lines_left = Rows - 1; } if (theline == NULL) { - EMSG(_("E126: Missing :endfunction")); + emsg(_("E126: Missing :endfunction")); goto erret; } if (show_block) { @@ -2349,7 +2349,7 @@ void ex_function(exarg_T *eap) // heredoc: Check for ":python <<EOF", ":lua <<EOF", etc. arg = skipwhite(skiptowhite(p)); - if (arg[0] == '<' && arg[1] =='<' + if (arg[0] == '<' && arg[1] == '<' && ((p[0] == 'p' && p[1] == 'y' && (!ASCII_ISALNUM(p[2]) || p[2] == 't' || ((p[2] == '3' || p[2] == 'x') @@ -2383,7 +2383,7 @@ void ex_function(exarg_T *eap) arg = skipwhite(skiptowhite(arg)); if (arg[0] == '=' && arg[1] == '<' - && arg[2] =='<' + && arg[2] == '<' && (p[0] == 'l' && p[1] == 'e' && (!ASCII_ISALNUM(p[2]) @@ -2405,14 +2405,14 @@ void ex_function(exarg_T *eap) // Add the line to the function. ga_grow(&newlines, 1 + sourcing_lnum_off); - /* Copy the line to newly allocated memory. get_one_sourceline() - * allocates 250 bytes per line, this saves 80% on average. The cost - * is an extra alloc/free. */ + // Copy the line to newly allocated memory. get_one_sourceline() + // allocates 250 bytes per line, this saves 80% on average. The cost + // is an extra alloc/free. p = vim_strsave(theline); ((char_u **)(newlines.ga_data))[newlines.ga_len++] = p; - /* Add NULL lines for continuation lines, so that the line count is - * equal to the index in the growarray. */ + // Add NULL lines for continuation lines, so that the line count is + // equal to the index in the growarray. while (sourcing_lnum_off-- > 0) { ((char_u **)(newlines.ga_data))[newlines.ga_len++] = NULL; } @@ -2475,7 +2475,7 @@ void ex_function(exarg_T *eap) fp = NULL; if (fudi.fd_newkey == NULL && !eap->forceit) { - EMSG(_(e_funcdict)); + emsg(_(e_funcdict)); goto erret; } if (fudi.fd_di == NULL) { @@ -2490,8 +2490,8 @@ void ex_function(exarg_T *eap) goto erret; } - /* Give the function a sequential number. Can only be used with a - * Funcref! */ + // Give the function a sequential number. Can only be used with a + // Funcref! xfree(name); sprintf(numbuf, "%d", ++func_nr); name = vim_strsave((char_u *)numbuf); @@ -2516,7 +2516,7 @@ void ex_function(exarg_T *eap) xfree(scriptname); } if (j == FAIL) { - EMSG2(_("E746: Function name does not match script file name: %s"), + semsg(_("E746: Function name does not match script file name: %s"), name); goto erret; } @@ -2709,13 +2709,13 @@ void ex_delfunction(exarg_T *eap) xfree(fudi.fd_newkey); if (name == NULL) { if (fudi.fd_dict != NULL && !eap->skip) { - EMSG(_(e_funcref)); + emsg(_(e_funcref)); } return; } if (!ends_excmd(*skipwhite(p))) { xfree(name); - EMSG(_(e_trailing)); + emsg(_(e_trailing)); return; } eap->nextcmd = check_nextcmd(p); @@ -2731,18 +2731,18 @@ void ex_delfunction(exarg_T *eap) if (!eap->skip) { if (fp == NULL) { if (!eap->forceit) { - EMSG2(_(e_nofunc), eap->arg); + semsg(_(e_nofunc), eap->arg); } return; } if (fp->uf_calls > 0) { - EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg); + semsg(_("E131: Cannot delete function %s: It is in use"), eap->arg); return; } // check `uf_refcount > 2` because deleting a function should also reduce // the reference count, and 1 is the initial refcount. if (fp->uf_refcount > 2) { - EMSG2(_("Cannot delete function %s: It is being used internally"), + semsg(_("Cannot delete function %s: It is being used internally"), eap->arg); return; } @@ -2878,7 +2878,7 @@ void ex_return(exarg_T *eap) int returning = FALSE; if (current_funccal == NULL) { - EMSG(_("E133: :return not inside a function")); + emsg(_("E133: :return not inside a function")); return; } @@ -2953,7 +2953,7 @@ void ex_call(exarg_T *eap) tofree = trans_function_name(&arg, false, TFN_INT, &fudi, &partial); if (fudi.fd_newkey != NULL) { // Still need to give an error message for missing key. - EMSG2(_(e_dictkey), fudi.fd_newkey); + semsg(_(e_dictkey), fudi.fd_newkey); xfree(fudi.fd_newkey); } if (tofree == NULL) { @@ -2979,7 +2979,7 @@ void ex_call(exarg_T *eap) rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this. if (*startarg != '(') { - EMSG2(_(e_missingparen), eap->arg); + semsg(_(e_missingparen), eap->arg); goto end; } @@ -2989,7 +2989,7 @@ void ex_call(exarg_T *eap) if (lnum > curbuf->b_ml.ml_line_count) { // If the function deleted lines or switched to another buffer // the line number may become invalid. - EMSG(_(e_invrange)); + emsg(_(e_invrange)); break; } curwin->w_cursor.lnum = lnum; @@ -3038,7 +3038,7 @@ void ex_call(exarg_T *eap) if (!ends_excmd(*arg)) { if (!failed) { emsg_severe = true; - EMSG(_(e_trailing)); + emsg(_(e_trailing)); } } else { eap->nextcmd = check_nextcmd(arg); @@ -3079,13 +3079,13 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) cstack->cs_pending[idx] = CSTP_RETURN; if (!is_cmd && !reanimate) { - /* A pending return again gets pending. "rettv" points to an - * allocated variable with the rettv of the original ":return"'s - * argument if present or is NULL else. */ + // A pending return again gets pending. "rettv" points to an + // allocated variable with the rettv of the original ":return"'s + // argument if present or is NULL else. cstack->cs_rettv[idx] = rettv; } else { - /* When undoing a return in order to make it pending, get the stored - * return rettv. */ + // When undoing a return in order to make it pending, get the stored + // return rettv. if (reanimate) { assert(current_funccal->rettv); rettv = current_funccal->rettv; @@ -3214,8 +3214,8 @@ int func_has_ended(void *cookie) { funccall_T *fcp = (funccall_T *)cookie; - /* Ignore the "abort" flag if the abortion behavior has been changed due to - * an error inside a try conditional. */ + // Ignore the "abort" flag if the abortion behavior has been changed due to + // an error inside a try conditional. return ((fcp->func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try()) || fcp->returned; } diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h index 2b22cd95dc..c20feb2c7a 100644 --- a/src/nvim/event/process.h +++ b/src/nvim/event/process.h @@ -8,7 +8,7 @@ typedef enum { kProcessTypeUv, - kProcessTypePty + kProcessTypePty, } ProcessType; typedef struct process Process; diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 4a23f284cc..145fe33284 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -14,8 +14,8 @@ #include <string.h> #include "nvim/api/buffer.h" +#include "nvim/api/extmark.h" #include "nvim/api/private/defs.h" -#include "nvim/api/vim.h" #include "nvim/ascii.h" #include "nvim/buffer.h" #include "nvim/buffer_updates.h" @@ -120,7 +120,7 @@ void do_ascii(const exarg_T *const eap) int cc[MAX_MCO]; int c = utfc_ptr2char(get_cursor_pos_ptr(), cc); if (c == NUL) { - MSG("NUL"); + msg("NUL"); return; } @@ -222,7 +222,7 @@ void do_ascii(const exarg_T *const eap) xstrlcpy((char *)IObuff + iobuff_len, " ...", sizeof(IObuff) - iobuff_len); } - msg(IObuff); + msg((char *)IObuff); } /* @@ -303,8 +303,9 @@ void ex_align(exarg_T *eap) * Now try to move the line as much as possible to * the right. Stop when it moves too far. */ - do + do{ (void)set_indent(++new_indent, 0); + } while (linelen(NULL) <= width); --new_indent; break; @@ -522,14 +523,14 @@ void ex_sort(exarg_T *eap) } else if (!ASCII_ISALPHA(*p) && regmatch.regprog == NULL) { s = skip_regexp(p + 1, *p, true, NULL); if (*s != *p) { - EMSG(_(e_invalpat)); + emsg(_(e_invalpat)); goto sortend; } *s = NUL; // Use last search pattern if sort pattern is empty. if (s == p + 1) { if (last_search_pat() == NULL) { - EMSG(_(e_noprevre)); + emsg(_(e_noprevre)); goto sortend; } regmatch.regprog = vim_regcomp(last_search_pat(), RE_MAGIC); @@ -542,14 +543,14 @@ void ex_sort(exarg_T *eap) p = s; // continue after the regexp regmatch.rm_ic = p_ic; } else { - EMSG2(_(e_invarg2), p); + semsg(_(e_invarg2), p); goto sortend; } } // Can only have one of 'n', 'b', 'o' and 'x'. if (format_found > 1) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); goto sortend; } @@ -719,7 +720,7 @@ sortend: xfree(sortbuf2); vim_regfree(regmatch.regprog); if (got_int) { - EMSG(_(e_interr)); + emsg(_(e_interr)); } } @@ -855,7 +856,7 @@ void ex_retab(exarg_T *eap) line_breakcheck(); } if (got_int) { - EMSG(_(e_interr)); + emsg(_(e_interr)); } // If a single value was given then it can be considered equal to @@ -913,7 +914,7 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) linenr_T last_line; // Last line in file after adding new text if (dest >= line1 && dest < line2) { - EMSG(_("E134: Cannot move a range of lines into itself")); + emsg(_("E134: Cannot move a range of lines into itself")); return FAIL; } @@ -1014,11 +1015,7 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) ml_delete(line1 + extra, true); } if (!global_busy && num_lines > p_report) { - if (num_lines == 1) { - MSG(_("1 line moved")); - } else { - smsg(_("%" PRId64 " lines moved"), (int64_t)num_lines); - } + smsg(NGETTEXT("1 line moved", "%" PRId64 " lines moved", num_lines), (int64_t)num_lines); } extmark_move_region(curbuf, line1-1, 0, start_byte, @@ -1082,8 +1079,8 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n) curwin->w_cursor.lnum = n; while (line1 <= line2) { - /* need to use vim_strsave() because the line will be unlocked within - * ml_append() */ + // need to use vim_strsave() because the line will be unlocked within + // ml_append() p = vim_strsave(ml_get(line1)); ml_append(curwin->w_cursor.lnum, p, (colnr_T)0, false); xfree(p); @@ -1163,7 +1160,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out } if (ins_prevcmd) { if (prevcmd == NULL) { - EMSG(_(e_noprev)); + emsg(_(e_noprev)); xfree(newcmd); return; } @@ -1206,9 +1203,9 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out prevcmd = newcmd; if (bangredo) { // put cmd in redo buffer for ! command - /* If % or # appears in the command, it must have been escaped. - * Reescape them, so that redoing them does not substitute them by the - * buffername. */ + // If % or # appears in the command, it must have been escaped. + // Reescape them, so that redoing them does not substitute them by the + // buffername. char_u *cmd = vim_strsave_escaped(prevcmd, (char_u *)"%#"); AppendToRedobuffLit(cmd, -1); @@ -1237,8 +1234,8 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out do_shell(newcmd, 0); } else { // :range! - /* Careful: This may recursively call do_bang() again! (because of - * autocommands) */ + // Careful: This may recursively call do_bang() again! (because of + // autocommands) do_filter(line1, line2, eap, newcmd, do_in, do_out); apply_autocmds(EVENT_SHELLFILTERPOST, NULL, NULL, false, curbuf); } @@ -1322,7 +1319,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd, curwin->w_cursor.lnum = line2; } else if ((do_in && (itmp = vim_tempname()) == NULL) || (do_out && (otmp = vim_tempname()) == NULL)) { - EMSG(_(e_notmp)); + emsg(_(e_notmp)); goto filterend; } @@ -1336,7 +1333,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd, 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. + semsg(_("E482: Can't create file %s"), itmp); // Will call wait_return. } goto filterend; } @@ -1368,9 +1365,9 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd, did_check_timestamps = FALSE; need_check_timestamps = TRUE; - /* When interrupting the shell command, it may still have produced some - * useful output. Reset got_int here, so that readfile() won't cancel - * reading. */ + // When interrupting the shell command, it may still have produced some + // useful output. Reset got_int here, so that readfile() won't cancel + // reading. os_breakcheck(); got_int = FALSE; @@ -1380,7 +1377,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd, READ_FILTER) != OK) { if (!aborting()) { msg_putchar('\n'); - EMSG2(_(e_notread), otmp); + semsg(_(e_notread), otmp); } goto error; } @@ -1441,7 +1438,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd, if (do_in) { vim_snprintf(msg_buf, sizeof(msg_buf), _("%" PRId64 " lines filtered"), (int64_t)linecount); - if (msg((char_u *)msg_buf) && !msg_scroll) { + if (msg(msg_buf) && !msg_scroll) { // save message to display it after redraw set_keep_msg((char_u *)msg_buf, 0); } @@ -1461,7 +1458,7 @@ filterend: if (curbuf != old_curbuf) { --no_wait_return; - EMSG(_("E135: *Filter* Autocommands must not change current buffer")); + emsg(_("E135: *Filter* Autocommands must not change current buffer")); } if (itmp != NULL) { os_remove((char *)itmp); @@ -1500,7 +1497,7 @@ void do_shell(char_u *cmd, int flags) && msg_silent == 0) { FOR_ALL_BUFFERS(buf) { if (bufIsChanged(buf)) { - MSG_PUTS(_("[No write since last change]\n")); + msg_puts(_("[No write since last change]\n")); break; } } @@ -1739,7 +1736,7 @@ void ex_file(exarg_T *eap) && (*eap->arg != NUL || eap->line2 > 0 || eap->addr_count > 1)) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -1809,7 +1806,7 @@ int do_write(exarg_T *eap) ffname = eap->arg; if (*ffname == NUL) { if (eap->cmdidx == CMD_saveas) { - EMSG(_(e_argreq)); + emsg(_(e_argreq)); goto theend; } other = FALSE; @@ -1837,9 +1834,9 @@ int do_write(exarg_T *eap) alt_buf = buflist_findname(ffname); } if (alt_buf != NULL && alt_buf->b_ml.ml_mfp != NULL) { - /* Overwriting a file that is loaded in another buffer is not a - * good idea. */ - EMSG(_(e_bufloaded)); + // Overwriting a file that is loaded in another buffer is not a + // good idea. + emsg(_(e_bufloaded)); goto theend; } } @@ -1859,11 +1856,11 @@ int do_write(exarg_T *eap) /* * Not writing the whole file is only allowed with '!'. */ - if ( (eap->line1 != 1 - || eap->line2 != curbuf->b_ml.ml_line_count) - && !eap->forceit - && !eap->append - && !p_wa) { + if ((eap->line1 != 1 + || eap->line2 != curbuf->b_ml.ml_line_count) + && !eap->forceit + && !eap->append + && !p_wa) { if (p_confirm || cmdmod.confirm) { if (vim_dialog_yesno(VIM_QUESTION, NULL, (char_u *)_("Write partial file?"), 2) != VIM_YES) { @@ -1871,7 +1868,7 @@ int do_write(exarg_T *eap) } eap->forceit = TRUE; } else { - EMSG(_("E140: Use ! to write partial buffer")); + emsg(_("E140: Use ! to write partial buffer")); goto theend; } } @@ -1979,7 +1976,7 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char_u *fname, char_u *ffname, int #ifdef UNIX // It is possible to open a directory on Unix. if (os_isdir(ffname)) { - EMSG2(_(e_isadir2), ffname); + semsg(_(e_isadir2), ffname); return FAIL; } #endif @@ -1992,7 +1989,7 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char_u *fname, char_u *ffname, int } eap->forceit = TRUE; } else { - EMSG(_(e_exists)); + emsg(_(e_exists)); return FAIL; } } @@ -2032,7 +2029,7 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char_u *fname, char_u *ffname, int } eap->forceit = TRUE; } else { - EMSG2(_("E768: Swap file exists: %s (:silent! overrides)"), + semsg(_("E768: Swap file exists: %s (:silent! overrides)"), swapname); xfree(swapname); return FAIL; @@ -2096,7 +2093,7 @@ void do_wqall(exarg_T *eap) break; } if (buf->b_ffname == NULL) { - EMSGN(_("E141: No file name for buffer %" PRId64), buf->b_fnum); + semsg(_("E141: No file name for buffer %" PRId64), (int64_t)buf->b_fnum); ++error; } else if (check_readonly(&eap->forceit, buf) || check_overwrite(eap, buf, buf->b_fname, buf->b_ffname, @@ -2132,7 +2129,7 @@ int not_writing(void) if (p_write) { return FALSE; } - EMSG(_("E142: File not written: Writing is disabled by 'write' option")); + emsg(_("E142: File not written: Writing is disabled by 'write' option")); return TRUE; } @@ -2143,8 +2140,8 @@ int not_writing(void) */ static int check_readonly(int *forceit, buf_T *buf) { - /* Handle a file being readonly when the 'readonly' option is set or when - * the file exists and permissions are read-only. */ + // Handle a file being readonly when the 'readonly' option is set or when + // the file exists and permissions are read-only. if (!*forceit && (buf->b_p_ro || (os_path_exists(buf->b_ffname) && !os_file_is_writable((char *)buf->b_ffname)))) { @@ -2170,9 +2167,9 @@ static int check_readonly(int *forceit, buf_T *buf) return TRUE; } } else if (buf->b_p_ro) { - EMSG(_(e_readonly)); + emsg(_(e_readonly)); } else { - EMSG2(_("E505: \"%s\" is read-only (add ! to override)"), + semsg(_("E505: \"%s\" is read-only (add ! to override)"), buf->b_fname); } return TRUE; @@ -2279,6 +2276,7 @@ theend: /// ECMD_ADDBUF: don't edit, just add to buffer list /// ECMD_ALTBUF: like ECMD_ADDBUF and also set the alternate /// file +/// ECMD_NOWINENTER: Do not trigger BufWinEnter /// @param oldwin Should be "curwin" when editing a new buffer in the current /// window, NULL when splitting the window first. When not NULL /// info of the previous buffer for "oldwin" is stored. @@ -2612,8 +2610,8 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new set_buflisted(TRUE); } - /* If autocommands change buffers under our fingers, forget about - * editing the file. */ + // If autocommands change buffers under our fingers, forget about + // editing the file. if (buf != curbuf) { goto theend; } @@ -2677,9 +2675,9 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new } xfree(new_name); - /* If autocommands change buffers under our fingers, forget about - * re-editing the file. Should do the buf_clear_file(), but perhaps - * the autocommands changed the buffer... */ + // If autocommands change buffers under our fingers, forget about + // re-editing the file. Should do the buf_clear_file(), but perhaps + // the autocommands changed the buffer... if (buf != curbuf) { goto theend; } @@ -2711,8 +2709,8 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new */ curwin_init(); - /* It's possible that all lines in the buffer changed. Need to update - * automatic folding for all windows where it's used. */ + // It's possible that all lines in the buffer changed. Need to update + // automatic folding for all windows where it's used. FOR_ALL_TAB_WINDOWS(tp, win) { if (win->w_buffer == curbuf) { foldUpdateAll(win); @@ -2735,7 +2733,10 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new /* * Open the buffer and read the file. */ - if (should_abort(open_buffer(FALSE, eap, readfile_flags))) { + if (flags & ECMD_NOWINENTER) { + readfile_flags |= READ_NOWINENTER; + } + if (should_abort(open_buffer(false, eap, readfile_flags))) { retval = FAIL; } @@ -2744,15 +2745,17 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new } 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 - * changed by the user. */ + // Read the modelines, but only to set window-local options. Any + // buffer-local options have already been set and may have been + // changed by the user. do_modelines(OPT_WINONLY); apply_autocmds_retval(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf, &retval); - apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf, - &retval); + if ((flags & ECMD_NOWINENTER) == 0) { + apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, false, curbuf, + &retval); + } } check_arg_idx(curwin); @@ -2778,16 +2781,16 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new maketitle(); } - /* Tell the diff stuff that this buffer is new and/or needs updating. - * Also needed when re-editing the same buffer, because unloading will - * have removed it as a diff buffer. */ + // Tell the diff stuff that this buffer is new and/or needs updating. + // Also needed when re-editing the same buffer, because unloading will + // have removed it as a diff buffer. if (curwin->w_p_diff) { diff_buf_add(curbuf); diff_invalidate(curbuf); } - /* If the window options were changed may need to set the spell language. - * Can only do this after the buffer has been properly setup. */ + // If the window options were changed may need to set the spell language. + // Can only do this after the buffer has been properly setup. if (did_get_winopts && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) { (void)did_set_spelllang(curwin); } @@ -2895,7 +2898,7 @@ theend: static void delbuf_msg(char_u *name) { - EMSG2(_("E143: Autocommands unexpectedly deleted new buffer %s"), + semsg(_("E143: Autocommands unexpectedly deleted new buffer %s"), name == NULL ? (char_u *)"" : name); xfree(name); au_new_curbuf.br_buf = NULL; @@ -3022,10 +3025,10 @@ void ex_append(exarg_T *eap) curbuf->b_p_ai = !curbuf->b_p_ai; } - /* "start" is set to eap->line2+1 unless that position is invalid (when - * eap->line2 pointed to the end of the buffer and nothing was appended) - * "end" is set to lnum when something has been appended, otherwise - * it is the same than "start" -- Acevedo */ + // "start" is set to eap->line2+1 unless that position is invalid (when + // eap->line2 pointed to the end of the buffer and nothing was appended) + // "end" is set to lnum when something has been appended, otherwise + // it is the same than "start" -- Acevedo curbuf->b_op_start.lnum = (eap->line2 < curbuf->b_ml.ml_line_count) ? eap->line2 + 1 : curbuf->b_ml.ml_line_count; if (eap->cmdidx != CMD_append) { @@ -3110,7 +3113,7 @@ void ex_z(exarg_T *eap) if (*x != 0) { if (!ascii_isdigit(*x)) { - EMSG(_("E144: non-numeric argument to :z")); + emsg(_("E144: non-numeric argument to :z")); return; } bigness = atol((char *)x); @@ -3129,7 +3132,6 @@ void ex_z(exarg_T *eap) // the number of '-' and '+' multiplies the distance if (*kind == '-' || *kind == '+') { for (x = kind + 1; *x == *kind; ++x) { - ; } } @@ -3221,14 +3223,14 @@ int check_secure(void) { if (secure) { secure = 2; - EMSG(_(e_curdir)); + emsg(_(e_curdir)); return TRUE; } // In the sandbox more things are not allowed, including the things // disallowed in secure mode. if (sandbox != 0) { - EMSG(_(e_sandbox)); + emsg(_(e_sandbox)); return TRUE; } return FALSE; @@ -3424,7 +3426,7 @@ static int check_regexp_delim(int c) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { if (isalpha(c)) { - EMSG(_("E146: Regular expressions can't be delimited by letters")); + emsg(_("E146: Regular expressions can't be delimited by letters")); return FAIL; } return OK; @@ -3503,7 +3505,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle if (*cmd == '\\') { ++cmd; if (vim_strchr((char_u *)"/?&", *cmd) == NULL) { - EMSG(_(e_backslash)); + emsg(_(e_backslash)); return NULL; } if (*cmd != '&') { @@ -3549,14 +3551,14 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle } } else if (!eap->skip) { // use previous pattern and substitution if (old_sub.sub == NULL) { // there is no previous command - EMSG(_(e_nopresub)); + emsg(_(e_nopresub)); return NULL; } pat = NULL; // search_regcomp() will use previous pattern sub = (char_u *)old_sub.sub; - /* Vi compatibility quirk: repeating with ":s" keeps the cursor in the - * last column after using "$". */ + // Vi compatibility quirk: repeating with ":s" keeps the cursor in the + // last column after using "$". endcolumn = (curwin->w_curswant == MAXCOL); } @@ -3574,7 +3576,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle if (ascii_isdigit(*cmd)) { i = getdigits_long(&cmd, true, 0); if (i <= 0 && !eap->skip && subflags.do_error) { - EMSG(_(e_zerocount)); + emsg(_(e_zerocount)); return NULL; } eap->line1 = eap->line2; @@ -3591,7 +3593,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle if (*cmd && *cmd != '"') { // if not end-of-line or comment eap->nextcmd = check_nextcmd(cmd); if (eap->nextcmd == NULL) { - EMSG(_(e_trailing)); + emsg(_(e_trailing)); return NULL; } } @@ -3602,14 +3604,14 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle if (!subflags.do_count && !MODIFIABLE(curbuf)) { // Substitution is not allowed in non-'modifiable' buffer - EMSG(_(e_modifiable)); + emsg(_(e_modifiable)); return NULL; } if (search_regcomp(pat, RE_SUBST, which_pat, (preview ? 0 : SEARCH_HIS), ®match) == FAIL) { if (subflags.do_error) { - EMSG(_(e_invcmd)); + emsg(_(e_invcmd)); } return NULL; } @@ -3769,7 +3771,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle skip_match = true; } else { // search for a match at next column - matchcol += mb_ptr2len(sub_firstline + matchcol); + matchcol += utfc_ptr2len(sub_firstline + matchcol); } // match will be pushed to preview_lines, bring it into a proper state current_match.start.col = matchcol; @@ -3807,8 +3809,8 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle if (subflags.do_ask && !preview) { int typed = 0; - /* change State to CONFIRM, so that the mouse works - * properly */ + // change State to CONFIRM, so that the mouse works + // properly int save_State = State; State = CONFIRM; setmouse(); // disable mouse in xterm @@ -3864,9 +3866,9 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle const bool save_p_lz = p_lz; int save_p_fen = curwin->w_p_fen; - curwin->w_p_fen = FALSE; - /* Invert the matched string. - * Remove the inversion afterwards. */ + curwin->w_p_fen = false; + // Invert the matched string. + // Remove the inversion afterwards. int temp = RedrawingDisabled; RedrawingDisabled = 0; @@ -3874,11 +3876,11 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle p_lz = false; if (new_start != NULL) { - /* There already was a substitution, we would - * like to show this to the user. We cannot - * really update the line, it would change - * what matches. Temporarily replace the line - * and change it back afterwards. */ + // There already was a substitution, we would + // like to show this to the user. We cannot + // really update the line, it would change + // what matches. Temporarily replace the line + // and change it back afterwards. orig_line = vim_strsave(ml_get(lnum)); char_u *new_line = concat_str(new_start, sub_firstline + copycol); @@ -3908,8 +3910,8 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle } msg_starthere(); i = msg_scroll; - msg_scroll = 0; /* truncate msg when - needed */ + msg_scroll = 0; // truncate msg when + // needed msg_no_more = true; msg_ext_set_kind("confirm_sub"); smsg_attr(HL_ATTR(HLF_R), // Same highlight as wait_return(). @@ -4364,7 +4366,7 @@ skip: } } if (!preview && !do_sub_msg(subflags.do_count) && subflags.do_ask) { - MSG(""); + msg(""); } } else { global_need_beginline = true; @@ -4375,13 +4377,13 @@ skip: } else if (!global_busy) { if (got_int) { // interrupted - EMSG(_(e_interr)); + emsg(_(e_interr)); } else if (got_match) { // did find something but nothing substituted - MSG(""); + msg(""); } else if (subflags.do_error) { // nothing found - EMSG2(_(e_patnotf2), get_search_pat()); + semsg(_(e_patnotf2), get_search_pat()); } } @@ -4403,7 +4405,7 @@ skip: if (got_quit || profile_passed_limit(timeout)) { // Too slow, disable. set_string_option_direct("icm", -1, (char_u *)"", OPT_FREE, SID_NONE); - } else if (*p_icm != NUL && pat != NULL) { + } else if (*p_icm != NUL && pat != NULL) { if (pre_src_id == 0) { // Get a unique new src_id, saved in a static pre_src_id = (int)nvim_create_namespace((String)STRING_INIT); @@ -4450,30 +4452,28 @@ bool do_sub_msg(bool count_only) } else { *msg_buf = NUL; } - if (sub_nsubs == 1) { - vim_snprintf_add(msg_buf, sizeof(msg_buf), - "%s", count_only ? _("1 match") : _("1 substitution")); - } else { - vim_snprintf_add(msg_buf, sizeof(msg_buf), - count_only ? _("%" PRId64 " matches") - : _("%" PRId64 " substitutions"), - (int64_t)sub_nsubs); - } - if (sub_nlines == 1) { - vim_snprintf_add(msg_buf, sizeof(msg_buf), - "%s", _(" on 1 line")); - } else { - vim_snprintf_add(msg_buf, sizeof(msg_buf), - _(" on %" PRId64 " lines"), (int64_t)sub_nlines); - } - if (msg((char_u *)msg_buf)) { + + char *msg_single = count_only + ? NGETTEXT("%" PRId64 " match on %" PRId64 " line", + "%" PRId64 " matches on %" PRId64 " line", sub_nsubs) + : NGETTEXT("%" PRId64 " substitution on %" PRId64 " line", + "%" PRId64 " substitutions on %" PRId64 " line", sub_nsubs); + char *msg_plural = count_only + ? NGETTEXT("%" PRId64 " match on %" PRId64 " lines", + "%" PRId64 " matches on %" PRId64 " lines", sub_nsubs) + : NGETTEXT("%" PRId64 " substitution on %" PRId64 " lines", + "%" PRId64 " substitutions on %" PRId64 " lines", sub_nsubs); + vim_snprintf_add((char *)msg_buf, sizeof(msg_buf), + NGETTEXT(msg_single, msg_plural, sub_nlines), + (int64_t)sub_nsubs, (int64_t)sub_nlines); + if (msg(msg_buf)) { // save message to display it after redraw set_keep_msg((char_u *)msg_buf, 0); } return true; } if (got_int) { - EMSG(_(e_interr)); + emsg(_(e_interr)); return true; } return false; @@ -4524,7 +4524,7 @@ void ex_global(exarg_T *eap) if (global_busy && (eap->line1 != 1 || eap->line2 != curbuf->b_ml.ml_line_count)) { // will increment global_busy to break out of the loop - EMSG(_("E147: Cannot do :global recursive with a range")); + emsg(_("E147: Cannot do :global recursive with a range")); return; } @@ -4544,7 +4544,7 @@ void ex_global(exarg_T *eap) if (*cmd == '\\') { ++cmd; if (vim_strchr((char_u *)"/?&", *cmd) == NULL) { - EMSG(_(e_backslash)); + emsg(_(e_backslash)); return; } if (*cmd == '&') { @@ -4555,7 +4555,7 @@ void ex_global(exarg_T *eap) ++cmd; pat = (char_u *)""; } else if (*cmd == NUL) { - EMSG(_("E148: Regular expression missing from global")); + emsg(_("E148: Regular expression missing from global")); return; } else if (check_regexp_delim(*cmd) == FAIL) { return; @@ -4572,7 +4572,7 @@ void ex_global(exarg_T *eap) } if (search_regcomp(pat, RE_BOTH, which_pat, SEARCH_HIS, ®match) == FAIL) { - EMSG(_(e_invcmd)); + emsg(_(e_invcmd)); return; } @@ -4598,7 +4598,7 @@ void ex_global(exarg_T *eap) // pass 2: execute the command for each line that has been marked if (got_int) { - MSG(_(e_interr)); + msg(_(e_interr)); } else if (ndone == 0) { if (type == 'v') { smsg(_("Pattern found in every line: %s"), pat); @@ -4718,7 +4718,6 @@ bool prepare_tagpreview(bool undo_sync) } - /* * ":help": open a read-only window on a help file */ @@ -4756,7 +4755,7 @@ void ex_help(exarg_T *eap) arg = eap->arg; if (eap->forceit && *arg == NUL && !curbuf->b_help) { - EMSG(_("E478: Don't panic!")); + emsg(_("E478: Don't panic!")); return; } @@ -4800,9 +4799,9 @@ void ex_help(exarg_T *eap) } if (i >= num_matches || n == FAIL) { if (lang != NULL) { - EMSG3(_("E661: Sorry, no '%s' help for %s"), lang, arg); + semsg(_("E661: Sorry, no '%s' help for %s"), lang, arg); } else { - EMSG2(_("E149: Sorry, no help for %s"), arg); + semsg(_("E149: Sorry, no help for %s"), arg); } if (n != FAIL) { FreeWild(num_matches, matches); @@ -4878,8 +4877,8 @@ void ex_help(exarg_T *eap) if (!p_im) { restart_edit = 0; // don't want insert mode in help file } - /* Restore KeyTyped, setting 'filetype=help' may reset it. - * It is needed for do_tag top open folds under the cursor. */ + // Restore KeyTyped, setting 'filetype=help' may reset it. + // It is needed for do_tag top open folds under the cursor. KeyTyped = old_KeyTyped; do_tag(tag, DT_HELP, 1, FALSE, TRUE); @@ -5073,11 +5072,10 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool STRCPY(d + 4, "\\$"); } } else { - /* Replace: - * "[:...:]" with "\[:...:]" - * "[++...]" with "\[++...]" - * "\{" with "\\{" -- matching "} \}" - */ + // Replace: + // "[:...:]" with "\[:...:]" + // "[++...]" with "\[++...]" + // "\{" with "\\{" -- matching "} \}" if ((arg[0] == '[' && (arg[1] == ':' || (arg[1] == '+' && arg[2] == '+'))) || (arg[0] == '\\' && arg[1] == '{')) { @@ -5170,7 +5168,7 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool // If tag contains "({" or "([", tag terminates at the "(". // This is for help on functions, e.g.: abs({expr}). - if (*s == '(' && (s[1] == '{' || s[1] =='[')) { + if (*s == '(' && (s[1] == '{' || s[1] == '[')) { break; } @@ -5327,8 +5325,8 @@ void fix_help_buffer(void) continue; } - /* Go through all directories in 'runtimepath', skipping - * $VIMRUNTIME. */ + // Go through all directories in 'runtimepath', skipping + // $VIMRUNTIME. char_u *p = p_rtp; while (*p != NUL) { copy_option_part(&p, NameBuff, MAXPATHL, ","); @@ -5345,7 +5343,7 @@ void fix_help_buffer(void) if (!add_pathsep((char *)NameBuff) || STRLCAT(NameBuff, "doc/*.??[tx]", sizeof(NameBuff)) >= MAXPATHL) { - EMSG(_(e_fnametoolong)); + emsg(_(e_fnametoolong)); continue; } @@ -5413,10 +5411,9 @@ void fix_help_buffer(void) if (*s == '\r' || *s == '\n') { *s = NUL; } - /* The text is utf-8 when a byte - * above 127 is found and no - * illegal byte sequence is found. - */ + // The text is utf-8 when a byte + // above 127 is found and no + // illegal byte sequence is found. if (*s >= 0x80 && this_utf != kFalse) { this_utf = kTrue; const int l = utf_ptr2len(s); @@ -5427,9 +5424,9 @@ void fix_help_buffer(void) } ++s; } - /* The help file is latin1 or utf-8; - * conversion to the current - * 'encoding' may be required. */ + // The help file is latin1 or utf-8; + // conversion to the current + // 'encoding' may be required. vc.vc_type = CONV_NONE; convert_setup(&vc, (char_u *)(this_utf == kTrue ? "utf-8" : "latin1"), @@ -5507,7 +5504,7 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname, if (dirlen >= MAXPATHL || STRLCAT(NameBuff, "/**/*", sizeof(NameBuff)) >= MAXPATHL // NOLINT || STRLCAT(NameBuff, ext, sizeof(NameBuff)) >= MAXPATHL) { - EMSG(_(e_fnametoolong)); + emsg(_(e_fnametoolong)); return; } @@ -5518,7 +5515,7 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname, EW_FILE|EW_SILENT) == FAIL || filecount == 0) { if (!got_int) { - EMSG2(_("E151: No match: %s"), NameBuff); + semsg(_("E151: No match: %s"), NameBuff); } return; } @@ -5530,14 +5527,14 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname, memcpy(NameBuff, dir, dirlen + 1); if (!add_pathsep((char *)NameBuff) || STRLCAT(NameBuff, tagfname, sizeof(NameBuff)) >= MAXPATHL) { - EMSG(_(e_fnametoolong)); + emsg(_(e_fnametoolong)); return; } FILE *const fd_tags = os_fopen((char *)NameBuff, "w"); if (fd_tags == NULL) { if (!ignore_writeerr) { - EMSG2(_("E152: Cannot open %s for writing"), NameBuff); + semsg(_("E152: Cannot open %s for writing"), NameBuff); } FreeWild(filecount, files); return; @@ -5559,7 +5556,7 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname, for (int fi = 0; fi < filecount && !got_int; fi++) { FILE *const fd = os_fopen((char *)files[fi], "r"); if (fd == NULL) { - EMSG2(_("E153: Unable to open %s for reading"), files[fi]); + semsg(_("E153: Unable to open %s for reading"), files[fi]); continue; } const char_u *const fname = files[fi] + dirlen + 1; @@ -5587,7 +5584,7 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname, if (utf8 == kNone) { // first file utf8 = this_utf8; } else if (utf8 != this_utf8) { - EMSG2(_("E670: Mix of help file encodings within a language: %s"), + semsg(_("E670: Mix of help file encodings within a language: %s"), files[fi]); mix = !got_int; got_int = TRUE; @@ -5646,7 +5643,7 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname, vim_snprintf((char *)NameBuff, MAXPATHL, _("E154: Duplicate tag \"%s\" in file %s/%s"), ((char_u **)ga.ga_data)[i], dir, p2 + 1); - EMSG(NameBuff); + emsg((char *)NameBuff); *p2 = '\t'; break; } @@ -5702,7 +5699,7 @@ static void do_helptags(char_u *dirname, bool add_help_tags, bool ignore_writeer STRLCPY(NameBuff, dirname, sizeof(NameBuff)); if (!add_pathsep((char *)NameBuff) || STRLCAT(NameBuff, "**", sizeof(NameBuff)) >= MAXPATHL) { - EMSG(_(e_fnametoolong)); + emsg(_(e_fnametoolong)); return; } @@ -5712,12 +5709,12 @@ static void do_helptags(char_u *dirname, bool add_help_tags, bool ignore_writeer if (gen_expand_wildcards(1, buff_list, &filecount, &files, EW_FILE|EW_SILENT) == FAIL || filecount == 0) { - EMSG2(_("E151: No match: %s"), NameBuff); + semsg(_("E151: No match: %s"), NameBuff); return; } - /* Go over all files in the directory to find out what languages are - * present. */ + // Go over all files in the directory to find out what languages are + // present. int j; ga_init(&ga, 1, 10); for (int i = 0; i < filecount; i++) { @@ -5807,7 +5804,7 @@ void ex_helptags(exarg_T *eap) dirname = ExpandOne(&xpc, eap->arg, NULL, WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE); if (dirname == NULL || !os_isdir(dirname)) { - EMSG2(_("E150: Not a directory: %s"), eap->arg); + semsg(_("E150: Not a directory: %s"), eap->arg); } else { do_helptags(dirname, add_help_tags, false); } @@ -6128,7 +6125,7 @@ void ex_oldfiles(exarg_T *eap) long nr = 0; if (l == NULL) { - msg((char_u *)_("No old files")); + msg(_("No old files")); } else { msg_start(); msg_scroll = true; @@ -6140,7 +6137,7 @@ void ex_oldfiles(exarg_T *eap) const char *fname = tv_get_string(TV_LIST_ITEM_TV(li)); if (!message_filtered((char_u *)fname)) { msg_outnum(nr); - MSG_PUTS(": "); + msg_puts(": "); msg_outtrans((char_u *)tv_get_string(TV_LIST_ITEM_TV(li))); msg_clr_eos(); msg_putchar('\n'); diff --git a/src/nvim/ex_cmds.h b/src/nvim/ex_cmds.h index c34ffa1d3b..241674c24c 100644 --- a/src/nvim/ex_cmds.h +++ b/src/nvim/ex_cmds.h @@ -16,7 +16,8 @@ #define ECMD_OLDBUF 0x04 // use existing buffer if it exists #define ECMD_FORCEIT 0x08 // ! used in Ex command #define ECMD_ADDBUF 0x10 // don't edit, just add to buffer list -#define ECMD_ALTBUF 0x20 // like ECMD_ADDBUF and set the alternate file +#define ECMD_ALTBUF 0x20 // like ECMD_ADDBUF and set the alternate file +#define ECMD_NOWINENTER 0x40 // do not trigger BufWinEnter // for lnum argument in do_ecmd() #define ECMD_LASTL (linenr_T)0 // use last position in loaded file diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 5d40d7a16a..787b3f07b2 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -110,7 +110,7 @@ void ex_profile(exarg_T *eap) profile_set_wait(profile_zero()); set_vim_var_nr(VV_PROFILING, 1L); } else if (do_profiling == PROF_NONE) { - EMSG(_("E750: First use \":profile start {fname}\"")); + emsg(_("E750: First use \":profile start {fname}\"")); } else if (STRCMP(eap->arg, "stop") == 0) { profile_dump(); do_profiling = PROF_NONE; @@ -198,7 +198,7 @@ void ex_perldo(exarg_T *eap) // Command line expansion for :profile. static enum { PEXP_SUBCMD, ///< expand :profile sub-commands - PEXP_FUNC ///< expand :profile func {funcname} + PEXP_FUNC, ///< expand :profile func {funcname} } pexpand_what; static char *pexpand_cmds[] = { @@ -256,7 +256,7 @@ void profile_dump(void) if (profile_fname != NULL) { fd = os_fopen((char *)profile_fname, "w"); if (fd == NULL) { - EMSG2(_(e_notopen), profile_fname); + semsg(_(e_notopen), profile_fname); } else { script_dump_profile(fd); func_dump_profile(fd); @@ -550,7 +550,6 @@ bool check_changed(buf_T *buf, int flags) } - /// Ask the user what to do when abandoning a changed buffer. /// Must check 'write' option first! /// @@ -749,8 +748,8 @@ bool check_changed_any(bool hidden, bool unload) msg_didout = false; } if ((buf->terminal && channel_job_running((uint64_t)buf->b_p_channel)) - ? EMSG2(_("E947: Job still running in buffer \"%s\""), buf->b_fname) - : EMSG2(_("E162: No write since last change for buffer \"%s\""), + ? semsg(_("E947: Job still running in buffer \"%s\""), buf->b_fname) + : semsg(_("E162: No write since last change for buffer \"%s\""), buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname)) { save = no_wait_return; no_wait_return = false; @@ -791,7 +790,7 @@ theend: int check_fname(void) { if (curbuf->b_ffname == NULL) { - EMSG(_(e_noname)); + emsg(_(e_noname)); return FAIL; } return OK; @@ -810,7 +809,7 @@ int buf_write_all(buf_T *buf, int forceit) false, forceit, true, false)); if (curbuf != old_curbuf) { msg_source(HL_ATTR(HLF_W)); - MSG(_("Warning: Entered other buffer unexpectedly (check autocommands)")); + msg(_("Warning: Entered other buffer unexpectedly (check autocommands)")); } return retval; } @@ -965,7 +964,7 @@ static int do_arglist(char_u *str, int what, int after, bool will_edit) vim_regfree(regmatch.regprog); xfree(p); if (!didone) { - EMSG2(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]); + semsg(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]); } } ga_clear(&new_ga); @@ -975,7 +974,7 @@ static int do_arglist(char_u *str, int what, int after, bool will_edit) EW_DIR|EW_FILE|EW_ADDSLASH|EW_NOTFOUND); ga_clear(&new_ga); if (i == FAIL || exp_count == 0) { - EMSG(_(e_nomatch)); + emsg(_(e_nomatch)); return FAIL; } @@ -1136,11 +1135,11 @@ void do_argfile(exarg_T *eap, int argn) if (argn < 0 || argn >= ARGCOUNT) { if (ARGCOUNT <= 1) { - EMSG(_("E163: There is only one file to edit")); + emsg(_("E163: There is only one file to edit")); } else if (argn < 0) { - EMSG(_("E164: Cannot go before first file")); + emsg(_("E164: Cannot go before first file")); } else { - EMSG(_("E165: Cannot go beyond last file")); + emsg(_("E165: Cannot go beyond last file")); } } else { setpcmark(); @@ -1253,7 +1252,7 @@ void ex_argdelete(exarg_T *eap) // ":argdel" works like ":.argdel" if (eap->addr_count == 0) { if (curwin->w_arg_idx >= ARGCOUNT) { - EMSG(_("E610: No argument to delete")); + emsg(_("E610: No argument to delete")); return; } eap->line1 = eap->line2 = curwin->w_arg_idx + 1; @@ -1264,11 +1263,11 @@ void ex_argdelete(exarg_T *eap) linenr_T n = eap->line2 - eap->line1 + 1; if (*eap->arg != NUL) { // Can't have both a range and an argument. - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } else if (n <= 0) { // Don't give an error for ":%argdel" if the list is empty. if (eap->line1 != 1 || eap->line2 != 0) { - EMSG(_(e_invrange)); + emsg(_(e_invrange)); } } else { for (linenr_T i = eap->line1; i <= eap->line2; i++) { @@ -1382,6 +1381,7 @@ void ex_listdo(exarg_T *eap) listcmd_busy = true; // avoids setting pcmark below while (!got_int && buf != NULL) { + bool execute = true; if (eap->cmdidx == CMD_argdo) { // go to argument "i" if (i == ARGCOUNT) { @@ -1407,11 +1407,14 @@ void ex_listdo(exarg_T *eap) break; } assert(wp); - win_goto(wp); - if (curwin != wp) { - break; // something must be wrong + execute = !wp->w_floating || wp->w_float_config.focusable; + if (execute) { + win_goto(wp); + if (curwin != wp) { + break; // something must be wrong + } } - wp = curwin->w_next; + wp = wp->w_next; } else if (eap->cmdidx == CMD_tabdo) { // go to window "tp" if (!valid_tabpage(tp)) { @@ -1434,8 +1437,10 @@ void ex_listdo(exarg_T *eap) i++; // execute the command - do_cmdline(eap->arg, eap->getline, eap->cookie, - DOCMD_VERBOSE + DOCMD_NOWAIT); + if (execute) { + do_cmdline(eap->arg, eap->getline, eap->cookie, + DOCMD_VERBOSE + DOCMD_NOWAIT); + } if (eap->cmdidx == CMD_bufdo) { // Done? @@ -1486,7 +1491,7 @@ void ex_listdo(exarg_T *eap) } } - if (eap->cmdidx == CMD_windo) { + if (eap->cmdidx == CMD_windo && execute) { validate_cursor(); // cursor may have moved // required when 'scrollbind' has been set if (curwin->w_p_scb) { @@ -1618,7 +1623,7 @@ void ex_compiler(exarg_T *eap) // Try lua compiler snprintf((char *)buf, bufsize, "compiler/%s.lua", eap->arg); if (source_runtime((char *)buf, DIP_ALL) == FAIL) { - EMSG2(_("E666: compiler not supported: %s"), eap->arg); + semsg(_("E666: compiler not supported: %s"), eap->arg); } } xfree(buf); @@ -1798,7 +1803,7 @@ static void cmd_source(char_u *fname, exarg_T *eap) // ":source" read ex commands } else if (do_source((char *)fname, false, DOSO_NONE) == FAIL) { - EMSG2(_(e_notopen), fname); + semsg(_(e_notopen), fname); } } @@ -2252,7 +2257,7 @@ int do_source(char *fname, int check_other, int is_vimrc) } if (got_int) { - EMSG(_(e_interr)); + emsg(_(e_interr)); } sourcing_name = save_sourcing_name; sourcing_lnum = save_sourcing_lnum; @@ -2308,7 +2313,7 @@ void ex_scriptnames(exarg_T *eap) if (eap->addr_count > 0) { // :script {scriptId}: edit the script if (eap->line2 < 1 || eap->line2 > script_items.ga_len) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } else { eap->arg = SCRIPT_ITEM(eap->line2).sn_name; do_exedit(eap, NULL); @@ -2554,7 +2559,7 @@ retry: } else { // lines like ":map xx yy^M" will have failed if (!sp->error) { msg_source(HL_ATTR(HLF_W)); - EMSG(_("W15: Warning: Wrong line separator, ^M may be missing")); + emsg(_("W15: Warning: Wrong line separator, ^M may be missing")); } sp->error = true; sp->fileformat = EOL_UNIX; @@ -2668,7 +2673,7 @@ void ex_scriptencoding(exarg_T *eap) char_u *name; if (!getline_equal(eap->getline, eap->cookie, getsourceline)) { - EMSG(_("E167: :scriptencoding used outside of a sourced file")); + emsg(_("E167: :scriptencoding used outside of a sourced file")); return; } @@ -2693,7 +2698,7 @@ void ex_finish(exarg_T *eap) if (getline_equal(eap->getline, eap->cookie, getsourceline)) { do_finish(eap, false); } else { - EMSG(_("E168: :finish used outside of a sourced file")); + emsg(_("E168: :finish used outside of a sourced file")); } } @@ -2940,7 +2945,7 @@ void ex_language(exarg_T *eap) } # endif if (loc == NULL) { - EMSG2(_("E197: Cannot set language to \"%s\""), name); + semsg(_("E197: Cannot set language to \"%s\""), name); } else { # ifdef HAVE_NL_MSG_CAT_CNTR // Need to do this for GNU gettext, otherwise cached translations diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h index 171f8ed5cd..6e5dd144ad 100644 --- a/src/nvim/ex_cmds_defs.h +++ b/src/nvim/ex_cmds_defs.h @@ -78,7 +78,7 @@ typedef enum { ADDR_QUICKFIX, // quickfix list entry number ADDR_UNSIGNED, // positive count or zero, defaults to 1 ADDR_OTHER, // something else, use line number for '$', '%', etc. - ADDR_NONE // no range used + ADDR_NONE, // no range used } cmd_addr_T; typedef struct exarg exarg_T; @@ -168,7 +168,7 @@ struct exarg { int force_enc; ///< ++enc= argument (index in cmd[]) int bad_char; ///< BAD_KEEP, BAD_DROP or replacement byte int useridx; ///< user command index - char_u *errmsg; ///< returned error message + char *errmsg; ///< returned error message LineGetter getline; ///< Function used to get the next line void *cookie; ///< argument for getline() cstack_T *cstack; ///< condition stack for ":if" etc. diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 4524026e3f..499c6ed4f9 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -207,7 +207,7 @@ void do_exmode(void) RedrawingDisabled++; // don't redisplay the window no_wait_return++; // don't wait for return - MSG(_("Entering Ex mode. Type \"visual\" to go to Normal mode.")); + msg(_("Entering Ex mode. Type \"visual\" to go to Normal mode.")); while (exmode_active) { // Check for a ":normal" command and no more characters left. if (ex_normal_busy > 0 && typebuf.tb_len == 0) { @@ -228,7 +228,7 @@ void do_exmode(void) if ((prev_line != curwin->w_cursor.lnum || changedtick != buf_get_changedtick(curbuf)) && !ex_no_reprint) { if (curbuf->b_ml.ml_flags & ML_EMPTY) { - EMSG(_(e_emptybuf)); + emsg(_(e_emptybuf)); } else { if (ex_pressedreturn) { // go up one line, to overwrite the ":<CR>" line, so the @@ -244,9 +244,9 @@ void do_exmode(void) } } else if (ex_pressedreturn && !ex_no_reprint) { // must be at EOF if (curbuf->b_ml.ml_flags & ML_EMPTY) { - EMSG(_(e_emptybuf)); + emsg(_(e_emptybuf)); } else { - EMSG(_("E501: At end-of-file")); + emsg(_("E501: At end-of-file")); } } } @@ -340,12 +340,12 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags) int getline_is_func; static int call_depth = 0; // recursiveness - /* For every pair of do_cmdline()/do_one_cmd() calls, use an extra memory - * location for storing error messages to be converted to an exception. - * This ensures that the do_errthrow() call in do_one_cmd() does not - * combine the messages stored by an earlier invocation of do_one_cmd() - * with the command name of the later one. This would happen when - * BufWritePost autocommands are executed after a write error. */ + // For every pair of do_cmdline()/do_one_cmd() calls, use an extra memory + // location for storing error messages to be converted to an exception. + // This ensures that the do_errthrow() call in do_one_cmd() does not + // combine the messages stored by an earlier invocation of do_one_cmd() + // with the command name of the later one. This would happen when + // BufWritePost autocommands are executed after a write error. saved_msg_list = msg_list; msg_list = &private_msg_list; private_msg_list = NULL; @@ -354,7 +354,7 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags) // 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")); + 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. do_errthrow((cstack_T *)NULL, (char_u *)NULL); @@ -445,12 +445,12 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags) // 1. If repeating, get a previous line from lines_ga. if (cstack.cs_looplevel > 0 && current_line < lines_ga.ga_len) { - /* Each '|' separated command is stored separately in lines_ga, to - * be able to jump to it. Don't use next_cmdline now. */ + // Each '|' separated command is stored separately in lines_ga, to + // be able to jump to it. Don't use next_cmdline now. XFREE_CLEAR(cmdline_copy); - /* Check if a function has returned or, unless it has an unclosed - * try conditional, aborted. */ + // Check if a function has returned or, unless it has an unclosed + // try conditional, aborted. if (getline_is_func) { if (do_profiling == PROF_YES) { func_line_end(real_cookie); @@ -630,8 +630,8 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags) new_last_cmdline = NULL; } } else { - /* need to copy the command after the '|' to cmdline_copy, for the - * next do_one_cmd() */ + // need to copy the command after the '|' to cmdline_copy, for the + // next do_one_cmd() STRMOVE(cmdline_copy, next_cmdline); next_cmdline = cmdline_copy; } @@ -656,10 +656,10 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags) if (cstack.cs_lflags & (CSL_HAD_CONT | CSL_HAD_ENDLOOP)) { cstack.cs_lflags &= ~(CSL_HAD_CONT | CSL_HAD_ENDLOOP); - /* Jump back to the matching ":while" or ":for". Be careful - * not to use a cs_line[] from an entry that isn't a ":while" - * or ":for": It would make "current_line" invalid and can - * cause a crash. */ + // Jump back to the matching ":while" or ":for". Be careful + // not to use a cs_line[] from an entry that isn't a ":while" + // or ":for": It would make "current_line" invalid and can + // cause a crash. if (!did_emsg && !got_int && !current_exception && cstack.cs_idx >= 0 && (cstack.cs_flags[cstack.cs_idx] @@ -752,9 +752,9 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags) while (!((got_int || (did_emsg && force_abort) || current_exception) && cstack.cs_trylevel == 0) && !(did_emsg - /* Keep going when inside try/catch, so that the error can be - * deal with, except when it is a syntax error, it may cause - * the :endtry to be missed. */ + // Keep going when inside try/catch, so that the error can be + // deal with, except when it is a syntax error, it may cause + // the :endtry to be missed. && (cstack.cs_trylevel == 0 || did_emsg_syntax) && used_getline && getline_equal(fgetline, cookie, getexline)) @@ -777,13 +777,13 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags) || (getline_equal(fgetline, cookie, get_func_line) && !func_has_ended(real_cookie)))) { if (cstack.cs_flags[cstack.cs_idx] & CSF_TRY) { - EMSG(_(e_endtry)); + emsg(_(e_endtry)); } else if (cstack.cs_flags[cstack.cs_idx] & CSF_WHILE) { - EMSG(_(e_endwhile)); + emsg(_(e_endwhile)); } else if (cstack.cs_flags[cstack.cs_idx] & CSF_FOR) { - EMSG(_(e_endfor)); + emsg(_(e_endfor)); } else { - EMSG(_(e_endif)); + emsg(_(e_endif)); } } @@ -1256,7 +1256,7 @@ static char_u *do_one_cmd(char_u **cmdlinep, int flags, cstack_T *cstack, LineGe char_u *p; linenr_T lnum; long n; - char_u *errormsg = NULL; // error message + char *errormsg = NULL; // error message char_u *after_modifier = NULL; exarg_T ea; const int save_msg_scroll = msg_scroll; @@ -1435,7 +1435,7 @@ static char_u *do_one_cmd(char_u **cmdlinep, int flags, cstack_T *cstack, LineGe } if (ea.line2 < 0) { - errormsg = (char_u *)_(e_invrange); + errormsg = _(e_invrange); } else { if (ea.line2 == 0) { curwin->w_cursor.lnum = 1; @@ -1467,7 +1467,7 @@ static char_u *do_one_cmd(char_u **cmdlinep, int flags, cstack_T *cstack, LineGe if (p == NULL) { if (!ea.skip) { - errormsg = (char_u *)_("E464: Ambiguous use of user-defined command"); + errormsg = _("E464: Ambiguous use of user-defined command"); } goto doend; } @@ -1481,7 +1481,7 @@ static char_u *do_one_cmd(char_u **cmdlinep, int flags, cstack_T *cstack, LineGe if (!(flags & DOCMD_VERBOSE)) { append_command(cmdname); } - errormsg = IObuff; + errormsg = (char *)IObuff; did_emsg_syntax = true; verify_command(cmdname); } @@ -1511,21 +1511,21 @@ static char_u *do_one_cmd(char_u **cmdlinep, int flags, cstack_T *cstack, LineGe if (!ea.skip) { if (sandbox != 0 && !(ea.argt & EX_SBOXOK)) { // Command not allowed in sandbox. - errormsg = (char_u *)_(e_sandbox); + errormsg = _(e_sandbox); goto doend; } if (!MODIFIABLE(curbuf) && (ea.argt & EX_MODIFY) // allow :put in terminals && (!curbuf->terminal || ea.cmdidx != CMD_put)) { // Command not allowed in non-'modifiable' buffer - errormsg = (char_u *)_(e_modifiable); + errormsg = _(e_modifiable); goto doend; } if (text_locked() && !(ea.argt & EX_CMDWIN) && !IS_USER_CMDIDX(ea.cmdidx)) { // Command not allowed when editing the command line. - errormsg = (char_u *)_(get_text_locked_msg()); + errormsg = _(get_text_locked_msg()); goto doend; } @@ -1544,13 +1544,13 @@ static char_u *do_one_cmd(char_u **cmdlinep, int flags, cstack_T *cstack, LineGe if (!ni && !(ea.argt & EX_RANGE) && ea.addr_count > 0) { // no range allowed - errormsg = (char_u *)_(e_norange); + errormsg = _(e_norange); goto doend; } } if (!ni && !(ea.argt & EX_BANG) && ea.forceit) { // no <!> allowed - errormsg = (char_u *)_(e_nobang); + errormsg = _(e_nobang); goto doend; } @@ -1565,7 +1565,7 @@ static char_u *do_one_cmd(char_u **cmdlinep, int flags, cstack_T *cstack, LineGe if (!global_busy && ea.line1 > ea.line2) { if (msg_silent == 0) { if ((flags & DOCMD_VERBOSE) || exmode_active) { - errormsg = (char_u *)_("E493: Backwards range given"); + errormsg = _("E493: Backwards range given"); goto doend; } if (ask_yesno(_("Backwards range given, OK to swap"), false) != 'y') { @@ -1627,7 +1627,7 @@ static char_u *do_one_cmd(char_u **cmdlinep, int flags, cstack_T *cstack, LineGe if (ea.argt & EX_ARGOPT) { while (ea.arg[0] == '+' && ea.arg[1] == '+') { if (getargopt(&ea) == FAIL && !ni) { - errormsg = (char_u *)_(e_invarg); + errormsg = _(e_invarg); goto doend; } } @@ -1636,7 +1636,7 @@ static char_u *do_one_cmd(char_u **cmdlinep, int flags, cstack_T *cstack, LineGe if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) { if (*ea.arg == '>') { // append if (*++ea.arg != '>') { // typed wrong - errormsg = (char_u *)_("E494: Use w or w>>"); + errormsg = _("E494: Use w or w>>"); goto doend; } ea.arg = skipwhite(ea.arg + 1); @@ -1755,7 +1755,7 @@ static char_u *do_one_cmd(char_u **cmdlinep, int flags, cstack_T *cstack, LineGe case ADDR_NONE: case ADDR_UNSIGNED: case ADDR_QUICKFIX: - IEMSG(_("INTERNAL: Cannot use EX_DFLALL " + iemsg(_("INTERNAL: Cannot use EX_DFLALL " "with ADDR_NONE, ADDR_UNSIGNED or ADDR_QUICKFIX")); break; } @@ -1789,7 +1789,7 @@ static char_u *do_one_cmd(char_u **cmdlinep, int flags, cstack_T *cstack, LineGe n = getdigits_long(&ea.arg, false, -1); ea.arg = skipwhite(ea.arg); if (n <= 0 && !ni && (ea.argt & EX_ZEROR) == 0) { - errormsg = (char_u *)_(e_zerocount); + errormsg = _(e_zerocount); goto doend; } if (ea.addr_type != ADDR_LINES) { // e.g. :buffer 2, :sleep 3 @@ -1817,12 +1817,12 @@ static char_u *do_one_cmd(char_u **cmdlinep, int flags, cstack_T *cstack, LineGe if (!ni && !(ea.argt & EX_EXTRA) && *ea.arg != NUL && *ea.arg != '"' && (*ea.arg != '|' || (ea.argt & EX_TRLBAR) == 0)) { // no arguments allowed but there is something - errormsg = (char_u *)_(e_trailing); + errormsg = _(e_trailing); goto doend; } if (!ni && (ea.argt & EX_NEEDARG) && *ea.arg == NUL) { - errormsg = (char_u *)_(e_argreq); + errormsg = _(e_argreq); goto doend; } @@ -1982,7 +1982,7 @@ static char_u *do_one_cmd(char_u **cmdlinep, int flags, cstack_T *cstack, LineGe ea.errmsg = NULL; (cmdnames[ea.cmdidx].cmd_func)(&ea); if (ea.errmsg != NULL) { - errormsg = (char_u *)_(ea.errmsg); + errormsg = _(ea.errmsg); } } @@ -2014,9 +2014,9 @@ doend: if (errormsg != NULL && *errormsg != NUL && !did_emsg) { if (flags & DOCMD_VERBOSE) { - if (errormsg != IObuff) { + if (errormsg != (char *)IObuff) { STRCPY(IObuff, errormsg); - errormsg = IObuff; + errormsg = (char *)IObuff; } append_command(*cmdlinep); } @@ -2056,7 +2056,7 @@ doend: // "cmdmod". // Return FAIL when the command is not to be executed. // May set "errormsg" to an error message. -int parse_command_modifiers(exarg_T *eap, char_u **errormsg, bool skip_only) +int parse_command_modifiers(exarg_T *eap, char **errormsg, bool skip_only) { char_u *p; @@ -2260,7 +2260,7 @@ int parse_command_modifiers(exarg_T *eap, char_u **errormsg, bool skip_only) cmdmod.tab = tabpage_index(curtab) + 1; } else { if (tabnr < 0 || tabnr > LAST_TAB_NR) { - *errormsg = (char_u *)_(e_invrange); + *errormsg = _(e_invrange); return false; } cmdmod.tab = tabnr + 1; @@ -2356,7 +2356,7 @@ static void undo_cmdmod(const exarg_T *eap, int save_msg_scroll) // Parse the address range, if any, in "eap". // May set the last search pattern, unless "silent" is true. // Return FAIL and set "errormsg" or return OK. -int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent) +int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent) FUNC_ATTR_NONNULL_ALL { int address_count = 1; @@ -2443,14 +2443,14 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent) } else { // there is no Vim command which uses '%' and // ADDR_WINDOWS or ADDR_TABS - *errormsg = (char_u *)_(e_invrange); + *errormsg = _(e_invrange); return FAIL; } break; case ADDR_TABS_RELATIVE: case ADDR_UNSIGNED: case ADDR_QUICKFIX: - *errormsg = (char_u *)_(e_invrange); + *errormsg = _(e_invrange); return FAIL; case ADDR_ARGUMENTS: if (ARGCOUNT == 0) { @@ -2475,7 +2475,7 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent) } else if (*eap->cmd == '*') { // '*' - visual area if (eap->addr_type != ADDR_LINES) { - *errormsg = (char_u *)_(e_invrange); + *errormsg = _(e_invrange); return FAIL; } @@ -2565,7 +2565,7 @@ static void append_command(char_u *cmd) STRCPY(d, "<a0>"); d += 4; } else { - MB_COPY_CHAR(s, d); + mb_copy_char((const char_u **)&s, &d); } } *d = NUL; @@ -2880,8 +2880,8 @@ int cmd_exists(const char *const name) } } - /* Check built-in commands and user defined commands. - * For ":2match" and ":3match" we need to skip the number. */ + // Check built-in commands and user defined commands. + // For ":2match" and ":3match" we need to skip the number. ea.cmd = (char_u *)((*name == '2' || *name == '3') ? name + 1 : name); ea.cmdidx = (cmdidx_T)0; int full = false; @@ -2915,6 +2915,7 @@ const char *set_one_cmd_context(expand_T *xp, const char *buff) ExpandInit(xp); xp->xp_pattern = (char_u *)buff; + xp->xp_line = (char_u *)buff; xp->xp_context = EXPAND_COMMANDS; // Default until we get past command ea.argt = 0; @@ -3828,9 +3829,9 @@ char_u *skip_range(const char_u *cmd, int *ctx) static void addr_error(cmd_addr_T addr_type) { if (addr_type == ADDR_NONE) { - EMSG(_(e_norange)); + emsg(_(e_norange)); } else { - EMSG(_(e_invrange)); + emsg(_(e_invrange)); } } @@ -3963,8 +3964,8 @@ static linenr_T get_address(exarg_T *eap, char_u **ptr, cmd_addr_T addr_type, in if (skip) { ++cmd; } else { - /* Only accept a mark in another file when it is - * used by itself: ":'M". */ + // Only accept a mark in another file when it is + // used by itself: ":'M". fp = getmark(*cmd, to_other_file && cmd[1] == NUL); ++cmd; if (fp == (pos_T *)-1) { @@ -4041,7 +4042,7 @@ static linenr_T get_address(exarg_T *eap, char_u **ptr, cmd_addr_T addr_type, in } else if (*cmd == '?' || *cmd == '/') { i = RE_SEARCH; } else { - EMSG(_(e_backslash)); + emsg(_(e_backslash)); cmd = NULL; goto error; } @@ -4124,7 +4125,7 @@ static linenr_T get_address(exarg_T *eap, char_u **ptr, cmd_addr_T addr_type, in } if (addr_type == ADDR_TABS_RELATIVE) { - EMSG(_(e_invrange)); + emsg(_(e_invrange)); cmd = NULL; goto error; } else if (addr_type == ADDR_LOADED_BUFFERS || addr_type == ADDR_BUFFERS) { @@ -4171,7 +4172,7 @@ static void get_flags(exarg_T *eap) void ex_ni(exarg_T *eap) { if (!eap->skip) { - eap->errmsg = (char_u *)N_("E319: The command is not available in this version"); + eap->errmsg = N_("E319: The command is not available in this version"); } } @@ -4191,11 +4192,11 @@ static void ex_script_ni(exarg_T *eap) * Check range in Ex command for validity. * Return NULL when valid, error message when invalid. */ -static char_u *invalid_range(exarg_T *eap) +static char *invalid_range(exarg_T *eap) { buf_T *buf; if (eap->line1 < 0 || eap->line2 < 0 || eap->line1 > eap->line2) { - return (char_u *)_(e_invrange); + return _(e_invrange); } if (eap->argt & EX_RANGE) { @@ -4203,51 +4204,51 @@ static char_u *invalid_range(exarg_T *eap) case ADDR_LINES: if (eap->line2 > (curbuf->b_ml.ml_line_count + (eap->cmdidx == CMD_diffget))) { - return (char_u *)_(e_invrange); + return _(e_invrange); } break; case ADDR_ARGUMENTS: // add 1 if ARGCOUNT is 0 if (eap->line2 > ARGCOUNT + (!ARGCOUNT)) { - return (char_u *)_(e_invrange); + return _(e_invrange); } break; case ADDR_BUFFERS: if (eap->line1 < firstbuf->b_fnum || eap->line2 > lastbuf->b_fnum) { - return (char_u *)_(e_invrange); + return _(e_invrange); } break; case ADDR_LOADED_BUFFERS: buf = firstbuf; while (buf->b_ml.ml_mfp == NULL) { if (buf->b_next == NULL) { - return (char_u *)_(e_invrange); + return _(e_invrange); } buf = buf->b_next; } if (eap->line1 < buf->b_fnum) { - return (char_u *)_(e_invrange); + return _(e_invrange); } buf = lastbuf; while (buf->b_ml.ml_mfp == NULL) { if (buf->b_prev == NULL) { - return (char_u *)_(e_invrange); + return _(e_invrange); } buf = buf->b_prev; } if (eap->line2 > buf->b_fnum) { - return (char_u *)_(e_invrange); + return _(e_invrange); } break; case ADDR_WINDOWS: if (eap->line2 > LAST_WIN_NR) { - return (char_u *)_(e_invrange); + return _(e_invrange); } break; case ADDR_TABS: if (eap->line2 > LAST_TAB_NR) { - return (char_u *)_(e_invrange); + return _(e_invrange); } break; case ADDR_TABS_RELATIVE: @@ -4258,13 +4259,13 @@ static char_u *invalid_range(exarg_T *eap) assert(eap->line2 >= 0); // No error for value that is too big, will use the last entry. if (eap->line2 <= 0) { - return (char_u *)_(e_invrange); + return _(e_invrange); } break; case ADDR_QUICKFIX_VALID: if ((eap->line2 != 1 && (size_t)eap->line2 > qf_get_valid_size(eap)) || eap->line2 < 0) { - return (char_u *)_(e_invrange); + return _(e_invrange); } break; case ADDR_UNSIGNED: @@ -4386,7 +4387,7 @@ static char_u *replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep) // Expand file name in Ex command argument. // When an error is detected, "errormsgp" is set to a non-NULL pointer. // Return FAIL for failure, OK otherwise. -int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp) +int expand_filename(exarg_T *eap, char_u **cmdlinep, char **errormsgp) { int has_wildcards; // need to expand wildcards char_u *repl; @@ -4444,11 +4445,10 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp) xfree(l); } - /* Need to escape white space et al. with a backslash. - * Don't do this for: - * - replacement that already has been escaped: "##" - * - shell commands (may have to use quotes instead). - */ + // Need to escape white space et al. with a backslash. + // Don't do this for: + // - replacement that already has been escaped: "##" + // - shell commands (may have to use quotes instead). if (!eap->usefilter && !escaped && eap->cmdidx != CMD_bang @@ -4794,8 +4794,8 @@ static int getargopt(exarg_T *eap) *p = TOLOWER_ASC(*p); } } else { - /* Check ++bad= argument. Must be a single-byte character, "keep" or - * "drop". */ + // Check ++bad= argument. Must be a single-byte character, "keep" or + // "drop". if (get_bad_opt(eap->cmd + bad_char_idx, eap) == FAIL) { return FAIL; } @@ -5116,23 +5116,16 @@ static int check_more(int message, bool forceit) if ((p_confirm || cmdmod.confirm) && curbuf->b_fname != NULL) { char_u buff[DIALOG_MSG_SIZE]; - if (n == 1) { - STRLCPY(buff, _("1 more file to edit. Quit anyway?"), - DIALOG_MSG_SIZE); - } else { - vim_snprintf((char *)buff, DIALOG_MSG_SIZE, - _("%d more files to edit. Quit anyway?"), n); - } + vim_snprintf((char *)buff, DIALOG_MSG_SIZE, + NGETTEXT("%d more file to edit. Quit anyway?", + "%d more files to edit. Quit anyway?", (unsigned long)n), n); if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 1) == VIM_YES) { return OK; } return FAIL; } - if (n == 1) { - EMSG(_("E173: 1 more file to edit")); - } else { - EMSGN(_("E173: %" PRId64 " more files to edit"), n); - } + semsg(NGETTEXT("E173: %" PRId64 " more file to edit", + "E173: %" PRId64 " more files to edit", (unsigned long)n), (int64_t)n); quitmore = 2; // next try to quit is allowed } return FAIL; @@ -5199,7 +5192,7 @@ static int uc_add_command(char_u *name, size_t name_len, char_u *rep, uint32_t a if (!force && (cmd->uc_script_ctx.sc_sid != current_sctx.sc_sid || cmd->uc_script_ctx.sc_seq == current_sctx.sc_seq)) { - EMSG2(_("E174: Command already exists: add ! to replace it: %s"), + semsg(_("E174: Command already exists: add ! to replace it: %s"), name); goto fail; } @@ -5347,7 +5340,7 @@ static void uc_list(char_u *name, size_t name_len) // Put out the title first time if (!found) { - MSG_PUTS_TITLE(_("\n Name Args Address " + msg_puts_title(_("\n Name Args Address " "Complete Definition")); } found = true; @@ -5482,7 +5475,7 @@ static void uc_list(char_u *name, size_t name_len) } if (!found) { - MSG(_("No user-defined commands found")); + msg(_("No user-defined commands found")); } } @@ -5493,7 +5486,7 @@ static int uc_scan_attr(char_u *attr, size_t len, uint32_t *argt, long *def, int char_u *p; if (len == 0) { - EMSG(_("E175: No attribute specified")); + emsg(_("E175: No attribute specified")); return FAIL; } @@ -5539,7 +5532,7 @@ static int uc_scan_attr(char_u *attr, size_t len, uint32_t *argt, long *def, int } } else { wrong_nargs: - EMSG(_("E176: Invalid number of arguments")); + emsg(_("E176: Invalid number of arguments")); return FAIL; } } else if (STRNICMP(attr, "range", attrlen) == 0) { @@ -5550,7 +5543,7 @@ wrong_nargs: p = val; if (*def >= 0) { two_count: - EMSG(_("E177: Count cannot be specified twice")); + emsg(_("E177: Count cannot be specified twice")); return FAIL; } @@ -5559,7 +5552,7 @@ two_count: if (p != val + vallen || vallen == 0) { invalid_count: - EMSG(_("E178: Invalid default value for count")); + emsg(_("E178: Invalid default value for count")); return FAIL; } } @@ -5592,7 +5585,7 @@ invalid_count: } } else if (STRNICMP(attr, "complete", attrlen) == 0) { if (val == NULL) { - EMSG(_("E179: argument required for -complete")); + emsg(_("E179: argument required for -complete")); return FAIL; } @@ -5603,7 +5596,7 @@ invalid_count: } else if (STRNICMP(attr, "addr", attrlen) == 0) { *argt |= EX_RANGE; if (val == NULL) { - EMSG(_("E179: argument required for -addr")); + emsg(_("E179: argument required for -addr")); return FAIL; } if (parse_addr_type_arg(val, (int)vallen, addr_type_arg) == FAIL) { @@ -5615,7 +5608,7 @@ invalid_count: } else { char_u ch = attr[len]; attr[len] = '\0'; - EMSG2(_("E181: Invalid attribute: %s"), attr); + semsg(_("E181: Invalid attribute: %s"), attr); attr[len] = ch; return FAIL; } @@ -5664,7 +5657,7 @@ static void ex_command(exarg_T *eap) } } if (!ends_excmd(*p) && !ascii_iswhite(*p)) { - EMSG(_("E182: Invalid command name")); + emsg(_("E182: Invalid command name")); return; } end = p; @@ -5676,11 +5669,11 @@ static void ex_command(exarg_T *eap) if (!has_attr && ends_excmd(*p)) { uc_list(name, end - name); } else if (!ASCII_ISUPPER(*name)) { - EMSG(_("E183: User defined commands must start with an uppercase letter")); + emsg(_("E183: User defined commands must start with an uppercase letter")); } else if (name_len <= 4 && STRNCMP(name, "Next", name_len) == 0) { - EMSG(_("E841: Reserved name, cannot be used for user defined command")); + emsg(_("E841: Reserved name, cannot be used for user defined command")); } else if (compl > 0 && (argt & EX_EXTRA) == 0) { - EMSG(_(e_complete_used_without_nargs)); + emsg(_(e_complete_used_without_nargs)); } else { uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg, addr_type_arg, eap->forceit); @@ -5697,7 +5690,8 @@ void ex_comclear(exarg_T *eap) uc_clear(&curbuf->b_ucmds); } -static void free_ucmd(ucmd_T *cmd) { +static void free_ucmd(ucmd_T *cmd) +{ xfree(cmd->uc_name); xfree(cmd->uc_rep); xfree(cmd->uc_compl_arg); @@ -5734,7 +5728,7 @@ static void ex_delcommand(exarg_T *eap) } if (cmp != 0) { - EMSG2(_("E184: No such user-defined command: %s"), eap->arg); + semsg(_("E184: No such user-defined command: %s"), eap->arg); return; } @@ -5812,7 +5806,7 @@ static char_u *uc_split_args(char_u *arg, size_t *lenp) *q++ = ','; *q++ = '"'; } else { - MB_COPY_CHAR(p, q); + mb_copy_char((const char_u **)&p, &q); } } *q++ = '"'; @@ -5868,7 +5862,7 @@ static size_t uc_check_code(char_u *code, size_t len, char_u *buf, ucmd_T *cmd, ct_MODS, ct_REGISTER, ct_LT, - ct_NONE + ct_NONE, } type = ct_NONE; if ((vim_strchr((char_u *)"qQfF", *p) != NULL) && p[1] == '-') { @@ -6339,7 +6333,7 @@ int parse_addr_type_arg(char_u *value, int vallen, cmd_addr_T *addr_type_arg) for (i = 0; err[i] != NUL && !ascii_iswhite(err[i]); i++) {} err[i] = NUL; - EMSG2(_("E180: Invalid address type value: %s"), err); + semsg(_("E180: Invalid address type value: %s"), err); return FAIL; } @@ -6389,19 +6383,19 @@ int parse_compl_arg(const char_u *value, int vallen, int *complp, uint32_t *argt } if (i == (int)ARRAY_SIZE(command_complete)) { - EMSG2(_("E180: Invalid complete value: %s"), value); + semsg(_("E180: Invalid complete value: %s"), value); return FAIL; } if (*complp != EXPAND_USER_DEFINED && *complp != EXPAND_USER_LIST && arg != NULL) { - EMSG(_("E468: Completion argument only allowed for custom completion")); + emsg(_("E468: Completion argument only allowed for custom completion")); return FAIL; } if ((*complp == EXPAND_USER_DEFINED || *complp == EXPAND_USER_LIST) && arg == NULL) { - EMSG(_("E467: Custom completion requires a function argument")); + emsg(_("E467: Custom completion requires a function argument")); return FAIL; } @@ -6438,20 +6432,20 @@ static void ex_colorscheme(exarg_T *eap) xfree(expr); if (p != NULL) { - MSG(p); + msg((char *)p); xfree(p); } else { - MSG("default"); + msg("default"); } } else if (load_colors(eap->arg) == FAIL) { - EMSG2(_("E185: Cannot find color scheme '%s'"), eap->arg); + semsg(_("E185: Cannot find color scheme '%s'"), eap->arg); } } static void ex_highlight(exarg_T *eap) { if (*eap->arg == NUL && eap->cmd[2] == '!') { - MSG(_("Greetings, Vim user!")); + msg(_("Greetings, Vim user!")); } do_highlight((const char *)eap->arg, eap->forceit, false); } @@ -6648,7 +6642,7 @@ void ex_win_close(int forceit, win_T *win, tabpage_T *tp) // Never close the autocommand window. if (win == aucmd_win) { - EMSG(_(e_autocmd_close)); + emsg(_(e_autocmd_close)); return; } @@ -6688,7 +6682,7 @@ static void ex_tabclose(exarg_T *eap) if (cmdwin_type != 0) { cmdwin_result = K_IGNORE; } else if (first_tabpage->tp_next == NULL) { - EMSG(_("E784: Cannot close last tab page")); + emsg(_("E784: Cannot close last tab page")); } else { int tab_number = get_tabpage_arg(eap); if (eap->errmsg == NULL) { @@ -6713,7 +6707,7 @@ static void ex_tabonly(exarg_T *eap) if (cmdwin_type != 0) { cmdwin_result = K_IGNORE; } else if (first_tabpage->tp_next == NULL) { - MSG(_("Already only one tab page")); + msg(_("Already only one tab page")); } else { int tab_number = get_tabpage_arg(eap); if (eap->errmsg == NULL) { @@ -6772,15 +6766,15 @@ void tabpage_close_other(tabpage_T *tp, int forceit) int h = tabline_height(); char_u prev_idx[NUMBUFLEN]; - /* Limit to 1000 windows, autocommands may add a window while we close - * one. OK, so I'm paranoid... */ + // Limit to 1000 windows, autocommands may add a window while we close + // one. OK, so I'm paranoid... while (++done < 1000) { snprintf((char *)prev_idx, sizeof(prev_idx), "%i", tabpage_index(tp)); wp = tp->tp_lastwin; ex_win_close(forceit, wp, tp); - /* Autocommands may delete the tab page under our fingers and we may - * fail to close a window with a modified buffer. */ + // Autocommands may delete the tab page under our fingers and we may + // fail to close a window with a modified buffer. if (!valid_tabpage(tp) || tp->tp_firstwin == wp) { break; } @@ -6918,7 +6912,7 @@ static void ex_exit(exarg_T *eap) static void ex_print(exarg_T *eap) { if (curbuf->b_ml.ml_flags & ML_EMPTY) { - EMSG(_(e_emptybuf)); + emsg(_(e_emptybuf)); } else { for (; !got_int; os_breakcheck()) { print_line(eap->line1, @@ -7032,7 +7026,7 @@ void alist_set(alist_T *al, int count, char_u **files, int use_curbuf, int *fnum static int recursive = 0; if (recursive) { - EMSG(_(e_au_recursive)); + emsg(_(e_au_recursive)); return; } recursive++; @@ -7166,8 +7160,8 @@ void ex_splitview(exarg_T *eap) || eap->cmdidx == CMD_tabfind || eap->cmdidx == CMD_tabnew; - /* A ":split" in the quickfix window works like ":new". Don't want two - * quickfix windows. But it's OK when doing ":tab split". */ + // A ":split" in the quickfix window works like ":new". Don't want two + // quickfix windows. But it's OK when doing ":tab split". if (bt_quickfix(curbuf) && cmdmod.tab == 0) { if (eap->cmdidx == CMD_split) { eap->cmdidx = CMD_new; @@ -7207,8 +7201,7 @@ void ex_splitview(exarg_T *eap) *eap->cmd == 'v' ? WSP_VERT : 0) != FAIL) { // Reset 'scrollbind' when editing another file, but keep it when // doing ":split" without arguments. - if (*eap->arg != NUL - ) { + if (*eap->arg != NUL) { RESET_BINDING(curwin); } else { do_check_scrollbind(false); @@ -7353,7 +7346,7 @@ static void ex_mode(exarg_T *eap) must_redraw = CLEAR; ex_redraw(eap); } else { - EMSG(_(e_screenmode)); + emsg(_(e_screenmode)); } } @@ -7369,7 +7362,6 @@ static void ex_resize(exarg_T *eap) if (eap->addr_count > 0) { n = eap->line2; for (wp = firstwin; wp->w_next != NULL && --n > 0; wp = wp->w_next) { - ; } } @@ -7514,18 +7506,18 @@ void do_exedit(exarg_T *eap, win_T *old_curwin) enter_cleanup(&cs); win_close(curwin, !need_hide && !buf_hide(curbuf)); - /* Restore the error/interrupt/exception state if not - * discarded by a new aborting error, interrupt, or - * uncaught exception. */ + // Restore the error/interrupt/exception state if not + // discarded by a new aborting error, interrupt, or + // uncaught exception. leave_cleanup(&cs); } } } else if (readonlymode && curbuf->b_nwindows == 1) { - /* When editing an already visited buffer, 'readonly' won't be set - * but the previous value is kept. With ":view" and ":sview" we - * want the file to be readonly, except when another window is - * editing the same buffer. */ - curbuf->b_p_ro = TRUE; + // When editing an already visited buffer, 'readonly' won't be set + // but the previous value is kept. With ":view" and ":sview" we + // want the file to be readonly, except when another window is + // editing the same buffer. + curbuf->b_p_ro = true; } readonlymode = n; } else { @@ -7558,17 +7550,16 @@ void do_exedit(exarg_T *eap, win_T *old_curwin) /// ":gui" and ":gvim" when there is no GUI. static void ex_nogui(exarg_T *eap) { - eap->errmsg = (char_u *)N_("E25: Nvim does not have a built-in GUI"); + eap->errmsg = N_("E25: Nvim does not have a built-in GUI"); } - static void ex_swapname(exarg_T *eap) { if (curbuf->b_ml.ml_mfp == NULL || curbuf->b_ml.ml_mfp->mf_fname == NULL) { - MSG(_("No swap file")); + msg(_("No swap file")); } else { - msg(curbuf->b_ml.ml_mfp->mf_fname); + msg((char *)curbuf->b_ml.ml_mfp->mf_fname); } } @@ -7671,7 +7662,7 @@ static void ex_read(exarg_T *eap) } if (i != OK) { if (!aborting()) { - EMSG2(_(e_notopen), eap->arg); + semsg(_(e_notopen), eap->arg); } } else { if (empty && exmode_active) { @@ -7787,7 +7778,7 @@ bool changedir_func(char_u *new_dir, CdScope scope) if (STRCMP(new_dir, "-") == 0) { pdir = get_prevdir(scope); if (pdir == NULL) { - EMSG(_("E186: No previous directory")); + emsg(_("E186: No previous directory")); return false; } new_dir = pdir; @@ -7827,7 +7818,7 @@ bool changedir_func(char_u *new_dir, CdScope scope) post_chdir(scope, dir_differs); retval = true; } else { - EMSG(_(e_failed)); + emsg(_(e_failed)); } xfree(tofree); @@ -7886,10 +7877,10 @@ static void ex_pwd(exarg_T *eap) } smsg("[%s] %s", context, (char *)NameBuff); } else { - msg(NameBuff); + msg((char *)NameBuff); } } else { - EMSG(_("E187: Unknown")); + emsg(_("E187: Unknown")); } } @@ -7921,7 +7912,7 @@ static void ex_sleep(exarg_T *eap) case NUL: len *= 1000L; break; default: - EMSG2(_(e_invarg2), eap->arg); return; + semsg(_(e_invarg2), eap->arg); return; } do_sleep(len); } @@ -7956,10 +7947,10 @@ static void do_exmap(exarg_T *eap, int isabbrev) switch (do_map((*cmdp == 'n') ? 2 : (*cmdp == 'u'), eap->arg, mode, isabbrev)) { case 1: - EMSG(_(e_invarg)); + emsg(_(e_invarg)); break; case 2: - EMSG(isabbrev ? _(e_noabbr) : _(e_nomap)); + emsg(isabbrev ? _(e_noabbr) : _(e_nomap)); break; } } @@ -7972,7 +7963,7 @@ static void ex_winsize(exarg_T *eap) char_u *arg = eap->arg; if (!ascii_isdigit(*arg)) { - EMSG2(_(e_invarg2), arg); + semsg(_(e_invarg2), arg); return; } int w = getdigits_int(&arg, false, 10); @@ -7982,7 +7973,7 @@ static void ex_winsize(exarg_T *eap) if (*p != NUL && *arg == NUL) { screen_resize(w, h); } else { - EMSG(_("E465: :winsize requires two number arguments")); + emsg(_("E465: :winsize requires two number arguments")); } } @@ -7994,7 +7985,7 @@ static void ex_wincmd(exarg_T *eap) if (*eap->arg == 'g' || *eap->arg == Ctrl_G) { // CTRL-W g and CTRL-W CTRL-G have an extra command character if (eap->arg[1] == NUL) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } xchar = eap->arg[1]; @@ -8006,7 +7997,7 @@ static void ex_wincmd(exarg_T *eap) eap->nextcmd = check_nextcmd(p); p = skipwhite(p); if (*p != NUL && *p != '"' && eap->nextcmd == NULL) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } else if (!eap->skip) { // Pass flags on for ":vertical wincmd ]". postponed_split_flags = cmdmod.split; @@ -8054,8 +8045,7 @@ static void ex_operators(exarg_T *eap) default: // CMD_rshift or CMD_lshift if ( - (eap->cmdidx == CMD_rshift) ^ curwin->w_p_rl - ) { + (eap->cmdidx == CMD_rshift) ^ curwin->w_p_rl) { oa.op_type = OP_RSHIFT; } else { oa.op_type = OP_LSHIFT; @@ -8098,7 +8088,7 @@ static void ex_copymove(exarg_T *eap) * move or copy lines from 'eap->line1'-'eap->line2' to below line 'n' */ if (n == MAXLNUM || n < 0 || n > curbuf->b_ml.ml_line_count) { - EMSG(_(e_invrange)); + emsg(_(e_invrange)); return; } @@ -8264,7 +8254,7 @@ static void ex_later(exarg_T *eap) } if (*p != NUL) { - EMSG2(_(e_invarg2), eap->arg); + semsg(_(e_invarg2), eap->arg); } else { undo_time(eap->cmdidx == CMD_earlier ? -count : count, sec, file, false); @@ -8325,7 +8315,7 @@ static void ex_redir(exarg_T *eap) } if (*arg != NUL) { redir_reg = 0; - EMSG2(_(e_invarg2), eap->arg); + semsg(_(e_invarg2), eap->arg); } } else if (*arg == '=' && arg[1] == '>') { int append; @@ -8347,7 +8337,7 @@ static void ex_redir(exarg_T *eap) } // TODO: redirect to a buffer else { - EMSG2(_(e_invarg2), eap->arg); + semsg(_(e_invarg2), eap->arg); } } @@ -8456,7 +8446,7 @@ int vim_mkdir_emsg(const char *const name, const int prot) { int ret; if ((ret = os_mkdir(name, prot)) != 0) { - EMSG3(_(e_mkdir), name, os_strerror(ret)); + semsg(_(e_mkdir), name, os_strerror(ret)); return FAIL; } return OK; @@ -8474,17 +8464,17 @@ FILE *open_exfile(char_u *fname, int forceit, char *mode) #ifdef UNIX // with Unix it is possible to open a directory if (os_isdir(fname)) { - EMSG2(_(e_isadir2), fname); + semsg(_(e_isadir2), fname); return NULL; } #endif if (!forceit && *mode != 'a' && os_path_exists(fname)) { - EMSG2(_("E189: \"%s\" exists (add ! to override)"), fname); + semsg(_("E189: \"%s\" exists (add ! to override)"), fname); return NULL; } if ((fd = os_fopen((char *)fname, mode)) == NULL) { - EMSG2(_("E190: Cannot open \"%s\" for writing"), fname); + semsg(_("E190: Cannot open \"%s\" for writing"), fname); } return fd; @@ -8498,15 +8488,15 @@ static void ex_mark(exarg_T *eap) pos_T pos; if (*eap->arg == NUL) { // No argument? - EMSG(_(e_argreq)); + emsg(_(e_argreq)); } else if (eap->arg[1] != NUL) { // more than one character? - EMSG(_(e_trailing)); + emsg(_(e_trailing)); } else { pos = curwin->w_cursor; // save curwin->w_cursor curwin->w_cursor.lnum = eap->line2; beginline(BL_WHITE | BL_FIX); if (setmark(*eap->arg) == FAIL) { // set mark - EMSG(_("E191: Argument must be a letter or forward/backward quote")); + emsg(_("E191: Argument must be a letter or forward/backward quote")); } curwin->w_cursor = pos; // restore curwin->w_cursor } @@ -8584,7 +8574,7 @@ void restore_current_state(save_state_T *sst) static void ex_normal(exarg_T *eap) { if (curbuf->terminal && State & TERM_FOCUS) { - EMSG("Can't re-enter normal mode from terminal mode"); + emsg("Can't re-enter normal mode from terminal mode"); return; } save_state_T save_state; @@ -8593,11 +8583,11 @@ static void ex_normal(exarg_T *eap) char_u *p; if (ex_normal_lock > 0) { - EMSG(_(e_secure)); + emsg(_(e_secure)); return; } if (ex_normal_busy >= p_mmd) { - EMSG(_("E192: Recursive use of :normal too deep")); + emsg(_("E192: Recursive use of :normal too deep")); return; } @@ -8608,8 +8598,8 @@ static void ex_normal(exarg_T *eap) int len = 0; // Count the number of characters to be escaped. - for (p = eap->arg; *p != NUL; ++p) { - for (l = (*mb_ptr2len)(p) - 1; l > 0; --l) { + for (p = eap->arg; *p != NUL; p++) { + for (l = utfc_ptr2len(p) - 1; l > 0; l--) { if (*++p == K_SPECIAL // trailbyte K_SPECIAL or CSI ) { len += 2; @@ -8621,7 +8611,7 @@ static void ex_normal(exarg_T *eap) len = 0; for (p = eap->arg; *p != NUL; ++p) { arg[len++] = *p; - for (l = (*mb_ptr2len)(p) - 1; l > 0; --l) { + for (l = utfc_ptr2len(p) - 1; l > 0; l--) { arg[len++] = *++p; if (*p == K_SPECIAL) { arg[len++] = KS_SPECIAL; @@ -8994,7 +8984,7 @@ ssize_t find_cmdline_var(const char_u *src, size_t *usedlen) /// Returns NULL if no match was found. "usedlen" then still contains the /// number of characters to skip. char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnump, - char_u **errormsg, int *escaped) + char **errormsg, int *escaped) { int i; char_u *s; @@ -9044,7 +9034,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum ? (FIND_IDENT | FIND_STRING | FIND_EVAL) : FIND_STRING)); if (resultlen == 0) { - *errormsg = (char_u *)""; + *errormsg = ""; return NULL; } // @@ -9097,7 +9087,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum result = (char_u *)tv_list_find_str(get_vim_var_list(VV_OLDFILES), i - 1); if (result == NULL) { - *errormsg = (char_u *)""; + *errormsg = ""; return NULL; } } else { @@ -9106,7 +9096,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum } buf = buflist_findnr(i); if (buf == NULL) { - *errormsg = (char_u *)_("E194: No alternate file name to substitute for '#'"); + *errormsg = _("E194: No alternate file name to substitute for '#'"); return NULL; } if (lnump != NULL) { @@ -9125,7 +9115,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum case SPEC_CFILE: // file name under cursor result = file_name_at_cursor(FNAME_MESS|FNAME_HYP, 1L, NULL); if (result == NULL) { - *errormsg = (char_u *)""; + *errormsg = ""; return NULL; } resultbuf = result; // remember allocated string @@ -9145,7 +9135,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum } result = autocmd_fname; if (result == NULL) { - *errormsg = (char_u *)_("E495: no autocommand file name to substitute for \"<afile>\""); + *errormsg = _("E495: no autocommand file name to substitute for \"<afile>\""); return NULL; } result = path_try_shorten_fname(result); @@ -9153,7 +9143,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum case SPEC_ABUF: // buffer number for autocommand if (autocmd_bufnr <= 0) { - *errormsg = (char_u *)_("E496: no autocommand buffer number to substitute for \"<abuf>\""); + *errormsg = _("E496: no autocommand buffer number to substitute for \"<abuf>\""); return NULL; } snprintf(strbuf, sizeof(strbuf), "%d", autocmd_bufnr); @@ -9163,7 +9153,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum case SPEC_AMATCH: // match name for autocommand result = autocmd_match; if (result == NULL) { - *errormsg = (char_u *)_("E497: no autocommand match name to substitute for \"<amatch>\""); + *errormsg = _("E497: no autocommand match name to substitute for \"<amatch>\""); return NULL; } break; @@ -9171,14 +9161,14 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum case SPEC_SFILE: // file name for ":so" command result = sourcing_name; if (result == NULL) { - *errormsg = (char_u *)_("E498: no :source file name to substitute for \"<sfile>\""); + *errormsg = _("E498: no :source file name to substitute for \"<sfile>\""); return NULL; } break; case SPEC_SLNUM: // line in file for ":so" command if (sourcing_name == NULL || sourcing_lnum == 0) { - *errormsg = (char_u *)_("E842: no line number to use for \"<slnum>\""); + *errormsg = _("E842: no line number to use for \"<slnum>\""); return NULL; } snprintf(strbuf, sizeof(strbuf), "%" PRIdLINENR, sourcing_lnum); @@ -9187,7 +9177,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum case SPEC_SFLNUM: // line in script file if (current_sctx.sc_lnum + sourcing_lnum == 0) { - *errormsg = (char_u *)_("E961: no line number to use for \"<sflnum>\""); + *errormsg = _("E961: no line number to use for \"<sflnum>\""); return NULL; } snprintf((char *)strbuf, sizeof(strbuf), "%" PRIdLINENR, @@ -9197,7 +9187,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum case SPEC_SID: if (current_sctx.sc_sid <= 0) { - *errormsg = (char_u *)_(e_usingsid); + *errormsg = _(e_usingsid); return NULL; } snprintf(strbuf, sizeof(strbuf), "<SNR>%" PRIdSCID "_", @@ -9207,7 +9197,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum default: // should not happen - *errormsg = (char_u *)""; + *errormsg = ""; result = (char_u *)""; // avoid gcc warning break; } @@ -9224,7 +9214,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum valid |= modify_fname(src, tilde_file, usedlen, &result, &resultbuf, &resultlen); if (result == NULL) { - *errormsg = (char_u *)""; + *errormsg = ""; return NULL; } } @@ -9233,9 +9223,9 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum if (resultlen == 0 || valid != VALID_HEAD + VALID_PATH) { if (valid != VALID_HEAD + VALID_PATH) { // xgettext:no-c-format - *errormsg = (char_u *)_("E499: Empty file name for '%' or '#', only works with \":p:h\""); + *errormsg = _("E499: Empty file name for '%' or '#', only works with \":p:h\""); } else { - *errormsg = (char_u *)_("E500: Evaluates to an empty string"); + *errormsg = _("E500: Evaluates to an empty string"); } result = NULL; } else { @@ -9315,7 +9305,7 @@ static char_u *arg_all(void) */ char_u *expand_sfile(char_u *arg) { - char_u *errormsg; + char *errormsg; size_t len; char_u *result; char_u *newres; @@ -9405,7 +9395,7 @@ static void ex_behave(exarg_T *eap) set_option_value("mousemodel", 0L, "extend", 0); set_option_value("keymodel", 0L, "", 0); } else { - EMSG2(_(e_invarg2), eap->arg); + semsg(_(e_invarg2), eap->arg); } } @@ -9516,7 +9506,7 @@ static void ex_filetype(exarg_T *eap) filetype_detect = kFalse; } } else { - EMSG2(_(e_invarg2), arg); + semsg(_(e_invarg2), arg); } } @@ -9604,7 +9594,7 @@ static void ex_match(exarg_T *eap) if (eap->line2 <= 3) { id = eap->line2; } else { - EMSG(e_invcmd); + emsg(e_invcmd); return; } @@ -9627,7 +9617,7 @@ static void ex_match(exarg_T *eap) if (*p == NUL) { // There must be two arguments. xfree(g); - EMSG2(_(e_invarg2), eap->arg); + semsg(_(e_invarg2), eap->arg); return; } end = skip_regexp(p + 1, *p, true, NULL); @@ -9639,7 +9629,7 @@ static void ex_match(exarg_T *eap) } if (*end != *p) { xfree(g); - EMSG2(_(e_invarg2), p); + semsg(_(e_invarg2), p); return; } @@ -9717,7 +9707,7 @@ static void ex_terminal(exarg_T *eap) xfree(name); } else { // No {cmd}: run the job with tokenized 'shell'. if (*p_sh == NUL) { - EMSG(_(e_shellempty)); + emsg(_(e_shellempty)); return; } @@ -9874,287 +9864,287 @@ void verify_command(char_u *cmd) if (strcmp("smile", (char *)cmd)) { return; // acceptable non-existing command } - MSG(" #xxn` #xnxx` ,+x@##@Mz;` .xxx" + msg(" #xxn` #xnxx` ,+x@##@Mz;` .xxx" "xxxxxxnz+, znnnnnnnnnnnnnnnn."); - MSG(" n###z x####` :x##########W+` ,###" + msg(" n###z x####` :x##########W+` ,###" "##########M; W################."); - MSG(" n####; x####` `z##############W: ,###" + msg(" n####; x####` `z##############W: ,###" "############# W################."); - MSG(" n####W. x####` ,W#################+ ,###" + msg(" n####W. x####` ,W#################+ ,###" "############## W################."); - MSG(" n#####n x####` @################### ,###" + msg(" n#####n x####` @################### ,###" "##############i W################."); - MSG(" n######i x####` .#########@W@########* ,###" + msg(" n######i x####` .#########@W@########* ,###" "##############W`W################."); - MSG(" n######@. x####` x######W*. `;n#######: ,###" + msg(" n######@. x####` x######W*. `;n#######: ,###" "#x,,,,:*M######iW###@:,,,,,,,,,,,`"); - MSG(" n#######n x####` *######+` :M#####M ,###" + msg(" n#######n x####` *######+` :M#####M ,###" "#n `x#####xW###@`"); - MSG(" n########* x####``@####@; `x#####i ,###" + msg(" n########* x####``@####@; `x#####i ,###" "#n ,#####@W###@`"); - MSG(" n########@ x####`*#####i `M####M ,###" + msg(" n########@ x####`*#####i `M####M ,###" "#n x#########@`"); - MSG(" n######### x####`M####z :#####:,###" + msg(" n######### x####`M####z :#####:,###" "#n z#########@`"); - MSG(" n#########* x####,#####. n####+,###" + msg(" n#########* x####,#####. n####+,###" "#n n#########@`"); - MSG(" n####@####@, x####i####x ;####x,###" + msg(" n####@####@, x####i####x ;####x,###" "#n `W#####@####+++++++++++i"); - MSG(" n####*#####M` x#########* `####@,###" + msg(" n####*#####M` x#########* `####@,###" "#n i#####MW###############W"); - MSG(" n####.######+ x####z####; W####,###" + msg(" n####.######+ x####z####; W####,###" "#n i@######W###############W"); - MSG(" n####.`W#####: x####n####: M####:###" + msg(" n####.`W#####: x####n####: M####:###" "#@nnnnnW#######,W###############W"); - MSG(" n####. :#####M`x####z####; W####,###" + msg(" n####. :#####M`x####z####; W####,###" "##############z W###############W"); - MSG(" n####. #######x#########* `####W,###" + msg(" n####. #######x#########* `####W,###" "#############W` W###############W"); - MSG(" n####. `M#####W####i####x ;####x,###" + msg(" n####. `M#####W####i####x ;####x,###" "############W, W####+**********i"); - MSG(" n####. ,##########,#####. n####+,###" + msg(" n####. ,##########,#####. n####+,###" "###########n. W###@`"); - MSG(" n####. ##########`M####z :#####:,###" + msg(" n####. ##########`M####z :#####:,###" "########Wz: W###@`"); - MSG(" n####. x#########`*#####i `M####M ,###" + msg(" n####. x#########`*#####i `M####M ,###" "#x.....` W###@`"); - MSG(" n####. ,@########``@####@; `x#####i ,###" + msg(" n####. ,@########``@####@; `x#####i ,###" "#n W###@`"); - MSG(" n####. *########` *#####@+` ,M#####M ,###" + msg(" n####. *########` *#####@+` ,M#####M ,###" "#n W###@`"); - MSG(" n####. x#######` x######W*. `;n######@: ,###" + msg(" n####. x#######` x######W*. `;n######@: ,###" "#n W###@,,,,,,,,,,,,`"); - MSG(" n####. .@######` .#########@W@########* ,###" + msg(" n####. .@######` .#########@W@########* ,###" "#n W################,"); - MSG(" n####. i######` @################### ,###" + msg(" n####. i######` @################### ,###" "#n W################,"); - MSG(" n####. n#####` ,W#################+ ,###" + msg(" n####. n#####` ,W#################+ ,###" "#n W################,"); - MSG(" n####. .@####` .n##############W; ,###" + msg(" n####. .@####` .n##############W; ,###" "#n W################,"); - MSG(" n####. i####` :x##########W+` ,###" + msg(" n####. i####` :x##########W+` ,###" "#n W################,"); - MSG(" +nnnn` +nnn` ,+x@##@Mz;` .nnn" + msg(" +nnnn` +nnn` ,+x@##@Mz;` .nnn" "n+ zxxxxxxxxxxxxxxxx."); - MSG(" "); - MSG(" " + msg(" "); + msg(" " " ,+M@#Mi"); - MSG(" " + msg(" " " .z########"); - MSG(" " + msg(" " " i@#########i"); - MSG(" " + msg(" " " `############W`"); - MSG(" " + msg(" " " `n#############i"); - MSG(" " + msg(" " " `n##############n"); - MSG(" `` " + msg(" `` " " z###############@`"); - MSG(" `W@z, " + msg(" `W@z, " " ##################,"); - MSG(" *#####` " + msg(" *#####` " " i############@x@###i"); - MSG(" ######M. " + msg(" ######M. " " :#############n`,W##+"); - MSG(" +######@: " + msg(" +######@: " " .W#########M@##+ *##z"); - MSG(" :#######@: " + msg(" :#######@: " " `x########@#x###* ,##n"); - MSG(" `@#######@; " + msg(" `@#######@; " " z#########M*@nW#i .##x"); - MSG(" z########@i " + msg(" z########@i " " *###########WM#@#, `##x"); - MSG(" i##########+ " + msg(" i##########+ " " ;###########*n###@ `##x"); - MSG(" `@#MM#######x, " + msg(" `@#MM#######x, " " ,@#########zM,`z##M `@#x"); - MSG(" n##M#W#######n. " + msg(" n##M#W#######n. " " `.:i*+#zzzz##+i:.` ,W#########Wii,`n@#@` n@##n"); - MSG(" ;###@#x#######n `,i" + msg(" ;###@#x#######n `,i" "#nW@#####@@WWW@@####@Mzi. ,W##########@z.. ;zM#+i####z"); - MSG(" x####nz######## .;#x@##" + msg(" x####nz######## .;#x@##" "@Wn#*;,.` ``,:*#x@##M+, ;@########xz@WM+#` `n@#######"); - MSG(" ,@####M########xi#@##@Mzi," + msg(" ,@####M########xi#@##@Mzi," "` .+x###Mi:n##########Mz```.:i *@######*"); - MSG(" *#####W#########ix+:` " + msg(" *#####W#########ix+:` " " :n#############z: `*.`M######i"); - MSG(" i#W##nW@+@##@#M@; " + msg(" i#W##nW@+@##@#M@; " " ;W@@##########W, i`x@#####,"); - MSG(" `@@n@Wn#@iMW*#*: " + msg(" `@@n@Wn#@iMW*#*: " " `iz#z@######x. M######`"); - MSG(" z##zM###x`*, .` " + msg(" z##zM###x`*, .` " " `iW#####W;:` +#####M"); - MSG(" ,###nn##n` " + msg(" ,###nn##n` " " ,#####x;` ,;@######"); - MSG(" x###xz#. " + msg(" x###xz#. " " in###+ `:######@."); - MSG(" ;####n+ " + msg(" ;####n+ " " `Mnx##xi` , zM#######"); - MSG(" `W####+ " + msg(" `W####+ " "i. `.+x###@#. :n,z######:"); - MSG(" z####@` ;" + msg(" z####@` ;" "#: .ii@###@;.*M*z####@`"); - MSG(" i####M ` `i@" + msg(" i####M ` `i@" "#, :: +#n##@+@##W####n"); - MSG(" :####x ,i. ##xzM###" + msg(" :####x ,i. ##xzM###" "@` i. .@@, .z####x#######*"); - MSG(" ,###W; i##Wz########" + msg(" ,###W; i##Wz########" "# :## z##n ,@########x###:"); - MSG(" n##n `W###########M" + msg(" n##n `W###########M" "`;n, i#x ,###@i *W########W#@`"); - MSG(" .@##+ `x###########@." + msg(" .@##+ `x###########@." " z#+ .M#W``x#####n` `;#######@z#x"); - MSG(" n###z :W############@ " + msg(" n###z :W############@ " " z#* @##xM#######@n; `########nW+"); - MSG(" ;####nW##############W " + msg(" ;####nW##############W " ":@#* `@#############* :########z@i`"); - MSG(" M##################### " + msg(" M##################### " "M##: @#############@: *W########M#"); - MSG(" ;#####################i." + msg(" ;#####################i." "##x` W#############W, :n########zx"); - MSG(" x####################@.`" + msg(" x####################@.`" "x; @#############z. .@########W#"); - MSG(" ,######################` " + msg(" ,######################` " " W###############x*,` W######zM#i"); - MSG(" #######################: " + msg(" #######################: " " z##################@x+*#zzi `@#########."); - MSG(" W########W#z#M#########; " + msg(" W########W#z#M#########; " " *##########################z :@#######@`"); - MSG(" `@#######x`;#z ,x#######; " + msg(" `@#######x`;#z ,x#######; " " z###########M###xnM@########* :M######@"); - MSG(" i########, x#@` z######; " + msg(" i########, x#@` z######; " " *##########i *#@` `+########+` n######."); - MSG(" n#######@` M##, `W#####. " + msg(" n#######@` M##, `W#####. " " *#########z ###; z########M: :W####n"); - MSG(" M#######M n##. x####x " + msg(" M#######M n##. x####x " " `x########: z##+ M#########@; .n###+"); - MSG(" W#######@` :#W `@####: " + msg(" W#######@` :#W `@####: " " `@######W i### ;###########@. n##n"); - MSG(" W########z` ,, .x####z " + msg(" W########z` ,, .x####z " " @######@` `W#; `W############* *###;"); - MSG(" `@#########Mi,:*n@####W` " + msg(" `@#########Mi,:*n@####W` " " W#######* .. `n#############i i###x"); - MSG(" .#####################z " + msg(" .#####################z " " `@#######@*` .x############n:` ;####."); - MSG(" :####################x`,,` " + msg(" :####################x`,,` " " `W#########@x#+#@#############i ,####:"); - MSG(" ;###################x#@###x" + msg(" ;###################x#@###x" "i` *############################: `####i"); - MSG(" i##################+#######" + msg(" i##################+#######" "#M, x##########################@` W###i"); - MSG(" *################@; @######" + msg(" *################@; @######" "##@, .W#########################@ x###:"); - MSG(" .+M#############z. M######" + msg(" .+M#############z. M######" "###x ,W########################@` ####."); - MSG(" *M*;z@########x: :W#####" + msg(" *M*;z@########x: :W#####" "##i .M########################i i###:"); - MSG(" *##@z;#@####x: :z###" + msg(" *##@z;#@####x: :z###" "@i `########################x .###;"); - MSG(" *#####n;#@## ;##" + msg(" *#####n;#@## ;##" "* ,x#####################@` W##*"); - MSG(" *#######n;* :M##" + msg(" *#######n;* :M##" "W*, *W####################` n##z"); - MSG(" i########@. ,*n####" + msg(" i########@. ,*n####" "###M*` `###################M *##M"); - MSG(" i########n `z#####@@" + msg(" i########n `z#####@@" "#####Wi ,M################; ,##@`"); - MSG(" ;WMWW@###* .x##@ni.``" + msg(" ;WMWW@###* .x##@ni.``" ".:+zW##z` `n##############z @##,"); - MSG(" .*++*i;;;. .M#@+` " + msg(" .*++*i;;;. .M#@+` " " .##n `x############x` n##i"); - MSG(" :########* x#W, " + msg(" :########* x#W, " " *#+ *###########M` +##+"); - MSG(" ,######### :#@: " + msg(" ,######### :#@: " " ##: #nzzzzzzzzzz. :##x"); - MSG(" .#####Wz+` ##+ " + msg(" .#####Wz+` ##+ " " `MM` .znnnnnnnnn. `@#@`"); - MSG(" `@@ni;*nMz` @W` " + msg(" `@@ni;*nMz` @W` " " :#+ .x#######n x##,"); - MSG(" i;z@#####, .#* " + msg(" i;z@#####, .#* " " z#: ;;;*zW##; ###i"); - MSG(" z########: :#; " + msg(" z########: :#; " " `Wx +###Wni;n. ;##z"); - MSG(" n########W: .#* " + msg(" n########W: .#* " " ,#, ;#######@+ `@#M"); - MSG(" .###########n;.MM " + msg(" .###########n;.MM " " n* ;iM#######* x#@`"); - MSG(" :#############@;; " + msg(" :#############@;; " " .n` ,#W*iW#####W` +##,"); - MSG(" ,##############. " + msg(" ,##############. " " ix. `x###M;####### ,##i"); - MSG(" .#############@` " + msg(" .#############@` " " x@n**#W######z;M###@. W##"); - MSG(" .##############W: " + msg(" .##############W: " " .x############@*;zW#; z#x"); - MSG(" ,###############@; " + msg(" ,###############@; " " `##############@n*;. i#@"); - MSG(" ,#################i " + msg(" ,#################i " " :n##############W` .##,"); - MSG(" ,###################` " + msg(" ,###################` " " .+W##########W, `##i"); - MSG(" :###################@zi,` " + msg(" :###################@zi,` " " ;zM@@@WMn*` @#z"); - MSG(" :#######################@x+" + msg(" :#######################@x+" "*i;;:i#M, `` M#W"); - MSG(" ;##########################" + msg(" ;##########################" "######@x. n##,"); - MSG(" i#####################@W@@@" + msg(" i#####################@W@@@" "@Wxz*:` *##+"); - MSG(" *######################+```" + msg(" *######################+```" " :##M"); - MSG(" ########################M; " + msg(" ########################M; " " `@##,"); - MSG(" z#########################x" + msg(" z#########################x" ", z###"); - MSG(" n##########################" + msg(" n##########################" "#n: ;##W`"); - MSG(" x##########################" + msg(" x##########################" "###Mz#++##* `W##i"); - MSG(" M##########################" + msg(" M##########################" "##########@` ###x"); - MSG(" W##########################" + msg(" W##########################" "###########` .###,"); - MSG(" @##########################" + msg(" @##########################" "##########M n##z"); - MSG(" @##################z*i@WMMM" + msg(" @##################z*i@WMMM" "x#x@#####,. :##@."); - MSG(" `#####################@xi` " + msg(" `#####################@xi` " " `::,* x##+"); - MSG(" .#####################@#M. " + msg(" .#####################@#M. " " ;##@`"); - MSG(" ,#####################:. " + msg(" ,#####################:. " " M##i"); - MSG(" ;###################ni` " + msg(" ;###################ni` " " i##M"); - MSG(" *#################W#` " + msg(" *#################W#` " " `W##,"); - MSG(" z#################@Wx+. " + msg(" z#################@Wx+. " " +###"); - MSG(" x######################z. " + msg(" x######################z. " " .@#@`"); - MSG(" `@#######################@; " + msg(" `@#######################@; " " z##;"); - MSG(" :##########################: " + msg(" :##########################: " " :##z"); - MSG(" +#########################W# " + msg(" +#########################W# " " M#W"); - MSG(" W################@n+*i;:,` " + msg(" W################@n+*i;:,` " " +##,"); - MSG(" :##################WMxz+, " + msg(" :##################WMxz+, " " ,##i"); - MSG(" n#######################W.., " + msg(" n#######################W.., " " W##"); - MSG(" +#########################WW@+. .:. " + msg(" +#########################WW@+. .:. " " z#x"); - MSG(" `@#############################@@###: " + msg(" `@#############################@@###: " " *#W"); - MSG(" #################################Wz: " + msg(" #################################Wz: " " :#@"); - MSG(",@###############################i " + msg(",@###############################i " " .##"); - MSG("n@@@@@@@#########################+ " + msg("n@@@@@@@#########################+ " " `##"); - MSG("` `.:.`.,:iii;;;;;;;;iii;;;:` `.`` " + msg("` `.:.`.,:iii;;;;;;;;iii;;;:` `.`` " " `nW"); } diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index 09a1350f17..cfc8eb7316 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -254,12 +254,12 @@ bool cause_errthrow(const char_u *mesg, bool severe, bool *ignore) } elem = xmalloc(sizeof(struct msglist)); - elem->msg = vim_strsave(mesg); + elem->msg = (char *)vim_strsave(mesg); elem->next = NULL; elem->throw_msg = NULL; *plist = elem; if (plist == msg_list || severe) { - char_u *tmsg; + char *tmsg; // Skip the extra "Vim " prefix for message "E458". tmsg = elem->msg; @@ -387,28 +387,28 @@ int do_intthrow(cstack_T *cstack) } // 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 *get_exception_string(void *value, except_type_T type, char_u *cmdname, int *should_free) { - char_u *ret, *mesg; - char_u *p, *val; + char *ret, *mesg; + char *p, *val; if (type == ET_ERROR) { *should_free = true; mesg = ((struct msglist *)value)->throw_msg; if (cmdname != NULL && *cmdname != NUL) { size_t cmdlen = STRLEN(cmdname); - ret = vim_strnsave((char_u *)"Vim(", 4 + cmdlen + 2 + STRLEN(mesg)); + ret = (char *)vim_strnsave((char_u *)"Vim(", 4 + cmdlen + 2 + STRLEN(mesg)); STRCPY(&ret[4], cmdname); STRCPY(&ret[4 + cmdlen], "):"); val = ret + 4 + cmdlen + 2; } else { - ret = vim_strnsave((char_u *)"Vim:", 4 + STRLEN(mesg)); + ret = (char *)vim_strnsave((char_u *)"Vim:", 4 + STRLEN(mesg)); val = ret + 4; } - /* msg_add_fname may have been used to prefix the message with a file - * name in quotes. In the exception value, put the file name in - * parentheses and move it to the end. */ + // msg_add_fname may have been used to prefix the message with a file + // name in quotes. In the exception value, put the file name in + // parentheses and move it to the end. for (p = mesg;; p++) { if (*p == NUL || (*p == 'E' @@ -438,7 +438,7 @@ char_u *get_exception_string(void *value, except_type_T type, char_u *cmdname, i } } else { *should_free = FALSE; - ret = (char_u *)value; + ret = value; } return ret; @@ -463,7 +463,7 @@ static int throw_exception(void *value, except_type_T type, char_u *cmdname) if (STRNCMP((char_u *)value, "Vim", 3) == 0 && (((char_u *)value)[3] == NUL || ((char_u *)value)[3] == ':' || ((char_u *)value)[3] == '(')) { - EMSG(_("E608: Cannot :throw exceptions with 'Vim' prefix")); + emsg(_("E608: Cannot :throw exceptions with 'Vim' prefix")); goto fail; } } @@ -518,7 +518,7 @@ static int throw_exception(void *value, except_type_T type, char_u *cmdname) nomem: xfree(excp); suppress_errthrow = true; - EMSG(_(e_outofmem)); + emsg(_(e_outofmem)); fail: current_exception = NULL; return FAIL; @@ -835,7 +835,7 @@ void ex_if(exarg_T *eap) cstack_T *const cstack = eap->cstack; if (cstack->cs_idx == CSTACK_LEN - 1) { - eap->errmsg = (char_u *)N_("E579: :if nesting too deep"); + eap->errmsg = N_("E579: :if nesting too deep"); } else { ++cstack->cs_idx; cstack->cs_flags[cstack->cs_idx] = 0; @@ -865,7 +865,7 @@ void ex_endif(exarg_T *eap) if (eap->cstack->cs_idx < 0 || (eap->cstack->cs_flags[eap->cstack->cs_idx] & (CSF_WHILE | CSF_FOR | CSF_TRY))) { - eap->errmsg = (char_u *)N_("E580: :endif without :if"); + eap->errmsg = N_("E580: :endif without :if"); } else { // When debugging or a breakpoint was encountered, display the debug // prompt (if not already done). This shows the user that an ":endif" @@ -898,17 +898,17 @@ void ex_else(exarg_T *eap) || (cstack->cs_flags[cstack->cs_idx] & (CSF_WHILE | CSF_FOR | CSF_TRY))) { if (eap->cmdidx == CMD_else) { - eap->errmsg = (char_u *)N_("E581: :else without :if"); + eap->errmsg = N_("E581: :else without :if"); return; } - eap->errmsg = (char_u *)N_("E582: :elseif without :if"); + eap->errmsg = N_("E582: :elseif without :if"); skip = TRUE; } else if (cstack->cs_flags[cstack->cs_idx] & CSF_ELSE) { if (eap->cmdidx == CMD_else) { - eap->errmsg = (char_u *)N_("E583: multiple :else"); + eap->errmsg = N_("E583: multiple :else"); return; } - eap->errmsg = (char_u *)N_("E584: :elseif after :else"); + eap->errmsg = N_("E584: :elseif after :else"); skip = TRUE; } @@ -922,16 +922,14 @@ void ex_else(exarg_T *eap) cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE; } - /* - * When debugging or a breakpoint was encountered, display the debug prompt - * (if not already done). This shows the user that an ":else" or ":elseif" - * is executed when the ":if" or previous ":elseif" was not TRUE. Handle - * a ">quit" debug command as if an interrupt had occurred before the - * ":else" or ":elseif". That is, set "skip" and throw an interrupt - * exception if appropriate. Doing this here prevents that an exception - * for a parsing errors is discarded when throwing the interrupt exception - * later on. - */ + // When debugging or a breakpoint was encountered, display the debug prompt + // (if not already done). This shows the user that an ":else" or ":elseif" + // is executed when the ":if" or previous ":elseif" was not TRUE. Handle + // a ">quit" debug command as if an interrupt had occurred before the + // ":else" or ":elseif". That is, set "skip" and throw an interrupt + // exception if appropriate. Doing this here prevents that an exception + // for a parsing errors is discarded when throwing the interrupt exception + // later on. if (!skip && dbg_check_skipped(eap) && got_int) { (void)do_intthrow(cstack); skip = TRUE; @@ -972,7 +970,7 @@ void ex_while(exarg_T *eap) cstack_T *const cstack = eap->cstack; if (cstack->cs_idx == CSTACK_LEN - 1) { - eap->errmsg = (char_u *)N_("E585: :while/:for nesting too deep"); + eap->errmsg = N_("E585: :while/:for nesting too deep"); } else { /* * The loop flag is set when we have jumped back from the matching @@ -1053,13 +1051,13 @@ void ex_continue(exarg_T *eap) cstack_T *const cstack = eap->cstack; if (cstack->cs_looplevel <= 0 || cstack->cs_idx < 0) { - eap->errmsg = (char_u *)N_("E586: :continue without :while or :for"); + eap->errmsg = N_("E586: :continue without :while or :for"); } else { - /* Try to find the matching ":while". This might stop at a try - * conditional not in its finally clause (which is then to be executed - * next). Therefore, deactivate all conditionals except the ":while" - * itself (if reached). */ - idx = cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, FALSE); + // Try to find the matching ":while". This might stop at a try + // conditional not in its finally clause (which is then to be executed + // next). Therefore, deactivate all conditionals except the ":while" + // itself (if reached). + idx = cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, false); assert(idx >= 0); if (cstack->cs_flags[idx] & (CSF_WHILE | CSF_FOR)) { rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel); @@ -1070,8 +1068,8 @@ void ex_continue(exarg_T *eap) */ cstack->cs_lflags |= CSL_HAD_CONT; // let do_cmdline() handle it } else { - /* If a try conditional not in its finally clause is reached first, - * make the ":continue" pending for execution at the ":endtry". */ + // If a try conditional not in its finally clause is reached first, + // make the ":continue" pending for execution at the ":endtry". cstack->cs_pending[idx] = CSTP_CONTINUE; report_make_pending(CSTP_CONTINUE, NULL); } @@ -1087,12 +1085,12 @@ void ex_break(exarg_T *eap) cstack_T *const cstack = eap->cstack; if (cstack->cs_looplevel <= 0 || cstack->cs_idx < 0) { - eap->errmsg = (char_u *)N_("E587: :break without :while or :for"); + eap->errmsg = N_("E587: :break without :while or :for"); } else { // Deactivate conditionals until the matching ":while" or a try // conditional not in its finally clause (which is then to be // executed next) is found. In the latter case, make the ":break" - // pending for execution at the ":endtry". */ + // pending for execution at the ":endtry". idx = cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, true); if (idx >= 0 && !(cstack->cs_flags[idx] & (CSF_WHILE | CSF_FOR))) { cstack->cs_pending[idx] = CSTP_BREAK; @@ -1108,7 +1106,7 @@ void ex_endwhile(exarg_T *eap) { cstack_T *const cstack = eap->cstack; int idx; - char_u *err; + char *err; int csf; int fl; @@ -1128,9 +1126,9 @@ void ex_endwhile(exarg_T *eap) // If we are in a ":while" or ":for" but used the wrong endloop // command, do not rewind to the next enclosing ":for"/":while". if (fl & CSF_WHILE) { - eap->errmsg = (char_u *)_("E732: Using :endfor with :while"); + eap->errmsg = _("E732: Using :endfor with :while"); } else if (fl & CSF_FOR) { - eap->errmsg = (char_u *)_("E733: Using :endwhile with :for"); + eap->errmsg = _("E733: Using :endwhile with :for"); } } if (!(fl & (CSF_WHILE | CSF_FOR))) { @@ -1155,20 +1153,17 @@ void ex_endwhile(exarg_T *eap) // Cleanup and rewind all contained (and unclosed) conditionals. (void)cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, FALSE); rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel); - } - /* - * When debugging or a breakpoint was encountered, display the debug - * prompt (if not already done). This shows the user that an - * ":endwhile"/":endfor" is executed when the ":while" was not TRUE or - * after a ":break". Handle a ">quit" debug command as if an - * interrupt had occurred before the ":endwhile"/":endfor". That is, - * throw an interrupt exception if appropriate. Doing this here - * prevents that an exception for a parsing error is discarded when - * throwing the interrupt exception later on. - */ - else if (cstack->cs_flags[cstack->cs_idx] & CSF_TRUE - && !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE) - && dbg_check_skipped(eap)) { + } else if (cstack->cs_flags[cstack->cs_idx] & CSF_TRUE + && !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE) + && dbg_check_skipped(eap)) { + // When debugging or a breakpoint was encountered, display the debug + // prompt (if not already done). This shows the user that an + // ":endwhile"/":endfor" is executed when the ":while" was not TRUE or + // after a ":break". Handle a ">quit" debug command as if an + // interrupt had occurred before the ":endwhile"/":endfor". That is, + // throw an interrupt exception if appropriate. Doing this here + // prevents that an exception for a parsing error is discarded when + // throwing the interrupt exception later on. (void)do_intthrow(cstack); } @@ -1193,7 +1188,7 @@ void ex_throw(exarg_T *eap) value = eval_to_string_skip(arg, (const char **)&eap->nextcmd, (bool)eap->skip); } else { - EMSG(_(e_argreq)); + emsg(_(e_argreq)); value = NULL; } @@ -1278,7 +1273,7 @@ void ex_try(exarg_T *eap) cstack_T *const cstack = eap->cstack; if (cstack->cs_idx == CSTACK_LEN - 1) { - eap->errmsg = (char_u *)N_("E601: :try nesting too deep"); + eap->errmsg = N_("E601: :try nesting too deep"); } else { ++cstack->cs_idx; ++cstack->cs_trylevel; @@ -1339,7 +1334,7 @@ void ex_catch(exarg_T *eap) char_u *pat; if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) { - eap->errmsg = (char_u *)N_("E603: :catch without :try"); + eap->errmsg = N_("E603: :catch without :try"); give_up = TRUE; } else { if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) { @@ -1354,9 +1349,9 @@ void ex_catch(exarg_T *eap) } } if (cstack->cs_flags[idx] & CSF_FINALLY) { - /* Give up for a ":catch" after ":finally" and ignore it. - * Just parse. */ - eap->errmsg = (char_u *)N_("E604: :catch after :finally"); + // Give up for a ":catch" after ":finally" and ignore it. + // Just parse. + eap->errmsg = N_("E604: :catch after :finally"); give_up = TRUE; } else { rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, @@ -1391,20 +1386,20 @@ void ex_catch(exarg_T *eap) if (!skip && (cstack->cs_flags[idx] & CSF_THROWN) && !(cstack->cs_flags[idx] & CSF_CAUGHT)) { if (end != NULL && *end != NUL && !ends_excmd(*skipwhite(end + 1))) { - EMSG(_(e_trailing)); + emsg(_(e_trailing)); return; } - /* When debugging or a breakpoint was encountered, display the - * debug prompt (if not already done) before checking for a match. - * This is a helpful hint for the user when the regular expression - * matching fails. Handle a ">quit" debug command as if an - * interrupt had occurred before the ":catch". That is, discard - * the original exception, replace it by an interrupt exception, - * and don't catch it in this try block. */ + // When debugging or a breakpoint was encountered, display the + // debug prompt (if not already done) before checking for a match. + // This is a helpful hint for the user when the regular expression + // matching fails. Handle a ">quit" debug command as if an + // interrupt had occurred before the ":catch". That is, discard + // the original exception, replace it by an interrupt exception, + // and don't catch it in this try block. if (!dbg_check_skipped(eap) || !do_intthrow(cstack)) { - /* Terminate the pattern and avoid the 'l' flag in 'cpoptions' - * while compiling it. */ + // Terminate the pattern and avoid the 'l' flag in 'cpoptions' + // while compiling it. if (end != NULL) { save_char = *end; *end = NUL; @@ -1422,7 +1417,7 @@ void ex_catch(exarg_T *eap) } p_cpo = save_cpo; if (regmatch.regprog == NULL) { - EMSG2(_(e_invarg2), pat); + semsg(_(e_invarg2), pat); } else { // // Save the value of got_int and reset it. We don't want @@ -1431,7 +1426,7 @@ void ex_catch(exarg_T *eap) // prev_got_int = got_int; got_int = FALSE; - caught = vim_regexec_nl(®match, current_exception->value, + caught = vim_regexec_nl(®match, (char_u *)current_exception->value, (colnr_T)0); got_int |= prev_got_int; vim_regfree(regmatch.regprog); @@ -1440,16 +1435,16 @@ void ex_catch(exarg_T *eap) } if (caught) { - /* Make this ":catch" clause active and reset did_emsg and got_int. - * Put the exception on the caught stack. */ + // Make this ":catch" clause active and reset did_emsg and got_int. + // Put the exception on the caught stack. cstack->cs_flags[idx] |= CSF_ACTIVE | CSF_CAUGHT; did_emsg = got_int = false; catch_exception((except_T *)cstack->cs_exception[idx]); - /* It's mandatory that the current exception is stored in the cstack - * so that it can be discarded at the next ":catch", ":finally", or - * ":endtry" or when the catch clause is left by a ":continue", - * ":break", ":return", ":finish", error, interrupt, or another - * exception. */ + // It's mandatory that the current exception is stored in the cstack + // so that it can be discarded at the next ":catch", ":finally", or + // ":endtry" or when the catch clause is left by a ":continue", + // ":break", ":return", ":finish", error, interrupt, or another + // exception. if (cstack->cs_exception[cstack->cs_idx] != current_exception) { internal_error("ex_catch()"); } @@ -1488,7 +1483,7 @@ void ex_finally(exarg_T *eap) cstack_T *const cstack = eap->cstack; if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) { - eap->errmsg = (char_u *)N_("E606: :finally without :try"); + eap->errmsg = N_("E606: :finally without :try"); } else { if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) { eap->errmsg = get_end_emsg(cstack); @@ -1507,7 +1502,7 @@ void ex_finally(exarg_T *eap) if (cstack->cs_flags[idx] & CSF_FINALLY) { // Give up for a multiple ":finally" and ignore it. - eap->errmsg = (char_u *)N_("E607: multiple :finally"); + eap->errmsg = N_("E607: multiple :finally"); return; } rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, @@ -1576,13 +1571,13 @@ void ex_finally(exarg_T *eap) assert(pending >= CHAR_MIN && pending <= CHAR_MAX); cstack->cs_pending[cstack->cs_idx] = (char)pending; - /* It's mandatory that the current exception is stored in the - * cstack so that it can be rethrown at the ":endtry" or be - * discarded if the finally clause is left by a ":continue", - * ":break", ":return", ":finish", error, interrupt, or another - * exception. When emsg() is called for a missing ":endif" or - * a missing ":endwhile"/":endfor" detected here, the - * exception will be discarded. */ + // It's mandatory that the current exception is stored in the + // cstack so that it can be rethrown at the ":endtry" or be + // discarded if the finally clause is left by a ":continue", + // ":break", ":return", ":finish", error, interrupt, or another + // exception. When emsg() is called for a missing ":endif" or + // a missing ":endwhile"/":endfor" detected here, the + // exception will be discarded. if (current_exception && cstack->cs_exception[cstack->cs_idx] != current_exception) { internal_error("ex_finally()"); @@ -1614,7 +1609,7 @@ void ex_endtry(exarg_T *eap) cstack_T *const cstack = eap->cstack; if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) { - eap->errmsg = (char_u *)N_("E602: :endtry without :try"); + eap->errmsg = N_("E602: :endtry without :try"); } else { // Don't do something after an error, interrupt or throw in the try // block, catch clause, or finally clause preceding this ":endtry" or @@ -1633,8 +1628,9 @@ void ex_endtry(exarg_T *eap) eap->errmsg = get_end_emsg(cstack); // Find the matching ":try" and report what's missing. idx = cstack->cs_idx; - do + do{ --idx; + } while (idx > 0 && !(cstack->cs_flags[idx] & CSF_TRY)); rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, &cstack->cs_looplevel); @@ -1666,21 +1662,20 @@ void ex_endtry(exarg_T *eap) } } - /* If there was no finally clause, show the user when debugging or - * a breakpoint was encountered that the end of the try conditional has - * been reached: display the debug prompt (if not already done). Do - * this on normal control flow or when an exception was thrown, but not - * on an interrupt or error not converted to an exception or when - * a ":break", ":continue", ":return", or ":finish" is pending. These - * actions are carried out immediately. - */ + // If there was no finally clause, show the user when debugging or + // a breakpoint was encountered that the end of the try conditional has + // been reached: display the debug prompt (if not already done). Do + // this on normal control flow or when an exception was thrown, but not + // on an interrupt or error not converted to an exception or when + // a ":break", ":continue", ":return", or ":finish" is pending. These + // actions are carried out immediately. if ((rethrow || (!skip && !(cstack->cs_flags[idx] & CSF_FINALLY) && !cstack->cs_pending[idx])) && dbg_check_skipped(eap)) { - /* Handle a ">quit" debug command as if an interrupt had occurred - * before the ":endtry". That is, throw an interrupt exception and - * set "skip" and "rethrow". */ + // Handle a ">quit" debug command as if an interrupt had occurred + // before the ":endtry". That is, throw an interrupt exception and + // set "skip" and "rethrow". if (got_int) { skip = TRUE; (void)do_intthrow(cstack); @@ -1815,13 +1810,12 @@ void enter_cleanup(cleanup_T *csp) | (current_exception ? CSTP_THROW : 0) | (need_rethrow ? CSTP_THROW : 0); - /* If we are currently throwing an exception, save it as well. On an error - * not yet converted to an exception, update "force_abort" and reset - * "cause_abort" (as do_errthrow() would do). This is needed for the - * do_cmdline() call that is going to be made for autocommand execution. We - * need not save *msg_list because there is an extra instance for every call - * of do_cmdline(), anyway. - */ + // If we are currently throwing an exception, save it as well. On an error + // not yet converted to an exception, update "force_abort" and reset + // "cause_abort" (as do_errthrow() would do). This is needed for the + // do_cmdline() call that is going to be made for autocommand execution. We + // need not save *msg_list because there is an extra instance for every call + // of do_cmdline(), anyway. if (current_exception || need_rethrow) { csp->exception = current_exception; current_exception = NULL; @@ -1897,13 +1891,10 @@ void leave_cleanup(cleanup_T *csp) */ if (pending & CSTP_THROW) { current_exception = csp->exception; - } - /* - * If an error was about to be converted to an exception when - * enter_cleanup() was called, let "cause_abort" take the part of - * "force_abort" (as done by cause_errthrow()). - */ - else if (pending & CSTP_ERROR) { + } else if (pending & CSTP_ERROR) { + // If an error was about to be converted to an exception when + // enter_cleanup() was called, let "cause_abort" take the part of + // "force_abort" (as done by cause_errthrow()). cause_abort = force_abort; force_abort = FALSE; } @@ -2052,7 +2043,7 @@ int cleanup_conditionals(cstack_T *cstack, int searched_cond, int inclusive) /* * Return an appropriate error message for a missing endwhile/endfor/endif. */ -static char_u *get_end_emsg(cstack_T *cstack) +static char *get_end_emsg(cstack_T *cstack) { if (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE) { return e_endwhile; @@ -2089,7 +2080,7 @@ void rewind_conditionals(cstack_T *cstack, int idx, int cond_type, int *cond_lev */ void ex_endfunction(exarg_T *eap) { - EMSG(_("E193: :endfunction not inside a function")); + emsg(_("E193: :endfunction not inside a function")); } /* diff --git a/src/nvim/ex_eval.h b/src/nvim/ex_eval.h index d3ba43a469..25b30b2805 100644 --- a/src/nvim/ex_eval.h +++ b/src/nvim/ex_eval.h @@ -40,8 +40,8 @@ * message in the list. See cause_errthrow() below. */ struct msglist { - char_u *msg; // original message - char_u *throw_msg; // msg to throw: usually original one + char *msg; // original message + char *throw_msg; // msg to throw: usually original one struct msglist *next; // next of several messages in a row }; @@ -60,7 +60,7 @@ typedef enum typedef struct vim_exception except_T; struct vim_exception { except_type_T type; // exception type - char_u *value; // exception value + char *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 diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 62a4d48645..9ccbdbaf58 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -362,7 +362,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s bool delim_optional = false; int delim; char_u *end; - char_u *dummy; + char *dummy; exarg_T ea; pos_T save_cursor; bool use_last_pat; @@ -2036,7 +2036,6 @@ static int command_line_handle_key(CommandLineState *s) return command_line_not_changed(s); - case K_SELECT: // end of Select mode mapping - ignore return command_line_not_changed(s); @@ -2373,7 +2372,7 @@ static void abandon_cmdline(void) if (msg_scrolled == 0) { compute_cmdrow(); } - MSG(""); + msg(""); redraw_cmdline = true; } @@ -2462,7 +2461,8 @@ char *getcmdline_prompt(const char firstc, const char *const prompt, const int a * Return TRUE when the text must not be changed and we can't switch to * another window or buffer. Used when editing the command line etc. */ -int text_locked(void) { +int text_locked(void) +{ if (cmdwin_type != 0) { return TRUE; } @@ -2475,10 +2475,11 @@ int text_locked(void) { */ void text_locked_msg(void) { - EMSG(_(get_text_locked_msg())); + emsg(_(get_text_locked_msg())); } -char_u *get_text_locked_msg(void) { +char *get_text_locked_msg(void) +{ if (cmdwin_type != 0) { return e_cmdwin; } else { @@ -2491,7 +2492,7 @@ char_u *get_text_locked_msg(void) { int curbuf_locked(void) { if (curbuf->b_ro_locked > 0) { - EMSG(_("E788: Not allowed to edit another buffer now")); + emsg(_("E788: Not allowed to edit another buffer now")); return TRUE; } return allbuf_locked(); @@ -2504,7 +2505,7 @@ int curbuf_locked(void) int allbuf_locked(void) { if (allbuf_lock > 0) { - EMSG(_("E811: Not allowed to change buffer information now")); + emsg(_("E811: Not allowed to change buffer information now")); return TRUE; } return FALSE; @@ -2625,8 +2626,8 @@ static void realloc_cmdbuff(int len) char_u *p = ccline.cmdbuff; alloc_cmdbuff(len); // will get some more - /* There isn't always a NUL after the command, but it may need to be - * there, thus copy up to the NUL and add a NUL. */ + // There isn't always a NUL after the command, but it may need to be + // there, thus copy up to the NUL and add a NUL. memmove(ccline.cmdbuff, p, (size_t)ccline.cmdlen); ccline.cmdbuff[ccline.cmdlen] = NUL; xfree(p); @@ -2655,7 +2656,7 @@ void free_arshape_buf(void) #endif -enum { MAX_CB_ERRORS = 1 }; +enum { MAX_CB_ERRORS = 1, }; /// Color expression cmdline using built-in expressions parser /// @@ -3231,7 +3232,7 @@ void unputcmdline(void) if (ccline.cmdlen == ccline.cmdpos && !ui_has(kUICmdline)) { msg_putchar(' '); } else { - draw_cmdline(ccline.cmdpos, mb_ptr2len(ccline.cmdbuff + ccline.cmdpos)); + draw_cmdline(ccline.cmdpos, utfc_ptr2len(ccline.cmdbuff + ccline.cmdpos)); } msg_no_more = false; cursorcmd(); @@ -3427,24 +3428,24 @@ static bool cmdline_paste(int regname, bool literally, bool remcr) bool allocated; struct cmdline_info save_ccline; - /* check for valid regname; also accept special characters for CTRL-R in - * the command line */ + // check for valid regname; also accept special characters for CTRL-R in + // the command line if (regname != Ctrl_F && regname != Ctrl_P && regname != Ctrl_W && regname != Ctrl_A && regname != Ctrl_L && !valid_yank_reg(regname, false)) { return FAIL; } - /* A register containing CTRL-R can cause an endless loop. Allow using - * CTRL-C to break the loop. */ + // A register containing CTRL-R can cause an endless loop. Allow using + // CTRL-C to break the loop. line_breakcheck(); if (got_int) { return FAIL; } - /* Need to save and restore ccline. And set "textlock" to avoid nasty - * things like going to another buffer when evaluating an expression. */ + // Need to save and restore ccline. And set "textlock" to avoid nasty + // things like going to another buffer when evaluating an expression. save_cmdline(&save_ccline); textlock++; const bool i = get_spec_reg(regname, &arg, &allocated, true); @@ -3763,7 +3764,7 @@ static int nextwild(expand_T *xp, int type, int options, int escape) } if (!(ui_has(kUICmdline) || ui_has(kUIWildmenu))) { - MSG_PUTS("..."); // show that we are busy + msg_puts("..."); // show that we are busy ui_flush(); } @@ -3968,12 +3969,12 @@ char_u *ExpandOne(expand_T *xp, char_u *str, char_u *orig, int options, int mode * causing the pattern to be added, which has illegal characters. */ if (!(options & WILD_SILENT) && (options & WILD_LIST_NOTFOUND)) { - EMSG2(_(e_nomatch2), str); + semsg(_(e_nomatch2), str); } #endif } else if (xp->xp_numfiles == 0) { if (!(options & WILD_SILENT)) { - EMSG2(_(e_nomatch2), str); + semsg(_(e_nomatch2), str); } } else { // Escape the matches for use on the command line. @@ -4011,7 +4012,7 @@ char_u *ExpandOne(expand_T *xp, char_u *str, char_u *orig, int options, int mode * (and possibly have to hit return to continue!). */ if (!(options & WILD_SILENT)) { - EMSG(_(e_toomany)); + emsg(_(e_toomany)); } else if (!(options & WILD_NO_BEEP)) { beep_flush(); } @@ -4366,10 +4367,10 @@ static int showmatches(expand_T *xp, int wildmenu) attr = HL_ATTR(HLF_D); // find out highlighting for directories if (xp->xp_context == EXPAND_TAGS_LISTFILES) { - MSG_PUTS_ATTR(_("tagname"), HL_ATTR(HLF_T)); + msg_puts_attr(_("tagname"), HL_ATTR(HLF_T)); msg_clr_eos(); msg_advance(maxlen - 3); - MSG_PUTS_ATTR(_(" kind file\n"), HL_ATTR(HLF_T)); + msg_puts_attr(_(" kind file\n"), HL_ATTR(HLF_T)); } // list the files line by line @@ -4382,7 +4383,7 @@ static int showmatches(expand_T *xp, int wildmenu) msg_advance(maxlen + 1); msg_puts((const char *)p); msg_advance(maxlen + 3); - msg_puts_long_attr(p + 2, HL_ATTR(HLF_D)); + msg_outtrans_long_attr(p + 2, HL_ATTR(HLF_D)); break; } for (j = maxlen - lastlen; --j >= 0; ) { @@ -5606,7 +5607,6 @@ void globpath(char_u *path, char_u *file, garray_T *ga, int expand_options) } - /********************************* * Command line history stuff * *********************************/ @@ -6222,7 +6222,7 @@ void ex_history(exarg_T *eap) char_u *arg = eap->arg; if (hislen == 0) { - MSG(_("'history' option is zero")); + msg(_("'history' option is zero")); return; } @@ -6238,7 +6238,7 @@ void ex_history(exarg_T *eap) histype1 = 0; histype2 = HIST_COUNT-1; } else { - EMSG(_(e_trailing)); + emsg(_(e_trailing)); return; } } else { @@ -6248,7 +6248,7 @@ void ex_history(exarg_T *eap) end = arg; } if (!get_list_range(&end, &hisidx1, &hisidx2) || *end != NUL) { - EMSG(_(e_trailing)); + emsg(_(e_trailing)); return; } @@ -6256,7 +6256,7 @@ void ex_history(exarg_T *eap) STRCPY(IObuff, "\n # "); assert(history_names[histype1] != NULL); STRCAT(STRCAT(IObuff, history_names[histype1]), " history"); - MSG_PUTS_TITLE(IObuff); + msg_puts_title((char *)IObuff); idx = hisidx[histype1]; hist = history[histype1]; j = hisidx1; @@ -6411,8 +6411,8 @@ static int open_cmdwin(void) } } - /* Replace the empty last line with the current command-line and put the - * cursor there. */ + // Replace the empty last line with the current command-line and put the + // cursor there. ml_replace(curbuf->b_ml.ml_line_count, ccline.cmdbuff, true); curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; curwin->w_cursor.col = ccline.cmdpos; @@ -6475,7 +6475,7 @@ static int open_cmdwin(void) // this happens! if (!win_valid(old_curwin) || !bufref_valid(&old_curbuf)) { cmdwin_result = Ctrl_C; - EMSG(_("E199: Active window or buffer deleted")); + emsg(_("E199: Active window or buffer deleted")); } else { // autocmds may abort script processing if (aborting() && cmdwin_result != K_IGNORE) { diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c index 0dfd7e1edd..9aa8cc0107 100644 --- a/src/nvim/ex_session.c +++ b/src/nvim/ex_session.c @@ -860,7 +860,7 @@ void ex_loadview(exarg_T *eap) char *fname = get_view_file(*eap->arg); if (fname != NULL) { if (do_source(fname, false, DOSO_NONE) == FAIL) { - EMSG2(_(e_notopen), fname); + semsg(_(e_notopen), fname); } xfree(fname); } @@ -980,7 +980,7 @@ void ex_mkrc(exarg_T *eap) || ((ssop_flags & SSOP_CURDIR) && globaldir != NULL))) { if (os_chdir((char *)dirnow) != 0) { - EMSG(_(e_prev_dir)); + emsg(_(e_prev_dir)); } shorten_fnames(true); // restore original dir @@ -988,7 +988,7 @@ void ex_mkrc(exarg_T *eap) || ((ssop_flags & SSOP_CURDIR) && globaldir != NULL))) { if (os_chdir((char *)dirnow) != 0) { - EMSG(_(e_prev_dir)); + emsg(_(e_prev_dir)); } shorten_fnames(true); } @@ -1025,7 +1025,7 @@ void ex_mkrc(exarg_T *eap) failed |= fclose(fd); if (failed) { - EMSG(_(e_write)); + emsg(_(e_write)); } else if (eap->cmdidx == CMD_mksession) { // successful session write - set v:this_session char *const tbuf = xmalloc(MAXPATHL); @@ -1043,7 +1043,7 @@ void ex_mkrc(exarg_T *eap) static char *get_view_file(int c) { if (curbuf->b_ffname == NULL) { - EMSG(_(e_noname)); + emsg(_(e_noname)); return NULL; } char *sname = (char *)home_replace_save(NULL, curbuf->b_ffname); diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c index dc73e34111..c4d8f75a21 100644 --- a/src/nvim/extmark.c +++ b/src/nvim/extmark.c @@ -30,7 +30,7 @@ #include <assert.h> -#include "nvim/api/vim.h" +#include "nvim/api/extmark.h" #include "nvim/buffer.h" #include "nvim/buffer_updates.h" #include "nvim/charset.h" @@ -48,7 +48,8 @@ # include "extmark.c.generated.h" #endif -static ExtmarkNs *buf_ns_ref(buf_T *buf, uint64_t ns_id, bool put) { +static ExtmarkNs *buf_ns_ref(buf_T *buf, uint64_t ns_id, bool put) +{ return map_ref(uint64_t, ExtmarkNs)(buf->b_extmark_ns, ns_id, put); } @@ -67,6 +68,14 @@ uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t *idp, int row, colnr_T uint64_t mark = 0; uint64_t id = idp ? *idp : 0; + uint8_t decor_level = kDecorLevelNone; // no decor + if (decor) { + decor_level = kDecorLevelVisible; // decor affects redraw + if (kv_size(decor->virt_lines)) { + decor_level = kDecorLevelVirtLine; // decor affects horizontal size + } + } + if (id == 0) { id = ns->free_id++; } else { @@ -75,7 +84,6 @@ uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t *idp, int row, colnr_T if (old_mark & MARKTREE_PAIRED_FLAG || end_row > -1) { extmark_del(buf, ns_id, id); } else { - // TODO(bfredl): we need to do more if "revising" a decoration mark. MarkTreeIter itr[1] = { 0 }; old_pos = marktree_lookup(buf->b_marktree, old_mark, itr); assert(itr->node); @@ -83,10 +91,9 @@ uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t *idp, int row, colnr_T ExtmarkItem it = map_del(uint64_t, ExtmarkItem)(buf->b_extmark_index, old_mark); if (it.decor) { - decor_redraw(buf, row, row, it.decor); - decor_free(it.decor); + decor_remove(buf, row, row, it.decor); } - mark = marktree_revise(buf->b_marktree, itr); + mark = marktree_revise(buf->b_marktree, itr, decor_level); goto revised; } marktree_del_itr(buf->b_marktree, itr, false); @@ -99,9 +106,9 @@ uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t *idp, int row, colnr_T if (end_row > -1) { mark = marktree_put_pair(buf->b_marktree, row, col, right_gravity, - end_row, end_col, end_right_gravity); + end_row, end_col, end_right_gravity, decor_level); } else { - mark = marktree_put(buf->b_marktree, row, col, right_gravity); + mark = marktree_put(buf->b_marktree, row, col, right_gravity, decor_level); } revised: @@ -117,6 +124,9 @@ revised: } if (decor) { + if (kv_size(decor->virt_lines)) { + buf->b_virt_line_blocks++; + } decor_redraw(buf, row, end_row > -1 ? end_row : row, decor); } @@ -170,12 +180,7 @@ bool extmark_del(buf_T *buf, uint64_t ns_id, uint64_t id) } if (item.decor) { - decor_redraw(buf, pos.row, pos2.row, item.decor); - decor_free(item.decor); - } - - if (mark == buf->b_virt_line_mark) { - clear_virt_lines(buf, pos.row); + decor_remove(buf, pos.row, pos2.row, item.decor); } map_del(uint64_t, uint64_t)(ns->map, id); @@ -228,17 +233,13 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id, int l_row, colnr_T l_col, int u_r marktree_del_itr(buf->b_marktree, itr, false); if (*del_status >= 0) { // we had a decor_id DecorItem it = kv_A(decors, *del_status); - decor_redraw(buf, it.row1, mark.row, it.decor); - decor_free(it.decor); + decor_remove(buf, it.row1, mark.row, it.decor); } map_del(uint64_t, ssize_t)(&delete_set, mark.id); continue; } uint64_t start_id = mark.id & ~MARKTREE_END_FLAG; - if (start_id == buf->b_virt_line_mark) { - clear_virt_lines(buf, mark.row); - } ExtmarkItem item = map_get(uint64_t, ExtmarkItem)(buf->b_extmark_index, start_id); @@ -257,8 +258,7 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id, int l_row, colnr_T l_col, int u_r } map_put(uint64_t, ssize_t)(&delete_set, other, decor_id); } else if (item.decor) { - decor_redraw(buf, mark.row, mark.row, item.decor); - decor_free(item.decor); + decor_remove(buf, mark.row, mark.row, item.decor); } ExtmarkNs *my_ns = all_ns ? buf_ns_ref(buf, item.ns_id, false) : ns; map_del(uint64_t, uint64_t)(my_ns->map, item.mark_id); @@ -276,8 +276,7 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id, int l_row, colnr_T l_col, int u_r marktree_del_itr(buf->b_marktree, itr, false); if (decor_id >= 0) { DecorItem it = kv_A(decors, decor_id); - decor_redraw(buf, it.row1, pos.row, it.decor); - decor_free(it.decor); + decor_remove(buf, it.row1, pos.row, it.decor); } }); map_clear(uint64_t, ssize_t)(&delete_set); @@ -508,7 +507,6 @@ void extmark_apply_undo(ExtmarkUndoObject undo_info, bool undo) kExtmarkNoUndo); } } - curbuf->b_virt_line_pos = -1; } @@ -588,7 +586,6 @@ void extmark_splice_impl(buf_T *buf, int start_row, colnr_T start_col, bcount_t colnr_T new_col, bcount_t new_byte, ExtmarkOp undo) { buf->deleted_bytes2 = 0; - buf->b_virt_line_pos = -1; buf_updates_send_splice(buf, start_row, start_col, start_byte, old_row, old_col, old_byte, new_row, new_col, new_byte); @@ -680,7 +677,6 @@ void extmark_move_region(buf_T *buf, int start_row, colnr_T start_col, bcount_t colnr_T new_col, bcount_t new_byte, ExtmarkOp undo) { buf->deleted_bytes2 = 0; - buf->b_virt_line_pos = -1; // TODO(bfredl): this is not synced to the buffer state inside the callback. // But unless we make the undo implementation smarter, this is not ensured // anyway. @@ -719,16 +715,3 @@ void extmark_move_region(buf_T *buf, int start_row, colnr_T start_col, bcount_t .data.move = move })); } } - -uint64_t src2ns(Integer *src_id) -{ - if (*src_id == 0) { - *src_id = nvim_create_namespace((String)STRING_INIT); - } - if (*src_id < 0) { - return UINT64_MAX; - } else { - return (uint64_t)(*src_id); - } -} - diff --git a/src/nvim/extmark.h b/src/nvim/extmark.h index aee679a9c7..c70db9f7aa 100644 --- a/src/nvim/extmark.h +++ b/src/nvim/extmark.h @@ -8,8 +8,7 @@ EXTERN int extmark_splice_pending INIT(= 0); -typedef struct -{ +typedef struct { uint64_t ns_id; uint64_t mark_id; int row; diff --git a/src/nvim/extmark_defs.h b/src/nvim/extmark_defs.h index c0a4f4014f..bbe8504ebf 100644 --- a/src/nvim/extmark_defs.h +++ b/src/nvim/extmark_defs.h @@ -11,13 +11,8 @@ typedef struct { int hl_id; } VirtTextChunk; -typedef kvec_t(VirtTextChunk) VirtText; -#define VIRTTEXT_EMPTY ((VirtText)KV_INITIAL_VALUE) -typedef kvec_t(VirtText) VirtLines; - -typedef struct -{ +typedef struct { uint64_t ns_id; uint64_t mark_id; // TODO(bfredl): a lot of small allocations. Should probably use @@ -38,4 +33,10 @@ typedef enum { kExtmarkUndoNoRedo, // Operation should be undoable, but not redoable } ExtmarkOp; +typedef enum { + kDecorLevelNone = 0, + kDecorLevelVisible = 1, + kDecorLevelVirtLine = 2, +} DecorLevel; + #endif // NVIM_EXTMARK_DEFS_H diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index fca62353d5..36257fefb3 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -419,7 +419,7 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le len = 0; while (*wc_part != NUL) { if (len + 5 >= MAXPATHL) { - EMSG(_(e_pathtoolong)); + emsg(_(e_pathtoolong)); break; } if (STRNCMP(wc_part, "**", 2) == 0) { @@ -437,7 +437,7 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le } wc_part = (char_u *)errpt; if (*wc_part != NUL && !vim_ispathsep(*wc_part)) { - EMSG2(_( + semsg(_( "E343: Invalid path: '**[number]' must be at the end of the path or be followed by '%s'."), PATHSEPSTR); goto error_return; @@ -463,7 +463,7 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le // create an absolute path if (STRLEN(search_ctx->ffsc_start_dir) + STRLEN(search_ctx->ffsc_fix_path) + 3 >= MAXPATHL) { - EMSG(_(e_pathtoolong)); + emsg(_(e_pathtoolong)); goto error_return; } STRCPY(ff_expand_buffer, search_ctx->ffsc_start_dir); @@ -1113,8 +1113,8 @@ static bool ff_wc_equal(char_u *s1, char_u *s2) } for (i = 0, j = 0; s1[i] != NUL && s2[j] != NUL;) { - c1 = PTR2CHAR(s1 + i); - c2 = PTR2CHAR(s2 + j); + c1 = utf_ptr2char(s1 + i); + c2 = utf_ptr2char(s2 + j); if ((p_fic ? mb_tolower(c1) != mb_tolower(c2) : c1 != c2) && (prev1 != '*' || prev2 != '*')) { @@ -1570,18 +1570,18 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first if (file_name == NULL && (options & FNAME_MESS)) { if (first == TRUE) { if (find_what == FINDFILE_DIR) { - EMSG2(_("E344: Can't find directory \"%s\" in cdpath"), + semsg(_("E344: Can't find directory \"%s\" in cdpath"), ff_file_to_find); } else { - EMSG2(_("E345: Can't find file \"%s\" in path"), + semsg(_("E345: Can't find file \"%s\" in path"), ff_file_to_find); } } else { if (find_what == FINDFILE_DIR) { - EMSG2(_("E346: No more directory \"%s\" found in cdpath"), + semsg(_("E346: No more directory \"%s\" found in cdpath"), ff_file_to_find); } else { - EMSG2(_("E347: No more file \"%s\" found in path"), + semsg(_("E347: No more file \"%s\" found in path"), ff_file_to_find); } } diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 4a33d74011..cf4037308b 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -224,8 +224,8 @@ int readfile(char_u *fname, char_u *sfname, linenr_T from, linenr_T lines_to_ski bool keep_dest_enc = false; // don't retry when char doesn't fit // in destination encoding int bad_char_behavior = BAD_REPLACE; - /* BAD_KEEP, BAD_DROP or character to - * replace with */ + // BAD_KEEP, BAD_DROP or character to + // replace with char_u *tmpname = NULL; // name of 'charconvert' output file int fio_flags = 0; char_u *fenc; // fileencoding to use @@ -280,8 +280,8 @@ int readfile(char_u *fname, char_u *sfname, linenr_T from, linenr_T lines_to_ski || (sfname == curbuf->b_ffname); using_b_fname = (fname == curbuf->b_fname) || (sfname == curbuf->b_fname); - /* After reading a file the cursor line changes but we don't want to - * display the line. */ + // After reading a file the cursor line changes but we don't want to + // display the line. ex_no_reprint = true; // don't display the file info for another buffer now @@ -454,9 +454,9 @@ int readfile(char_u *fname, char_u *sfname, linenr_T from, linenr_T lines_to_ski // been created by someone else, a ":w" will complain. curbuf->b_flags |= BF_NEW; - /* Create a swap file now, so that other Vims are warned - * that we are editing this file. Don't do this for a - * "nofile" or "nowrite" buffer type. */ + // Create a swap file now, so that other Vims are warned + // that we are editing this file. Don't do this for a + // "nofile" or "nowrite" buffer type. if (!bt_dontwrite(curbuf)) { check_need_swap(newfile); // SwapExists autocommand may mess things up @@ -465,7 +465,7 @@ int readfile(char_u *fname, char_u *sfname, linenr_T from, linenr_T lines_to_ski && (old_b_ffname != curbuf->b_ffname)) || (using_b_fname && (old_b_fname != curbuf->b_fname))) { - EMSG(_(e_auchangedbuf)); + emsg(_(e_auchangedbuf)); return FAIL; } } @@ -524,16 +524,16 @@ int readfile(char_u *fname, char_u *sfname, linenr_T from, linenr_T lines_to_ski curbuf->b_start_bomb = FALSE; } - /* Create a swap file now, so that other Vims are warned that we are - * editing this file. - * Don't do this for a "nofile" or "nowrite" buffer type. */ + // Create a swap file now, so that other Vims are warned that we are + // editing this file. + // Don't do this for a "nofile" or "nowrite" buffer type. if (!bt_dontwrite(curbuf)) { check_need_swap(newfile); if (!read_stdin && (curbuf != old_curbuf || (using_b_ffname && (old_b_ffname != curbuf->b_ffname)) || (using_b_fname && (old_b_fname != curbuf->b_fname)))) { - EMSG(_(e_auchangedbuf)); + emsg(_(e_auchangedbuf)); if (!read_buffer) { close(fd); } @@ -643,9 +643,9 @@ int readfile(char_u *fname, char_u *sfname, linenr_T from, linenr_T lines_to_ski --no_wait_return; msg_scroll = msg_save; if (fd < 0) { - EMSG(_("E200: *ReadPre autocommands made the file unreadable")); + emsg(_("E200: *ReadPre autocommands made the file unreadable")); } else { - EMSG(_("E201: *ReadPre autocommands must not change current buffer")); + emsg(_("E201: *ReadPre autocommands must not change current buffer")); } curbuf->b_p_ro = TRUE; // must use "w!" now return FAIL; @@ -832,7 +832,6 @@ retry: } - #ifdef HAVE_ICONV // Try using iconv() if we can't convert internally. if (fio_flags == 0 @@ -854,8 +853,8 @@ retry: #ifdef HAVE_ICONV did_iconv = false; #endif - /* Skip conversion when it's already done (retry for wrong - * "fileformat"). */ + // Skip conversion when it's already done (retry for wrong + // "fileformat"). if (tmpname == NULL) { tmpname = readfile_charconvert(fname, fenc, &fd); if (tmpname == NULL) { @@ -863,7 +862,7 @@ retry: advance_fenc = true; if (fd < 0) { // Re-opening the original file failed! - EMSG(_("E202: Conversion made file unreadable!")); + emsg(_("E202: Conversion made file unreadable!")); error = true; goto failed; } @@ -876,17 +875,17 @@ retry: && iconv_fd == (iconv_t)-1 #endif ) { - /* Conversion wanted but we can't. - * Try the next conversion in 'fileencodings' */ + // Conversion wanted but we can't. + // Try the next conversion in 'fileencodings' advance_fenc = true; goto 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. */ + // 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 && !read_fifo); if (!skip_read) { @@ -1014,9 +1013,9 @@ retry: read_buf_col += n; break; } else { - /* Append whole line and new-line. Change NL - * to NUL to reverse the effect done below. */ - for (ni = 0; ni < n; ++ni) { + // Append whole line and new-line. Change NL + // to NUL to reverse the effect done below. + for (ni = 0; ni < n; ni++) { if (p[ni] == NL) { ptr[tlen++] = NUL; } else { @@ -1076,10 +1075,10 @@ retry: *(ptr - conv_restlen) = NUL; conv_restlen = 0; } else { - /* Replace the trailing bytes with the replacement - * character if we were converting; if we weren't, - * leave the UTF8 checking code to do it, as it - * works slightly differently. */ + // Replace the trailing bytes with the replacement + // character if we were converting; if we weren't, + // leave the UTF8 checking code to do it, as it + // works slightly differently. if (bad_char_behavior != BAD_KEEP && (fio_flags != 0 #ifdef HAVE_ICONV || iconv_fd != (iconv_t)-1 @@ -1212,8 +1211,8 @@ retry: } if (from_size > 0) { - /* Some remaining characters, keep them for the next - * round. */ + // Some remaining characters, keep them for the next + // round. memmove(conv_rest, (char_u *)fromp, from_size); conv_restlen = (int)from_size; } @@ -1519,7 +1518,6 @@ rewind_retry: try_mac = 1; try_unix = 1; for (; p >= ptr && *p != CAR; p--) { - ; } if (p >= ptr) { for (p = ptr; p < ptr + size; ++p) { @@ -1752,11 +1750,11 @@ failed: } if (newfile || read_buffer) { redraw_curbuf_later(NOT_VALID); - /* After reading the text into the buffer the diff info needs to - * be updated. */ + // After reading the text into the buffer the diff info needs to + // be updated. diff_invalidate(curbuf); - /* All folds in the window are invalid now. Mark them for update - * before triggering autocommands. */ + // All folds in the window are invalid now. Mark them for update + // before triggering autocommands. foldUpdateAll(curwin); } else if (linecnt) { // appended at least one line appended_lines_mark(from, linecnt); @@ -1849,7 +1847,7 @@ failed: msg_scrolled_ign = true; if (!read_stdin && !read_buffer) { - p = msg_trunc_attr(IObuff, FALSE, 0); + p = (char_u *)msg_trunc_attr((char *)IObuff, FALSE, 0); } if (read_stdin || read_buffer || restart_edit != 0 @@ -2111,27 +2109,27 @@ static char_u *next_fenc(char_u **pp, bool *alloced) static char_u *readfile_charconvert(char_u *fname, char_u *fenc, int *fdp) { char_u *tmpname; - char_u *errmsg = NULL; + char *errmsg = NULL; tmpname = vim_tempname(); if (tmpname == NULL) { - errmsg = (char_u *)_("Can't find temp file for conversion"); + errmsg = _("Can't find temp file for conversion"); } else { close(*fdp); // close the input file, ignore errors *fdp = -1; if (eval_charconvert((char *)fenc, "utf-8", (char *)fname, (char *)tmpname) == FAIL) { - errmsg = (char_u *)_("Conversion with 'charconvert' failed"); + errmsg = _("Conversion with 'charconvert' failed"); } if (errmsg == NULL && (*fdp = os_open((char *)tmpname, O_RDONLY, 0)) < 0) { - errmsg = (char_u *)_("can't read output of 'charconvert'"); + errmsg = _("can't read output of 'charconvert'"); } } if (errmsg != NULL) { - /* Don't use emsg(), it breaks mappings, the retry with - * another type of conversion might still work. */ - MSG(errmsg); + // Don't use emsg(), it breaks mappings, the retry with + // another type of conversion might still work. + msg(errmsg); if (tmpname != NULL) { os_remove((char *)tmpname); // delete converted file XFREE_CLEAR(tmpname); @@ -2257,7 +2255,7 @@ int buf_write(buf_T *buf, char_u *fname, char_u *sfname, linenr_T start, linenr_ if (buf->b_ml.ml_mfp == NULL) { /* This can happen during startup when there is a stray "w" in the * vimrc file. */ - EMSG(_(e_emptybuf)); + emsg(_(e_emptybuf)); return FAIL; } @@ -2271,7 +2269,7 @@ int buf_write(buf_T *buf, char_u *fname, char_u *sfname, linenr_T start, linenr_ // Avoid a crash for a long name. if (STRLEN(fname) >= MAXPATHL) { - EMSG(_(e_longname)); + emsg(_(e_longname)); return FAIL; } @@ -2433,7 +2431,7 @@ int buf_write(buf_T *buf, char_u *fname, char_u *sfname, linenr_T start, linenr_ --no_wait_return; msg_scroll = msg_save; if (nofile_err) { - EMSG(_("E676: No matching autocommands for acwrite buffer")); + emsg(_("E676: No matching autocommands for acwrite buffer")); } if (nofile_err @@ -2466,7 +2464,7 @@ int buf_write(buf_T *buf, char_u *fname, char_u *sfname, linenr_T start, linenr_ return OK; } if (!aborting()) { - EMSG(_("E203: Autocommands deleted or unloaded buffer to be written")); + emsg(_("E203: Autocommands deleted or unloaded buffer to be written")); } return FAIL; } @@ -2487,7 +2485,7 @@ int buf_write(buf_T *buf, char_u *fname, char_u *sfname, linenr_T start, linenr_ if (end < start) { --no_wait_return; msg_scroll = msg_save; - EMSG(_("E204: Autocommand changed number of lines in unexpected way")); + emsg(_("E204: Autocommand changed number of lines in unexpected way")); return FAIL; } } @@ -2772,7 +2770,7 @@ int buf_write(buf_T *buf, char_u *fname, char_u *sfname, linenr_T start, linenr_ int ret; char *failed_dir; if ((ret = os_mkdir_recurse((char *)IObuff, 0755, &failed_dir)) != 0) { - EMSG3(_("E303: Unable to create directory \"%s\" for backup file: %s"), + semsg(_("E303: Unable to create directory \"%s\" for backup file: %s"), failed_dir, os_strerror(ret)); xfree(failed_dir); } @@ -2936,7 +2934,7 @@ nobackup: int ret; char *failed_dir; if ((ret = os_mkdir_recurse((char *)IObuff, 0755, &failed_dir)) != 0) { - EMSG3(_("E303: Unable to create directory \"%s\" for backup file: %s"), + semsg(_("E303: Unable to create directory \"%s\" for backup file: %s"), failed_dir, os_strerror(ret)); xfree(failed_dir); } @@ -3083,7 +3081,6 @@ nobackup: } - if (converted && wb_flags == 0) { #ifdef HAVE_ICONV // Use iconv() conversion when conversion is needed and it's not done @@ -3474,7 +3471,7 @@ restore_backup: // This may take a while, if we were interrupted let the user // know we got the message. if (got_int) { - MSG(_(e_interr)); + msg(_(e_interr)); ui_flush(); } @@ -3539,7 +3536,7 @@ restore_backup: } } - set_keep_msg(msg_trunc_attr(IObuff, FALSE, 0), 0); + set_keep_msg((char_u *)msg_trunc_attr((char *)IObuff, FALSE, 0), 0); } /* When written everything correctly: reset 'modified'. Unless not @@ -3584,7 +3581,7 @@ restore_backup: * the current backup file becomes the original file */ if (org == NULL) { - EMSG(_("E205: Patchmode: can't save original file")); + emsg(_("E205: Patchmode: can't save original file")); } else if (!os_path_exists((char_u *)org)) { vim_rename(backup, (char_u *)org); XFREE_CLEAR(backup); // don't delete the file @@ -3606,7 +3603,7 @@ restore_backup: || (empty_fd = os_open(org, O_CREAT | O_EXCL | O_NOFOLLOW, perm < 0 ? 0666 : (perm & 0777))) < 0) { - EMSG(_("E206: patchmode: can't touch empty original file")); + emsg(_("E206: patchmode: can't touch empty original file")); } else { close(empty_fd); } @@ -3623,7 +3620,7 @@ restore_backup: if (!p_bk && backup != NULL && !write_info.bw_conv_error && os_remove((char *)backup) != 0) { - EMSG(_("E207: Can't delete backup file")); + emsg(_("E207: Can't delete backup file")); } goto nofail; @@ -3663,14 +3660,14 @@ nofail: #endif if (errnum != NULL) { if (errmsgarg != 0) { - emsgf("%s: %s%s: %s", errnum, IObuff, errmsg, os_strerror(errmsgarg)); + semsg("%s: %s%s: %s", errnum, IObuff, errmsg, os_strerror(errmsgarg)); } else { - emsgf("%s: %s%s", errnum, IObuff, errmsg); + semsg("%s: %s%s", errnum, IObuff, errmsg); } } else if (errmsgarg != 0) { - emsgf(errmsg, os_strerror(errmsgarg)); + semsg(errmsg, os_strerror(errmsgarg)); } else { - EMSG(errmsg); + emsg(errmsg); } if (errmsg_allocated) { xfree(errmsg); @@ -3679,9 +3676,9 @@ nofail: 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"), + msg_puts_attr(_("\nWARNING: Original file may be lost or damaged\n"), attr | MSG_HIST); - MSG_PUTS_ATTR(_("don't quit the editor until the file is successfully written!"), + msg_puts_attr(_("don't quit the editor until the file is successfully written!"), attr | MSG_HIST); /* Update the timestamp to avoid an "overwrite changed file" @@ -3764,7 +3761,7 @@ static int set_rw_fname(char_u *fname, char_u *sfname) } if (curbuf != buf) { // We are in another buffer now, don't do the renaming. - EMSG(_(e_auchangedbuf)); + emsg(_(e_auchangedbuf)); return FAIL; } @@ -3852,20 +3849,16 @@ void msg_add_lines(int insert_space, long lnum, off_T nchars) *p++ = ' '; } if (shortmess(SHM_LINES)) { - sprintf((char *)p, "%" PRId64 "L, %" PRId64 "C", - (int64_t)lnum, (int64_t)nchars); + vim_snprintf((char *)p, IOSIZE - (p - IObuff), "%" PRId64 "L, %" PRId64 "C", + (int64_t)lnum, (int64_t)nchars); } else { - if (lnum == 1) { - STRCPY(p, _("1 line, ")); - } else { - sprintf((char *)p, _("%" PRId64 " lines, "), (int64_t)lnum); - } + vim_snprintf((char *)p, IOSIZE - (p - IObuff), + NGETTEXT("%" PRId64 " line, ", "%" PRId64 " lines, ", lnum), + (int64_t)lnum); p += STRLEN(p); - if (nchars == 1) { - STRCPY(p, _("1 character")); - } else { - sprintf((char *)p, _("%" PRId64 " characters"), (int64_t)nchars); - } + vim_snprintf((char *)p, IOSIZE - (p - IObuff), + NGETTEXT("%" PRId64 " character", "%" PRId64 " characters", nchars), + (int64_t)nchars); } } @@ -3908,9 +3901,9 @@ static int check_mtime(buf_T *buf, FileInfo *file_info) static bool time_differs(long t1, long t2) FUNC_ATTR_CONST { #if defined(__linux__) || defined(MSWIN) - /* On a FAT filesystem, esp. under Linux, there are only 5 bits to store - * the seconds. Since the roundoff is done when flushing the inode, the - * time may change unexpectedly by one second!!! */ + // On a FAT filesystem, esp. under Linux, there are only 5 bits to store + // the seconds. Since the roundoff is done when flushing the inode, the + // time may change unexpectedly by one second!!! return t1 - t2 > 1 || t2 - t1 > 1; #else return t1 != t2; @@ -4192,8 +4185,8 @@ static bool need_conversion(const char_u *fenc) same_encoding = TRUE; fenc_flags = 0; } else { - /* Ignore difference between "ansi" and "latin1", "ucs-4" and - * "ucs-4be", etc. */ + // Ignore difference between "ansi" and "latin1", "ucs-4" and + // "ucs-4be", etc. enc_flags = get_fio_flags(p_enc); fenc_flags = get_fio_flags(fenc); same_encoding = (enc_flags != 0 && fenc_flags == enc_flags); @@ -4203,8 +4196,8 @@ static bool need_conversion(const char_u *fenc) return false; } - /* Encodings differ. However, conversion is not needed when 'enc' is any - * Unicode encoding and the file is UTF-8. */ + // Encodings differ. However, conversion is not needed when 'enc' is any + // Unicode encoding and the file is UTF-8. return !(fenc_flags == FIO_UTF8); } @@ -4250,7 +4243,6 @@ static int get_fio_flags(const char_u *name) } - /* * Check for a Unicode BOM (Byte Order Mark) at the start of p[size]. * "size" must be at least 2. @@ -4697,8 +4689,8 @@ int vim_rename(const char_u *from, const char_u *to) (void)os_rename(tempname, from); return -1; } - /* If it fails for one temp name it will most likely fail - * for any temp name, give up. */ + // If it fails for one temp name it will most likely fail + // for any temp name, give up. return -1; } } @@ -4783,7 +4775,7 @@ int vim_rename(const char_u *from, const char_u *to) mch_free_acl(acl); #endif if (errmsg != NULL) { - EMSG2(errmsg, to); + semsg(errmsg, to); return -1; } os_remove((char *)from); @@ -4954,8 +4946,8 @@ int buf_check_timestamp(buf_T *buf) buf_store_file_info(buf, &file_info); } - /* Don't do anything for a directory. Might contain the file - * explorer. */ + // Don't do anything for a directory. Might contain the file + // explorer. if (os_isdir(buf->b_fname)) { } else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar) && !bufIsChanged(buf) && file_info_ok) { @@ -4989,7 +4981,7 @@ int buf_check_timestamp(buf_T *buf) busy = false; if (n) { if (!bufref_valid(&bufref)) { - EMSG(_("E246: FileChangedShell autocommand deleted buffer")); + emsg(_("E246: FileChangedShell autocommand deleted buffer")); } s = get_vim_var_str(VV_FCS_CHOICE); if (STRCMP(s, "reload") == 0 && *reason != 'd') { @@ -5065,7 +5057,7 @@ int buf_check_timestamp(buf_T *buf) xstrlcat(tbuf, "; ", tbuf_len - 1); xstrlcat(tbuf, mesg2, tbuf_len - 1); } - EMSG(tbuf); + emsg(tbuf); retval = 2; } else { if (!autocmd_busy) { @@ -5170,7 +5162,7 @@ void buf_reload(buf_T *buf, int orig_mode) } if (savebuf == NULL || saved == FAIL || buf != curbuf || move_lines(buf, savebuf) == FAIL) { - EMSG2(_("E462: Could not prepare for reloading \"%s\""), + semsg(_("E462: Could not prepare for reloading \"%s\""), buf->b_fname); saved = FAIL; } @@ -5182,7 +5174,7 @@ void buf_reload(buf_T *buf, int orig_mode) 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); + semsg(_("E321: Could not reload \"%s\""), buf->b_fname); } if (savebuf != NULL && bufref_valid(&bufref) && buf == curbuf) { // Put the text back from the save buffer. First @@ -5217,8 +5209,8 @@ void buf_reload(buf_T *buf, int orig_mode) // Invalidate diff info if necessary. diff_invalidate(curbuf); - /* Restore the topline and cursor position and check it (lines may - * have been removed). */ + // Restore the topline and cursor position and check it (lines may + // have been removed). if (old_topline > curbuf->b_ml.ml_line_count) { curwin->w_topline = curbuf->b_ml.ml_line_count; } else { @@ -5237,9 +5229,9 @@ void buf_reload(buf_T *buf, int orig_mode) } } - /* If the mode didn't change and 'readonly' was set, keep the old - * value; the user probably used the ":view" command. But don't - * reset it, might have had a read error. */ + // If the mode didn't change and 'readonly' was set, keep the old + // value; the user probably used the ":view" command. But don't + // reset it, might have had a read error. if (orig_mode == curbuf->b_orig_mode) { curbuf->b_p_ro |= old_ro; } @@ -5436,7 +5428,6 @@ char_u *vim_tempname(void) } - /// Tries matching a filename with a "pattern" ("prog" is NULL), or use the /// precompiled regprog "prog" ("pattern" is NULL). That avoids calling /// vim_regcomp() often. @@ -5718,9 +5709,9 @@ char_u *file_pat_to_reg_pat(const char_u *pat, const char_u *pat_end, char *allo reg_pat[i] = NUL; if (nested != 0) { if (nested < 0) { - EMSG(_("E219: Missing {.")); + emsg(_("E219: Missing {.")); } else { - EMSG(_("E220: Missing }.")); + emsg(_("E220: Missing }.")); } XFREE_CLEAR(reg_pat); } @@ -5754,8 +5745,8 @@ long write_eintr(int fd, void *buf, size_t bufsize) long ret = 0; long wlen; - /* Repeat the write() so long it didn't fail, other than being interrupted - * by a signal. */ + // Repeat the write() so long it didn't fail, other than being interrupted + // by a signal. while (ret < (long)bufsize) { wlen = write(fd, (char *)buf + ret, bufsize - ret); if (wlen < 0) { diff --git a/src/nvim/fileio.h b/src/nvim/fileio.h index 9bfec44ef3..186d0b90ab 100644 --- a/src/nvim/fileio.h +++ b/src/nvim/fileio.h @@ -13,6 +13,7 @@ #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_NOWINENTER 0x80 // do not trigger BufWinEnter #define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) diff --git a/src/nvim/fold.c b/src/nvim/fold.c index e141f9bb62..daf0df9326 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -72,12 +72,12 @@ typedef struct { linenr_T lnum_save; // line nr used by foldUpdateIEMSRecurse() int lvl; // current level (-1 for undefined) int lvl_next; // level used for next line - int start; /* number of folds that are forced to start at - this line. */ - int end; /* level of fold that is forced to end below - this line */ - int had_end; /* level of fold that is forced to end above - this line (copy of "end" of prev. line) */ + int start; // number of folds that are forced to start at + // this line. + int end; // level of fold that is forced to end below + // this line + int had_end; // level of fold that is forced to end above + // this line (copy of "end" of prev. line) } fline_T; // Flag is set when redrawing is needed. @@ -405,8 +405,8 @@ void opFoldRange(pos_T firstpos, pos_T lastpos, int opening, int recurse, int ha for (lnum = first; lnum <= last; lnum = lnum_next + 1) { pos_T temp = { lnum, 0, 0 }; lnum_next = lnum; - /* Opening one level only: next fold to open is after the one going to - * be opened. */ + // Opening one level only: next fold to open is after the one going to + // be opened. if (opening && !recurse) { (void)hasFolding(lnum, NULL, &lnum_next); } @@ -418,7 +418,7 @@ void opFoldRange(pos_T firstpos, pos_T lastpos, int opening, int recurse, int ha } } if (done == DONE_NOTHING) { - EMSG(_(e_nofold)); + emsg(_(e_nofold)); } // Force a redraw to remove the Visual highlighting. if (had_visual) { @@ -551,9 +551,9 @@ int foldManualAllowed(bool create) return TRUE; } if (create) { - EMSG(_("E350: Cannot create fold with current 'foldmethod'")); + emsg(_("E350: Cannot create fold with current 'foldmethod'")); } else { - EMSG(_("E351: Cannot delete fold with current 'foldmethod'")); + emsg(_("E351: Cannot delete fold with current 'foldmethod'")); } return FALSE; } @@ -639,8 +639,8 @@ void foldCreate(win_T *wp, pos_T start, pos_T end) } if (cont > 0) { ga_grow(&fold_ga, cont); - /* If the first fold starts before the new fold, let the new fold - * start there. Otherwise the existing fold would change. */ + // If the first fold starts before the new fold, let the new fold + // start there. Otherwise the existing fold would change. if (start_rel.lnum > fp->fd_top) { start_rel.lnum = fp->fd_top; } @@ -655,8 +655,8 @@ void foldCreate(win_T *wp, pos_T start, pos_T end) fold_ga.ga_len += cont; i += cont; - /* Adjust line numbers in contained folds to be relative to the - * new fold. */ + // Adjust line numbers in contained folds to be relative to the + // new fold. for (int j = 0; j < cont; j++) { ((fold_T *)fold_ga.ga_data)[j].fd_top -= start_rel.lnum; } @@ -673,9 +673,8 @@ void foldCreate(win_T *wp, pos_T start, pos_T end) fp->fd_top = start_rel.lnum; fp->fd_len = end_rel.lnum - start_rel.lnum + 1; - /* We want the new fold to be closed. If it would remain open because - * of using 'foldlevel', need to adjust fd_flags of containing folds. - */ + // We want the new fold to be closed. If it would remain open because + // of using 'foldlevel', need to adjust fd_flags of containing folds. if (use_level && !closed && level < wp->w_p_fdl) { closeFold(start, 1L); } @@ -765,7 +764,7 @@ void deleteFold(win_T *const wp, const linenr_T start, const linenr_T end, const } } if (!did_one) { - EMSG(_(e_nofold)); + emsg(_(e_nofold)); // Force a redraw to remove the Visual highlighting. if (had_visual) { redraw_buf_later(wp->w_buffer, INVERTED); @@ -916,8 +915,8 @@ int foldMoveTo(const bool updown, const int dir, const long count) break; } } - /* don't look for contained folds, they will always move - * the cursor too far. */ + // don't look for contained folds, they will always move + // the cursor too far. last = true; } @@ -953,8 +952,8 @@ int foldMoveTo(const bool updown, const int dir, const long count) } } } else { - /* Open fold found, set cursor to its start/end and then check - * nested folds. */ + // Open fold found, set cursor to its start/end and then check + // nested folds. if (dir == FORWARD) { lnum = fp->fd_top + lnum_off + fp->fd_len - 1; if (lnum > curwin->w_cursor.lnum) { @@ -1197,7 +1196,7 @@ static void setFoldRepeat(pos_T pos, long count, int do_open) if (!(done & DONE_ACTION)) { // Only give an error message when no fold could be opened. if (n == 0 && !(done & DONE_FOLD)) { - EMSG(_(e_nofold)); + emsg(_(e_nofold)); } break; } @@ -1334,7 +1333,7 @@ static linenr_T setManualFoldWin(win_T *wp, linenr_T lnum, int opening, int recu } done |= DONE_FOLD; } else if (donep == NULL && wp == curwin) { - EMSG(_(e_nofold)); + emsg(_(e_nofold)); } if (donep != NULL) { @@ -1375,8 +1374,8 @@ static void deleteFoldEntry(win_T *const wp, garray_T *const gap, const int idx, memmove(fp, fp + 1, sizeof(*fp) * (size_t)(gap->ga_len - idx)); } } else { - /* Move nested folds one level up, to overwrite the fold that is - * deleted. */ + // Move nested folds one level up, to overwrite the fold that is + // deleted. int moved = fp->fd_nested.ga_len; ga_grow(gap, moved - 1); { @@ -1517,8 +1516,8 @@ static void foldMarkAdjustRecurse(win_T *wp, garray_T *gap, linenr_T line1, line fp->fd_len += amount_after; } } else { - /* 5. fold is below line1 and contains line2; need to - * correct nested folds too */ + // 5. fold is below line1 and contains line2; need to + // correct nested folds too if (amount == MAXLNUM) { foldMarkAdjustRecurse(wp, &fp->fd_nested, line1 - fp->fd_top, line2 - fp->fd_top, amount, @@ -1652,7 +1651,7 @@ static void foldCreateMarkers(win_T *wp, pos_T start, pos_T end) { buf_T *buf = wp->w_buffer; if (!MODIFIABLE(buf)) { - EMSG(_(e_modifiable)); + emsg(_(e_modifiable)); return; } parseMarker(wp); @@ -1660,8 +1659,8 @@ static void foldCreateMarkers(win_T *wp, pos_T start, pos_T end) foldAddMarker(buf, start, wp->w_p_fmr, foldstartmarkerlen); foldAddMarker(buf, end, foldendmarker, foldendmarkerlen); - /* Update both changes here, to avoid all folds after the start are - * changed when the start marker is inserted and the end isn't. */ + // Update both changes here, to avoid all folds after the start are + // changed when the start marker is inserted and the end isn't. // TODO(teto): pass the buffer changed_lines(start.lnum, (colnr_T)0, end.lnum, 0L, false); @@ -1857,8 +1856,8 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldin } if (text != NULL) { - /* Replace unprintable characters, if there are any. But - * replace a TAB with a space. */ + // Replace unprintable characters, if there are any. But + // replace a TAB with a space. for (p = text; *p != NUL; p++) { int len = utfc_ptr2len(p); @@ -1941,10 +1940,9 @@ void foldtext_cleanup(char_u *str) ++len; } - /* May remove 'commentstring' start. Useful when it's a double - * quote and we already removed a double quote. */ - for (p = s; p > str && ascii_iswhite(p[-1]); --p) { - ; + // May remove 'commentstring' start. Useful when it's a double + // quote and we already removed a double quote. + for (p = s; p > str && ascii_iswhite(p[-1]); p--) { } if (p >= str + cms_slen && STRNCMP(p - cms_slen, cms_start, cms_slen) == 0) { @@ -2074,12 +2072,12 @@ static void foldUpdateIEMS(win_T *const wp, linenr_T top, linenr_T bot) getlevel = foldlevelIndent; } - /* Backup to a line for which the fold level is defined. Since it's - * always defined for line one, we will stop there. */ + // Backup to a line for which the fold level is defined. Since it's + // always defined for line one, we will stop there. fline.lvl = -1; - for (; !got_int; --fline.lnum) { - /* Reset lvl_next each time, because it will be set to a value for - * the next line, but we search backwards here. */ + for (; !got_int; fline.lnum--) { + // Reset lvl_next each time, because it will be set to a value for + // the next line, but we search backwards here. fline.lvl_next = -1; getlevel(&fline); if (fline.lvl >= 0) { @@ -2128,15 +2126,15 @@ static void foldUpdateIEMS(win_T *const wp, linenr_T top, linenr_T bot) end = start; } while (!got_int) { - /* Always stop at the end of the file ("end" can be past the end of - * the file). */ + // Always stop at the end of the file ("end" can be past the end of + // the file). if (fline.lnum > wp->w_buffer->b_ml.ml_line_count) { break; } if (fline.lnum > end) { - /* For "marker", "expr" and "syntax" methods: If a change caused - * a fold to be removed, we need to continue at least until where - * it ended. */ + // For "marker", "expr" and "syntax" methods: If a change caused + // a fold to be removed, we need to continue at least until where + // it ended. if (getlevel != foldlevelMarker && getlevel != foldlevelSyntax && getlevel != foldlevelExpr) { @@ -2334,17 +2332,17 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level, * firstlnum. */ while (!got_int) { - /* set concat to 1 if it's allowed to concatenated this fold - * with a previous one that touches it. */ + // set concat to 1 if it's allowed to concatenated this fold + // with a previous one that touches it. if (flp->start != 0 || flp->had_end <= MAX_LEVEL) { concat = 0; } else { concat = 1; } - /* Find an existing fold to re-use. Preferably one that - * includes startlnum, otherwise one that ends just before - * startlnum or starts after it. */ + // Find an existing fold to re-use. Preferably one that + // includes startlnum, otherwise one that ends just before + // startlnum or starts after it. if (gap->ga_len > 0 && (foldFind(gap, startlnum, &fp) || (fp < ((fold_T *)gap->ga_data) + gap->ga_len @@ -2405,9 +2403,9 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level, i = (int)(fp - (fold_T *)gap->ga_data); foldSplit(flp->wp->w_buffer, 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 - * found. */ + // If using the "marker" or "syntax" method, we + // need to continue until the end of the fold is + // found. if (getlevel == foldlevelMarker || getlevel == foldlevelExpr || getlevel == foldlevelSyntax) { @@ -2433,8 +2431,8 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level, deleteFoldEntry(flp->wp, gap, (int)(fp - (fold_T *)gap->ga_data), true); } else { - /* A fold has some lines above startlnum, truncate it - * to stop just above startlnum. */ + // A fold has some lines above startlnum, truncate it + // to stop just above startlnum. fp->fd_len = startlnum - fp->fd_top; foldMarkAdjustRecurse(flp->wp, &fp->fd_nested, fp->fd_len, (linenr_T)MAXLNUM, @@ -2442,8 +2440,8 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level, fold_changed = true; } } else { - /* Insert new fold. Careful: ga_data may be NULL and it - * may change! */ + // Insert new fold. Careful: ga_data may be NULL and it + // may change! if (gap->ga_len == 0) { i = 0; } else { @@ -2451,13 +2449,13 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level, } foldInsert(gap, i); fp = (fold_T *)gap->ga_data + i; - /* The new fold continues until bot, unless we find the - * end earlier. */ + // The new fold continues until bot, unless we find the + // end earlier. fp->fd_top = firstlnum; fp->fd_len = bot - firstlnum + 1; - /* When the containing fold is open, the new fold is open. - * The new fold is closed if the fold above it is closed. - * The first fold depends on the containing fold. */ + // When the containing fold is open, the new fold is open. + // The new fold is closed if the fold above it is closed. + // The first fold depends on the containing fold. if (topflags == FD_OPEN) { flp->wp->w_fold_manual = true; fp->fd_flags = FD_OPEN; @@ -2684,8 +2682,8 @@ static void foldSplit(buf_T *buf, garray_T *const gap, const int i, const linenr fp[1].fd_small = kNone; fp->fd_small = kNone; - /* Move nested folds below bot to new fold. There can't be - * any between top and bot, they have been removed by the caller. */ + // Move nested folds below bot to new fold. There can't be + // any between top and bot, they have been removed by the caller. garray_T *const gap1 = &fp->fd_nested; garray_T *const gap2 = &fp[1].fd_nested; if (foldFind(gap1, bot + 1 - fp->fd_top, &fp2)) { @@ -3039,8 +3037,8 @@ static void foldlevelExpr(fline_T *flp) flp->lvl = 0; } - /* KeyTyped may be reset to 0 when calling a function which invokes - * do_cmdline(). To make 'foldopen' work correctly restore KeyTyped. */ + // KeyTyped may be reset to 0 when calling a function which invokes + // do_cmdline(). To make 'foldopen' work correctly restore KeyTyped. const bool save_keytyped = KeyTyped; const int n = eval_foldexpr(flp->wp->w_p_fde, &c); KeyTyped = save_keytyped; @@ -3308,9 +3306,9 @@ static int put_foldopen_recurse(FILE *fd, win_T *wp, garray_T *gap, linenr_T off } } } else { - /* Open or close the leaf according to the window foldlevel. - * Do not close a leaf that is already closed, as it will close - * the parent. */ + // Open or close the leaf according to the window foldlevel. + // Do not close a leaf that is already closed, as it will close + // the parent. level = foldLevelWin(wp, off + fp->fd_top); if ((fp->fd_flags == FD_CLOSED && wp->w_p_fdl >= level) || (fp->fd_flags != FD_CLOSED && wp->w_p_fdl < level)) { diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index eb836b9005..5267b313c7 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -144,10 +144,9 @@ static int KeyNoremap = 0; // remapping flags #define RM_SCRIPT 2 // tb_noremap: remap local script mappings #define RM_ABBR 4 // tb_noremap: don't remap, do abbrev. -/* typebuf.tb_buf has three parts: room in front (for result of mappings), the - * middle for typeahead and room for new characters (which needs to be 3 * - * MAXMAPLEN) for the Amiga). - */ +// typebuf.tb_buf has three parts: room in front (for result of mappings), the +// middle for typeahead and room for new characters (which needs to be 3 * +// MAXMAPLEN) for the Amiga). #define TYPELEN_INIT (5 * (MAXMAPLEN + 3)) static char_u typebuf_init[TYPELEN_INIT]; // initial typebuf.tb_buf static char_u noremapbuf_init[TYPELEN_INIT]; // initial typebuf.tb_noremap @@ -265,7 +264,7 @@ static void add_buff(buffheader_T *const buf, const char *const s, ptrdiff_t sle buf->bh_space = 0; buf->bh_curr = &(buf->bh_first); } else if (buf->bh_curr == NULL) { // buffer has already been read - IEMSG(_("E222: Add to read buffer")); + iemsg(_("E222: Add to read buffer")); return; } else if (buf->bh_index != 0) { memmove(buf->bh_first.b_next->b_str, @@ -682,7 +681,7 @@ static int read_redo(bool init, bool old_redo) if ((c = *p) == NUL) { return c; } - // Reverse the conversion done by add_char_buff() */ + // Reverse the conversion done by add_char_buff() // For a multi-byte character get all the bytes and return the // converted character. if (c != K_SPECIAL || p[1] == KS_SPECIAL) { @@ -900,7 +899,7 @@ int ins_typebuf(char_u *str, int noremap, int offset, bool nottyped, bool silent newoff = MAXMAPLEN + 4; newlen = typebuf.tb_len + addlen + newoff + 4 * (MAXMAPLEN + 4); if (newlen < 0) { // string is getting too long - EMSG(_(e_toocompl)); // also calls flush_buffers + emsg(_(e_toocompl)); // also calls flush_buffers setcursor(); return FAIL; } @@ -966,9 +965,9 @@ int ins_typebuf(char_u *str, int noremap, int offset, bool nottyped, bool silent (char_u)((--nrm >= 0) ? val : RM_YES); } - /* tb_maplen and tb_silent only remember the length of mapped and/or - * silent mappings at the start of the buffer, assuming that a mapped - * sequence doesn't result in typed characters. */ + // tb_maplen and tb_silent only remember the length of mapped and/or + // silent mappings at the start of the buffer, assuming that a mapped + // sequence doesn't result in typed characters. if (nottyped || typebuf.tb_maplen > offset) { typebuf.tb_maplen += addlen; } @@ -1116,8 +1115,8 @@ void del_typebuf(int len, int offset) } } - /* Reset the flag that text received from a client or from feedkeys() - * was inserted in the typeahead buffer. */ + // Reset the flag that text received from a client or from feedkeys() + // was inserted in the typeahead buffer. typebuf_was_filled = false; if (++typebuf.tb_change_cnt == 0) { typebuf.tb_change_cnt = 1; @@ -1167,9 +1166,9 @@ static void gotchars(const char_u *chars, size_t len) // output "debug mode" message next time in debug mode debug_did_msg = false; - /* Since characters have been typed, consider the following to be in - * another mapping. Search string will be kept in history. */ - ++maptick; + // Since characters have been typed, consider the following to be in + // another mapping. Search string will be kept in history. + maptick++; } /* @@ -1287,7 +1286,7 @@ void restore_typeahead(tasave_T *tp) void openscript(char_u *name, bool directly) { if (curscript + 1 == NSCRIPT) { - EMSG(_(e_nesting)); + emsg(_(e_nesting)); return; } @@ -1310,7 +1309,7 @@ void openscript(char_u *name, bool directly) int error; if ((scriptin[curscript] = file_open_new(&error, (char *)NameBuff, kFileReadOnly, 0)) == NULL) { - emsgf(_(e_notopen_2), name, os_strerror(error)); + semsg(_(e_notopen_2), name, os_strerror(error)); if (curscript) { curscript--; } @@ -1561,8 +1560,7 @@ int vgetc(void) buf[0] = (char_u)c; for (i = 1; i < n; i++) { buf[i] = (char_u)vgetorpeek(true); - if (buf[i] == K_SPECIAL - ) { + if (buf[i] == K_SPECIAL) { // Must be a K_SPECIAL - KS_SPECIAL - KE_FILLER sequence, // which represents a K_SPECIAL (0x80), // or a CSI - KS_EXTRA - KE_CSI sequence, which represents @@ -1581,7 +1579,8 @@ int vgetc(void) // If mappings are enabled (i.e., not Ctrl-v) and the user directly typed // something with a meta- or alt- modifier that was not mapped, interpret // <M-x> as <Esc>x rather than as an unbound meta keypress. #8213 - if (!no_mapping && KeyTyped + // In Terminal mode, however, this is not desirable. #16220 + if (!no_mapping && KeyTyped && !(State & TERM_FOCUS) && (mod_mask == MOD_MASK_ALT || mod_mask == MOD_MASK_META)) { mod_mask = 0; ins_char_typebuf(c); @@ -1691,7 +1690,7 @@ void vungetc(int c) old_mouse_col = mouse_col; } -/// Gets a character: +/// Gets a byte: /// 1. from the stuffbuffer /// This is used for abbreviated commands like "D" -> "d$". /// Also used to redo a command for ".". @@ -1823,8 +1822,8 @@ static int vgetorpeek(bool advance) flush_buffers(FLUSH_INPUT); // flush all typeahead if (advance) { - /* Also record this character, it might be needed to - * get out of Insert mode. */ + // Also record this character, it might be needed to + // get out of Insert mode. *typebuf.tb_buf = (char_u)c; gotchars(typebuf.tb_buf, 1); } @@ -2076,7 +2075,7 @@ static int vgetorpeek(bool advance) * The depth check catches ":map x y" and ":map y x". */ if (++mapdepth >= p_mmd) { - EMSG(_("E223: recursive mapping")); + emsg(_("E223: recursive mapping")); if (State & CMDLINE) { redrawcmdline(); } else { @@ -2311,13 +2310,13 @@ static int vgetorpeek(bool advance) /* * get a character: 3. from the user - update display */ - /* In insert mode a screen update is skipped when characters - * are still available. But when those available characters - * are part of a mapping, and we are going to do a blocking - * wait here. Need to update the screen to display the - * changed text so far. Also for when 'lazyredraw' is set and - * redrawing was postponed because there was something in the - * input buffer (e.g., termresponse). */ + // In insert mode a screen update is skipped when characters + // are still available. But when those available characters + // are part of a mapping, and we are going to do a blocking + // wait here. Need to update the screen to display the + // changed text so far. Also for when 'lazyredraw' is set and + // redrawing was postponed because there was something in the + // input buffer (e.g., termresponse). if (((State & INSERT) != 0 || p_lz) && (State & CMDLINE) == 0 && advance && must_redraw != 0 && !need_wait_return) { update_screen(0); @@ -2889,7 +2888,7 @@ int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, buf_T if (same == -1 && last != first) { same = n - 1; // count of same char type } - p += (*mb_ptr2len)(p); + p += utfc_ptr2len(p); } if (last && n > 2 && same >= 0 && same < n - 1) { retval = 1; @@ -2932,10 +2931,10 @@ int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, buf_T && args->unique && STRNCMP(mp->m_keys, lhs, (size_t)len) == 0) { if (is_abbrev) { - EMSG2(_("E224: global abbreviation already exists for %s"), + semsg(_("E224: global abbreviation already exists for %s"), mp->m_keys); } else { - EMSG2(_("E225: global mapping already exists for %s"), mp->m_keys); + semsg(_("E225: global mapping already exists for %s"), mp->m_keys); } retval = 5; goto theend; @@ -3031,9 +3030,9 @@ int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, buf_T continue; } else if (args->unique) { if (is_abbrev) { - EMSG2(_("E226: abbreviation already exists for %s"), p); + semsg(_("E226: abbreviation already exists for %s"), p); } else { - EMSG2(_("E227: mapping already exists for %s"), p); + semsg(_("E227: mapping already exists for %s"), p); } retval = 5; goto theend; @@ -3092,9 +3091,9 @@ int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, buf_T if (!has_lhs || !has_rhs) { // print entries if (!did_it && !did_local) { if (is_abbrev) { - MSG(_("No abbreviation found")); + msg(_("No abbreviation found")); } else { - MSG(_("No mapping found")); + msg(_("No mapping found")); } } goto theend; // listing finished @@ -3293,7 +3292,7 @@ void map_clear_mode(char_u *cmdp, char_u *arg, int forceit, int abbr) local = (STRCMP(arg, "<buffer>") == 0); if (!local && *arg != NUL) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -3813,7 +3812,7 @@ bool check_abbr(int c, char_u *ptr, int col, int mincol) while (p > ptr + mincol) { p = mb_prevptr(ptr, p); if (ascii_isspace(*p) || (!vim_abbr && is_id != vim_iswordp(p))) { - p += (*mb_ptr2len)(p); + p += utfc_ptr2len(p); break; } ++clen; @@ -3997,8 +3996,8 @@ char_u *vim_strsave_escape_csi(char_u *p) } else { // 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); - s += MB_CPTR2LEN(s); + d = add_char2buf(utf_ptr2char(s), d); + s += utf_ptr2len(s); } } *d = NUL; @@ -4169,7 +4168,7 @@ int makemap(FILE *fd, buf_T *buf) c1 = 't'; break; default: - IEMSG(_("E228: makemap: Illegal mode")); + iemsg(_("E228: makemap: Illegal mode")); return FAIL; } do { @@ -4532,7 +4531,7 @@ char_u *getcmdkeycmd(int promptc, void *cookie, int indent, bool do_concat) if (vgetorpeek(false) == NUL) { // incomplete <Cmd> is an error, because there is not much the user // could do in this state. - EMSG(e_cmdmap_err); + emsg(e_cmdmap_err); aborted = true; break; } @@ -4559,13 +4558,13 @@ char_u *getcmdkeycmd(int promptc, void *cookie, int indent, bool do_concat) aborted = true; } else if (c1 == K_COMMAND) { // special case to give nicer error message - EMSG(e_cmdmap_repeated); + emsg(e_cmdmap_repeated); aborted = true; } else if (IS_SPECIAL(c1)) { if (c1 == K_SNR) { ga_concat(&line_ga, "<SNR>"); } else { - EMSG2(e_cmdmap_key, get_special_key_name(c1, cmod)); + semsg(e_cmdmap_key, get_special_key_name(c1, cmod)); aborted = true; } } else { diff --git a/src/nvim/getchar.h b/src/nvim/getchar.h index 4e9dd2eab7..5950611d3f 100644 --- a/src/nvim/getchar.h +++ b/src/nvim/getchar.h @@ -21,7 +21,7 @@ enum RemapValues { typedef enum { FLUSH_MINIMAL, FLUSH_TYPEAHEAD, // flush current typebuf contents - FLUSH_INPUT // flush typebuf and inchar() input + FLUSH_INPUT, // flush typebuf and inchar() input } flush_buffers_T; /// All possible |:map-arguments| usable in a |:map| command. @@ -63,7 +63,7 @@ typedef struct map_arguments MapArguments; #define KEYLEN_PART_MAP -2 // keylen value for incomplete mapping /// Maximum number of streams to read script from -enum { NSCRIPT = 15 }; +enum { NSCRIPT = 15, }; /// Streams to read script from extern FileDescriptor *scriptin[NSCRIPT]; diff --git a/src/nvim/gettext.h b/src/nvim/gettext.h index 629301e8fe..6d2a55124e 100644 --- a/src/nvim/gettext.h +++ b/src/nvim/gettext.h @@ -10,7 +10,7 @@ # else # define N_(x) x # endif -# define NGETTEXT(x, xs, n) ngettext(x, xs, n) +# define NGETTEXT(x, xs, n) ngettext(x, xs, (unsigned long)n) // On a Mac, gettext's libintl.h defines "setlocale" to be replaced by // "libintl_setlocal" which leads to wrong return values. #9789 # if defined(__APPLE__) && defined(setlocale) diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 73cfffb0fb..e2d3378402 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -363,7 +363,7 @@ EXTERN int t_colors INIT(= 256); // int value of T_CCO // a match within one line), search_match_endcol the column number of the // character just after the match in the last line. EXTERN bool highlight_match INIT(= false); // show search match pos -EXTERN linenr_T search_match_lines; // lines of of matched string +EXTERN linenr_T search_match_lines; // lines of matched string EXTERN colnr_T search_match_endcol; // col nr of match end EXTERN linenr_T search_first_line INIT(= 0); // for :{FIRST},{last}s/pat EXTERN linenr_T search_last_line INIT(= MAXLNUM); // for :{first},{LAST}s/pat @@ -845,154 +845,156 @@ EXTERN linenr_T spell_redraw_lnum INIT(= 0); // The error messages that can be shared are included here. // Excluded are errors that are only used once and debugging messages. -EXTERN char_u e_abort[] INIT(= N_("E470: Command aborted")); -EXTERN char_u e_afterinit[] INIT(= N_("E905: Cannot set this option after startup")); -EXTERN char_u e_api_spawn_failed[] INIT(= N_("E903: Could not spawn API job")); -EXTERN char_u e_argreq[] INIT(= N_("E471: Argument required")); -EXTERN char_u e_backslash[] INIT(= N_("E10: \\ should be followed by /, ? or &")); -EXTERN char_u e_cmdwin[] INIT(= - N_( - "E11: Invalid in command-line window; <CR> executes, CTRL-C quits")); -EXTERN char_u e_curdir[] INIT(= - N_( - "E12: Command not allowed from exrc/vimrc in current dir or tag search")); -EXTERN char_u e_endif[] INIT(= N_("E171: Missing :endif")); -EXTERN char_u e_endtry[] INIT(= N_("E600: Missing :endtry")); -EXTERN char_u e_endwhile[] INIT(= N_("E170: Missing :endwhile")); -EXTERN char_u e_endfor[] INIT(= N_("E170: Missing :endfor")); -EXTERN char_u e_while[] INIT(= N_("E588: :endwhile without :while")); -EXTERN char_u e_for[] INIT(= N_("E588: :endfor without :for")); -EXTERN char_u e_exists[] INIT(= N_("E13: File exists (add ! to override)")); -EXTERN char_u e_failed[] INIT(= N_("E472: Command failed")); -EXTERN char_u e_internal[] INIT(= N_("E473: Internal error")); -EXTERN char_u e_intern2[] INIT(= N_("E685: Internal error: %s")); -EXTERN char_u e_interr[] INIT(= N_("Interrupted")); -EXTERN char_u e_invarg[] INIT(= N_("E474: Invalid argument")); -EXTERN char_u e_invarg2[] INIT(= N_("E475: Invalid argument: %s")); -EXTERN char_u e_invargval[] INIT(= N_("E475: Invalid value for argument %s")); -EXTERN char_u e_invargNval[] INIT(= N_("E475: Invalid value for argument %s: %s")); -EXTERN char_u e_duparg2[] INIT(= N_("E983: Duplicate argument: %s")); -EXTERN char_u e_invexpr2[] INIT(= N_("E15: Invalid expression: %s")); -EXTERN char_u e_invrange[] INIT(= N_("E16: Invalid range")); -EXTERN char_u e_invcmd[] INIT(= N_("E476: Invalid command")); -EXTERN char_u e_isadir2[] INIT(= N_("E17: \"%s\" is a directory")); -EXTERN char_u e_no_spell[] INIT(= N_("E756: Spell checking is not possible")); -EXTERN char_u e_invchan[] INIT(= N_("E900: Invalid channel id")); -EXTERN char_u e_invchanjob[] INIT(= N_("E900: Invalid channel id: not a job")); -EXTERN char_u e_jobtblfull[] INIT(= N_("E901: Job table is full")); -EXTERN char_u e_jobspawn[] INIT(= N_("E903: Process failed to start: %s: \"%s\"")); -EXTERN char_u e_channotpty[] INIT(= N_("E904: channel is not a pty")); -EXTERN char_u e_stdiochan2[] INIT(= N_("E905: Couldn't open stdio channel: %s")); -EXTERN char_u e_invstream[] INIT(= N_("E906: invalid stream for channel")); -EXTERN char_u e_invstreamrpc[] INIT(= N_("E906: invalid stream for rpc channel, use 'rpc'")); -EXTERN char_u e_streamkey[] INIT(= - N_( - "E5210: dict key '%s' already set for buffered stream in channel %" - PRIu64)); -EXTERN char_u e_libcall[] INIT(= N_("E364: Library call failed for \"%s()\"")); +EXTERN char e_abort[] INIT(= N_("E470: Command aborted")); +EXTERN char e_afterinit[] INIT(= N_("E905: Cannot set this option after startup")); +EXTERN char e_api_spawn_failed[] INIT(= N_("E903: Could not spawn API job")); +EXTERN char e_argreq[] INIT(= N_("E471: Argument required")); +EXTERN char e_backslash[] INIT(= N_("E10: \\ should be followed by /, ? or &")); +EXTERN char e_cmdwin[] INIT(= + N_( + "E11: Invalid in command-line window; <CR> executes, CTRL-C quits")); +EXTERN char e_curdir[] INIT(= + N_( + "E12: Command not allowed from exrc/vimrc in current dir or tag search")); +EXTERN char e_endif[] INIT(= N_("E171: Missing :endif")); +EXTERN char e_endtry[] INIT(= N_("E600: Missing :endtry")); +EXTERN char e_endwhile[] INIT(= N_("E170: Missing :endwhile")); +EXTERN char e_endfor[] INIT(= N_("E170: Missing :endfor")); +EXTERN char e_while[] INIT(= N_("E588: :endwhile without :while")); +EXTERN char e_for[] INIT(= N_("E588: :endfor without :for")); +EXTERN char e_exists[] INIT(= N_("E13: File exists (add ! to override)")); +EXTERN char e_failed[] INIT(= N_("E472: Command failed")); +EXTERN char e_internal[] INIT(= N_("E473: Internal error")); +EXTERN char e_intern2[] INIT(= N_("E685: Internal error: %s")); +EXTERN char e_interr[] INIT(= N_("Interrupted")); +EXTERN char e_invarg[] INIT(= N_("E474: Invalid argument")); +EXTERN char e_invarg2[] INIT(= N_("E475: Invalid argument: %s")); +EXTERN char e_invargval[] INIT(= N_("E475: Invalid value for argument %s")); +EXTERN char e_invargNval[] INIT(= N_("E475: Invalid value for argument %s: %s")); +EXTERN char e_duparg2[] INIT(= N_("E983: Duplicate argument: %s")); +EXTERN char e_invexpr2[] INIT(= N_("E15: Invalid expression: %s")); +EXTERN char e_invrange[] INIT(= N_("E16: Invalid range")); +EXTERN char e_invcmd[] INIT(= N_("E476: Invalid command")); +EXTERN char e_isadir2[] INIT(= N_("E17: \"%s\" is a directory")); +EXTERN char e_no_spell[] INIT(= N_("E756: Spell checking is not possible")); +EXTERN char e_invchan[] INIT(= N_("E900: Invalid channel id")); +EXTERN char e_invchanjob[] INIT(= N_("E900: Invalid channel id: not a job")); +EXTERN char e_jobtblfull[] INIT(= N_("E901: Job table is full")); +EXTERN char e_jobspawn[] INIT(= N_("E903: Process failed to start: %s: \"%s\"")); +EXTERN char e_channotpty[] INIT(= N_("E904: channel is not a pty")); +EXTERN char e_stdiochan2[] INIT(= N_("E905: Couldn't open stdio channel: %s")); +EXTERN char e_invstream[] INIT(= N_("E906: invalid stream for channel")); +EXTERN char e_invstreamrpc[] INIT(= N_("E906: invalid stream for rpc channel, use 'rpc'")); +EXTERN char e_streamkey[] INIT(= + N_( + "E5210: dict key '%s' already set for buffered stream in channel %" + PRIu64)); +EXTERN char e_libcall[] INIT(= N_("E364: Library call failed for \"%s()\"")); EXTERN char e_fsync[] INIT(= N_("E667: Fsync failed: %s")); -EXTERN char_u e_mkdir[] INIT(= N_("E739: Cannot create directory %s: %s")); -EXTERN char_u e_markinval[] INIT(= N_("E19: Mark has invalid line number")); -EXTERN char_u e_marknotset[] INIT(= N_("E20: Mark not set")); -EXTERN char_u e_modifiable[] INIT(= N_("E21: Cannot make changes, 'modifiable' is off")); -EXTERN char_u e_nesting[] INIT(= N_("E22: Scripts nested too deep")); -EXTERN char_u e_noalt[] INIT(= N_("E23: No alternate file")); -EXTERN char_u e_noabbr[] INIT(= N_("E24: No such abbreviation")); -EXTERN char_u e_nobang[] INIT(= N_("E477: No ! allowed")); -EXTERN char_u e_nogroup[] INIT(= N_("E28: No such highlight group name: %s")); -EXTERN char_u e_noinstext[] INIT(= N_("E29: No inserted text yet")); -EXTERN char_u e_nolastcmd[] INIT(= N_("E30: No previous command line")); -EXTERN char_u e_nomap[] INIT(= N_("E31: No such mapping")); -EXTERN char_u e_nomatch[] INIT(= N_("E479: No match")); -EXTERN char_u e_nomatch2[] INIT(= N_("E480: No match: %s")); -EXTERN char_u e_noname[] INIT(= N_("E32: No file name")); -EXTERN char_u e_nopresub[] INIT(= N_("E33: No previous substitute regular expression")); -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_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_notopen_2[] INIT(= N_("E484: Can't open file %s: %s")); -EXTERN char_u e_notread[] INIT(= N_("E485: Can't read file %s")); -EXTERN char_u e_null[] INIT(= N_("E38: Null argument")); -EXTERN char_u e_number_exp[] INIT(= N_("E39: Number expected")); -EXTERN char_u e_openerrf[] INIT(= N_("E40: Can't open errorfile %s")); -EXTERN char_u e_outofmem[] INIT(= N_("E41: Out of memory!")); -EXTERN char_u e_patnotf[] INIT(= N_("Pattern not found")); -EXTERN char_u e_patnotf2[] INIT(= N_("E486: Pattern not found: %s")); -EXTERN char_u e_positive[] INIT(= N_("E487: Argument must be positive")); -EXTERN char_u e_prev_dir[] INIT(= N_("E459: Cannot go back to previous directory")); - -EXTERN char_u e_quickfix[] INIT(= N_("E42: No Errors")); -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_stringreq[] INIT(= N_("E928: String required")); -EXTERN char_u e_dictreq[] INIT(= N_("E715: Dictionary required")); -EXTERN char_u e_blobidx[] INIT(= N_("E979: Blob index out of range: %" PRId64)); -EXTERN char_u e_invalblob[] INIT(= N_("E978: Invalid operation for Blob")); -EXTERN char_u e_toomanyarg[] INIT(= N_("E118: Too many arguments for function: %s")); -EXTERN char_u e_dictkey[] INIT(= N_("E716: Key not present in Dictionary: \"%s\"")); -EXTERN char_u e_listreq[] INIT(= N_("E714: List required")); -EXTERN char_u e_listblobreq[] INIT(= N_("E897: List or Blob required")); -EXTERN char_u e_listdictarg[] INIT(= N_("E712: Argument of %s must be a List or Dictionary")); -EXTERN char_u e_listdictblobarg[] INIT(= - N_( - "E896: Argument of %s must be a List, Dictionary or Blob")); -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")); -EXTERN char_u e_screenmode[] INIT(= N_("E359: Screen mode setting not supported")); -EXTERN char_u e_scroll[] INIT(= N_("E49: Invalid scroll size")); -EXTERN char_u e_shellempty[] INIT(= N_("E91: 'shell' option is empty")); -EXTERN char_u e_signdata[] INIT(= N_("E255: Couldn't read in sign data!")); -EXTERN char_u e_swapclose[] INIT(= N_("E72: Close error on swap file")); -EXTERN char_u e_tagstack[] INIT(= N_("E73: tag stack empty")); -EXTERN char_u e_toocompl[] INIT(= N_("E74: Command too complex")); -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_("E591: 'winheight' cannot be smaller than 'winminheight'")); -EXTERN char_u e_winwidth[] INIT(= N_("E592: 'winwidth' cannot be smaller than 'winminwidth'")); -EXTERN char_u e_write[] INIT(= N_("E80: Error while writing")); -EXTERN char_u e_zerocount[] INIT(= N_("E939: Positive count required")); -EXTERN char_u e_usingsid[] INIT(= N_("E81: Using <SID> not in a script context")); -EXTERN char_u e_missingparen[] INIT(= N_("E107: Missing parentheses: %s")); -EXTERN char_u e_maxmempat[] INIT(= N_("E363: pattern uses more memory than 'maxmempattern'")); -EXTERN char_u e_emptybuf[] INIT(= N_("E749: empty buffer")); -EXTERN char_u e_nobufnr[] INIT(= N_("E86: Buffer %" PRId64 " does not exist")); - -EXTERN char_u e_invalpat[] INIT(= N_("E682: Invalid search pattern or delimiter")); -EXTERN char_u e_bufloaded[] INIT(= N_("E139: File is loaded in another buffer")); -EXTERN char_u e_notset[] INIT(= N_("E764: Option '%s' is not set")); -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_au_recursive[] INIT(= N_("E952: Autocommand caused recursive behavior")); -EXTERN char_u e_autocmd_close[] INIT(= N_("E813: Cannot close autocmd window")); -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_u e_autocmd_err[] INIT(=N_("E5500: autocmd has thrown an exception: %s")); -EXTERN char_u e_cmdmap_err[] INIT(=N_("E5520: <Cmd> mapping must end with <CR>")); -EXTERN char_u +EXTERN char e_mkdir[] INIT(= N_("E739: Cannot create directory %s: %s")); +EXTERN char e_markinval[] INIT(= N_("E19: Mark has invalid line number")); +EXTERN char e_marknotset[] INIT(= N_("E20: Mark not set")); +EXTERN char e_modifiable[] INIT(= N_("E21: Cannot make changes, 'modifiable' is off")); +EXTERN char e_nesting[] INIT(= N_("E22: Scripts nested too deep")); +EXTERN char e_noalt[] INIT(= N_("E23: No alternate file")); +EXTERN char e_noabbr[] INIT(= N_("E24: No such abbreviation")); +EXTERN char e_nobang[] INIT(= N_("E477: No ! allowed")); +EXTERN char e_nogroup[] INIT(= N_("E28: No such highlight group name: %s")); +EXTERN char e_noinstext[] INIT(= N_("E29: No inserted text yet")); +EXTERN char e_nolastcmd[] INIT(= N_("E30: No previous command line")); +EXTERN char e_nomap[] INIT(= N_("E31: No such mapping")); +EXTERN char e_nomatch[] INIT(= N_("E479: No match")); +EXTERN char e_nomatch2[] INIT(= N_("E480: No match: %s")); +EXTERN char e_noname[] INIT(= N_("E32: No file name")); +EXTERN char e_nopresub[] INIT(= N_("E33: No previous substitute regular expression")); +EXTERN char e_noprev[] INIT(= N_("E34: No previous command")); +EXTERN char e_noprevre[] INIT(= N_("E35: No previous regular expression")); +EXTERN char e_norange[] INIT(= N_("E481: No range allowed")); +EXTERN char e_noroom[] INIT(= N_("E36: Not enough room")); +EXTERN char e_notmp[] INIT(= N_("E483: Can't get temp file name")); +EXTERN char e_notopen[] INIT(= N_("E484: Can't open file %s")); +EXTERN char e_notopen_2[] INIT(= N_("E484: Can't open file %s: %s")); +EXTERN char e_notread[] INIT(= N_("E485: Can't read file %s")); +EXTERN char e_null[] INIT(= N_("E38: Null argument")); +EXTERN char e_number_exp[] INIT(= N_("E39: Number expected")); +EXTERN char e_openerrf[] INIT(= N_("E40: Can't open errorfile %s")); +EXTERN char e_outofmem[] INIT(= N_("E41: Out of memory!")); +EXTERN char e_patnotf[] INIT(= N_("Pattern not found")); +EXTERN char e_patnotf2[] INIT(= N_("E486: Pattern not found: %s")); +EXTERN char e_positive[] INIT(= N_("E487: Argument must be positive")); +EXTERN char e_prev_dir[] INIT(= N_("E459: Cannot go back to previous directory")); + +EXTERN char e_quickfix[] INIT(= N_("E42: No Errors")); +EXTERN char e_loclist[] INIT(= N_("E776: No location list")); +EXTERN char e_re_damg[] INIT(= N_("E43: Damaged match string")); +EXTERN char e_re_corr[] INIT(= N_("E44: Corrupted regexp program")); +EXTERN char e_readonly[] INIT(= N_("E45: 'readonly' option is set (add ! to override)")); +EXTERN char e_readonlyvar[] INIT(= N_("E46: Cannot change read-only variable \"%.*s\"")); +EXTERN char e_stringreq[] INIT(= N_("E928: String required")); +EXTERN char e_dictreq[] INIT(= N_("E715: Dictionary required")); +EXTERN char e_blobidx[] INIT(= N_("E979: Blob index out of range: %" PRId64)); +EXTERN char e_invalblob[] INIT(= N_("E978: Invalid operation for Blob")); +EXTERN char e_toomanyarg[] INIT(= N_("E118: Too many arguments for function: %s")); +EXTERN char e_dictkey[] INIT(= N_("E716: Key not present in Dictionary: \"%s\"")); +EXTERN char e_listreq[] INIT(= N_("E714: List required")); +EXTERN char e_listblobreq[] INIT(= N_("E897: List or Blob required")); +EXTERN char e_listdictarg[] INIT(= N_("E712: Argument of %s must be a List or Dictionary")); +EXTERN char e_listdictblobarg[] INIT(= + N_( + "E896: Argument of %s must be a List, Dictionary or Blob")); +EXTERN char e_readerrf[] INIT(= N_("E47: Error while reading errorfile")); +EXTERN char e_sandbox[] INIT(= N_("E48: Not allowed in sandbox")); +EXTERN char e_secure[] INIT(= N_("E523: Not allowed here")); +EXTERN char e_screenmode[] INIT(= N_("E359: Screen mode setting not supported")); +EXTERN char e_scroll[] INIT(= N_("E49: Invalid scroll size")); +EXTERN char e_shellempty[] INIT(= N_("E91: 'shell' option is empty")); +EXTERN char e_signdata[] INIT(= N_("E255: Couldn't read in sign data!")); +EXTERN char e_swapclose[] INIT(= N_("E72: Close error on swap file")); +EXTERN char e_tagstack[] INIT(= N_("E73: tag stack empty")); +EXTERN char e_toocompl[] INIT(= N_("E74: Command too complex")); +EXTERN char e_longname[] INIT(= N_("E75: Name too long")); +EXTERN char e_toomsbra[] INIT(= N_("E76: Too many [")); +EXTERN char e_toomany[] INIT(= N_("E77: Too many file names")); +EXTERN char e_trailing[] INIT(= N_("E488: Trailing characters")); +EXTERN char e_trailing2[] INIT(= N_("E488: Trailing characters: %s")); +EXTERN char e_umark[] INIT(= N_("E78: Unknown mark")); +EXTERN char e_wildexpand[] INIT(= N_("E79: Cannot expand wildcards")); +EXTERN char e_winheight[] INIT(= N_("E591: 'winheight' cannot be smaller than 'winminheight'")); +EXTERN char e_winwidth[] INIT(= N_("E592: 'winwidth' cannot be smaller than 'winminwidth'")); +EXTERN char e_write[] INIT(= N_("E80: Error while writing")); +EXTERN char e_zerocount[] INIT(= N_("E939: Positive count required")); +EXTERN char e_usingsid[] INIT(= N_("E81: Using <SID> not in a script context")); +EXTERN char e_missingparen[] INIT(= N_("E107: Missing parentheses: %s")); +EXTERN char e_maxmempat[] INIT(= N_("E363: pattern uses more memory than 'maxmempattern'")); +EXTERN char e_emptybuf[] INIT(= N_("E749: empty buffer")); +EXTERN char e_nobufnr[] INIT(= N_("E86: Buffer %" PRId64 " does not exist")); + +EXTERN char e_invalpat[] INIT(= N_("E682: Invalid search pattern or delimiter")); +EXTERN char e_bufloaded[] INIT(= N_("E139: File is loaded in another buffer")); +EXTERN char e_notset[] INIT(= N_("E764: Option '%s' is not set")); +EXTERN char e_invalidreg[] INIT(= N_("E850: Invalid register name")); +EXTERN char e_dirnotf[] INIT(= N_("E919: Directory not found in '%s': \"%s\"")); +EXTERN char e_au_recursive[] INIT(= N_("E952: Autocommand caused recursive behavior")); +EXTERN char e_autocmd_close[] INIT(= N_("E813: Cannot close autocmd window")); +EXTERN char e_unsupportedoption[] INIT(= N_("E519: Option not supported")); +EXTERN char e_fnametoolong[] INIT(= N_("E856: Filename too long")); +EXTERN char e_float_as_string[] INIT(= N_("E806: using Float as a String")); + +EXTERN char e_autocmd_err[] INIT(=N_("E5500: autocmd has thrown an exception: %s")); +EXTERN char e_cmdmap_err[] INIT(=N_("E5520: <Cmd> mapping must end with <CR>")); +EXTERN char e_cmdmap_repeated[] INIT(=N_("E5521: <Cmd> mapping must end with <CR> before second <Cmd>")); -EXTERN char_u e_cmdmap_key[] INIT(=N_("E5522: <Cmd> mapping must not include %s key")); +EXTERN char e_cmdmap_key[] INIT(=N_("E5522: <Cmd> mapping must not include %s key")); -EXTERN char_u e_api_error[] INIT(=N_("E5555: API call: %s")); +EXTERN char e_api_error[] INIT(=N_("E5555: API call: %s")); EXTERN char e_luv_api_disabled[] INIT(=N_("E5560: %s must not be called in a lua loop callback")); -EXTERN char_u e_floatonly[] INIT(=N_( - "E5601: Cannot close window, only floating window would remain")); -EXTERN char_u e_floatexchange[] INIT(=N_("E5602: Cannot exchange or rotate float")); +EXTERN char e_floatonly[] INIT(=N_( + "E5601: Cannot close window, only floating window would remain")); +EXTERN char e_floatexchange[] INIT(=N_("E5602: Cannot exchange or rotate float")); + +EXTERN char e_non_empty_string_required[] INIT(= N_("E1142: Non-empty string required")); EXTERN char e_cannot_define_autocommands_for_all_events[] INIT(= N_( @@ -1023,7 +1025,7 @@ EXTERN bool headless_mode INIT(= false); typedef enum { kUnknown, kWorking, - kBroken + kBroken, } WorkingStatus; /// The scope of a working-directory command like `:cd`. diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c index 0b828777f4..296c5cbdbf 100644 --- a/src/nvim/hardcopy.c +++ b/src/nvim/hardcopy.c @@ -263,7 +263,7 @@ struct prt_resfile_buffer_S { * Parse 'printoptions' and set the flags in "printer_opts". * Returns an error message or NULL; */ -char_u *parse_printoptions(void) +char *parse_printoptions(void) { return parse_list_options(p_popt, printer_opts, OPT_PRINT_NUM_OPTIONS); } @@ -272,7 +272,7 @@ char_u *parse_printoptions(void) * Parse 'printoptions' and set the flags in "printer_opts". * Returns an error message or NULL; */ -char_u *parse_printmbfont(void) +char *parse_printmbfont(void) { return parse_list_options(p_pmfn, mbfont_opts, OPT_MBFONT_NUM_OPTIONS); } @@ -286,10 +286,10 @@ char_u *parse_printmbfont(void) * Returns an error message for an illegal option, NULL otherwise. * Only used for the printer at the moment... */ -static char_u *parse_list_options(char_u *option_str, option_table_T *table, size_t table_size) +static char *parse_list_options(char_u *option_str, option_table_T *table, size_t table_size) { option_table_T *old_opts; - char_u *ret = NULL; + char *ret = NULL; char_u *stringp; char_u *colonp; char_u *commap; @@ -312,7 +312,7 @@ static char_u *parse_list_options(char_u *option_str, option_table_T *table, siz while (*stringp) { colonp = vim_strchr(stringp, ':'); if (colonp == NULL) { - ret = (char_u *)N_("E550: Missing colon"); + ret = N_("E550: Missing colon"); break; } commap = vim_strchr(stringp, ','); @@ -329,7 +329,7 @@ static char_u *parse_list_options(char_u *option_str, option_table_T *table, siz } if (idx == table_size) { - ret = (char_u *)N_("E551: Illegal component"); + ret = N_("E551: Illegal component"); break; } @@ -338,7 +338,7 @@ static char_u *parse_list_options(char_u *option_str, option_table_T *table, siz if (table[idx].hasnum) { if (!ascii_isdigit(*p)) { - ret = (char_u *)N_("E552: digit expected"); + ret = N_("E552: digit expected"); break; } @@ -572,7 +572,7 @@ static void prt_header(prt_settings_T *const psettings, const int pagenum, const int page_line = 0 - prt_header_height(); mch_print_start_line(true, page_line); for (char_u *p = tbuf; *p != NUL; ) { - const int l = (*mb_ptr2len)(p); + const int l = utfc_ptr2len(p); assert(l >= 0); if (mch_print_text_out(p, (size_t)l)) { page_line++; @@ -621,12 +621,12 @@ void ex_hardcopy(exarg_T *eap) settings.has_color = TRUE; if (*eap->arg == '>') { - char_u *errormsg = NULL; + char *errormsg = NULL; // Expand things like "%.ps". if (expand_filename(eap, eap->cmdlinep, &errormsg) == FAIL) { if (errormsg != NULL) { - EMSG(errormsg); + emsg(errormsg); } return; } @@ -684,7 +684,7 @@ void ex_hardcopy(exarg_T *eap) bytes_to_print += STRLEN(skipwhite(ml_get(lnum))); } if (bytes_to_print == 0) { - MSG(_("No text to be printed")); + msg(_("No text to be printed")); goto print_fail_no_begin; } @@ -794,8 +794,8 @@ void ex_hardcopy(exarg_T *eap) break; // reached the end } } else if (prtpos.ff) { - /* Line had a formfeed in it - start new page but - * stay on the current line */ + // Line had a formfeed in it - start new page but + // stay on the current line break; } } @@ -879,7 +879,7 @@ 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) { - if ((outputlen = (*mb_ptr2len)(line + col)) < 1) { + if ((outputlen = utfc_ptr2len(line + col)) < 1) { outputlen = 1; } // syntax highlighting stuff. @@ -1329,7 +1329,7 @@ static void prt_write_file_raw_len(char_u *buffer, size_t bytes) { if (!prt_file_error && fwrite(buffer, sizeof(char_u), bytes, prt_ps_fd) != bytes) { - EMSG(_("E455: Error writing to PostScript output file")); + emsg(_("E455: Error writing to PostScript output file")); prt_file_error = TRUE; } } @@ -1505,9 +1505,8 @@ static void prt_flush_buffer(void) prt_write_real(b / 255.0, 3); prt_write_string("bg\n"); } - /* Draw underlines before the text as it makes it slightly easier to - * find the starting point. - */ + // Draw underlines before the text as it makes it slightly easier to + // find the starting point. if (prt_do_underline) { if (prt_do_moveto) { prt_write_real(prt_pos_x_moveto, 2); @@ -1696,9 +1695,8 @@ static bool prt_next_dsc(struct prt_dsc_line_S *p_dsc_line) return true; } -/* Improved hand crafted parser to get the type, title, and version number of a - * PS resource file so the file details can be added to the DSC header comments. - */ +/// Improved hand crafted parser to get the type, title, and version number of a +/// PS resource file so the file details can be added to the DSC header comments. static bool prt_open_resource(struct prt_ps_resource_S *resource) FUNC_ATTR_NONNULL_ALL { @@ -1706,7 +1704,7 @@ static bool prt_open_resource(struct prt_ps_resource_S *resource) FILE *fd_resource = os_fopen((char *)resource->filename, READBIN); if (fd_resource == NULL) { - EMSG2(_("E624: Can't open file \"%s\""), resource->filename); + semsg(_("E624: Can't open file \"%s\""), resource->filename); return false; } memset(prt_resfile.buffer, NUL, PRT_FILE_BUFFER_LEN); @@ -1715,7 +1713,7 @@ static bool prt_open_resource(struct prt_ps_resource_S *resource) prt_resfile.len = (int)fread((char *)prt_resfile.buffer, sizeof(char_u), PRT_FILE_BUFFER_LEN, fd_resource); if (ferror(fd_resource)) { - EMSG2(_("E457: Can't read PostScript resource file \"%s\""), + semsg(_("E457: Can't read PostScript resource file \"%s\""), resource->filename); fclose(fd_resource); return false; @@ -1731,7 +1729,7 @@ static bool prt_open_resource(struct prt_ps_resource_S *resource) if (prt_resfile_strncmp(offset, PRT_RESOURCE_HEADER, (int)STRLEN(PRT_RESOURCE_HEADER)) != 0) { - EMSG2(_("E618: file \"%s\" is not a PostScript resource file"), + semsg(_("E618: file \"%s\" is not a PostScript resource file"), resource->filename); return false; } @@ -1748,7 +1746,7 @@ static bool prt_open_resource(struct prt_ps_resource_S *resource) } if (prt_resfile_strncmp(offset, PRT_RESOURCE_RESOURCE, (int)STRLEN(PRT_RESOURCE_RESOURCE)) != 0) { - EMSG2(_("E619: file \"%s\" is not a supported PostScript resource file"), + semsg(_("E619: file \"%s\" is not a supported PostScript resource file"), resource->filename); return false; } @@ -1765,7 +1763,7 @@ static bool prt_open_resource(struct prt_ps_resource_S *resource) (int)STRLEN(PRT_RESOURCE_CMAP)) == 0) { resource->type = PRT_RESOURCE_TYPE_CMAP; } else { - EMSG2(_("E619: file \"%s\" is not a supported PostScript resource file"), + semsg(_("E619: file \"%s\" is not a supported PostScript resource file"), resource->filename); return false; } @@ -1806,7 +1804,7 @@ static bool prt_open_resource(struct prt_ps_resource_S *resource) } if (!seen_title || !seen_version) { - EMSG2(_("E619: file \"%s\" is not a supported PostScript resource file"), + semsg(_("E619: file \"%s\" is not a supported PostScript resource file"), resource->filename); return false; } @@ -1819,7 +1817,7 @@ static bool prt_check_resource(const struct prt_ps_resource_S *resource, const c { // Version number m.n should match, the revision number does not matter if (STRNCMP(resource->version, version, STRLEN(version))) { - EMSG2(_("E621: \"%s\" resource file has wrong version"), + semsg(_("E621: \"%s\" resource file has wrong version"), resource->name); return false; } @@ -1906,9 +1904,8 @@ static void prt_dsc_font_resource(char *resource, struct prt_ps_font_S *ps_font) static void prt_dsc_requirements(int duplex, int tumble, int collate, int color, int num_copies) { - /* Only output the comment if we need to. - * Note: tumble is ignored if we are not duplexing - */ + // Only output the comment if we need to. + // Note: tumble is ignored if we are not duplexing if (!(duplex || collate || color || (num_copies > 1))) { return; } @@ -1967,10 +1964,9 @@ void mch_print_cleanup(void) if (prt_out_mbyte) { int i; - /* Free off all CID font names created, but first clear duplicate - * pointers to the same string (when the same font is used for more than - * one style). - */ + // Free off all CID font names created, but first clear duplicate + // pointers to the same string (when the same font is used for more than + // one style). for (i = PRT_PS_FONT_ROMAN; i <= PRT_PS_FONT_BOLDOBLIQUE; i++) { if (prt_ps_mb_font.ps_fontname[i] != NULL) { xfree(prt_ps_mb_font.ps_fontname[i]); @@ -2048,9 +2044,8 @@ static int prt_get_cpl(void) { if (prt_use_number()) { prt_number_width = PRINT_NUMBER_WIDTH * prt_char_width; - /* If we are outputting multi-byte characters then line numbers will be - * printed with half width characters - */ + // If we are outputting multi-byte characters then line numbers will be + // printed with half width characters if (prt_out_mbyte) { prt_number_width /= 2; } @@ -2168,10 +2163,10 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit) p_encoding = enc_skip(p_enc); } - /* Look for a multi-byte font that matches the encoding and character set. - * Only look if multi-byte character set is defined, or using multi-byte - * encoding other than Unicode. This is because a Unicode encoding does not - * uniquely identify a CJK character set to use. */ + // Look for a multi-byte font that matches the encoding and character set. + // Only look if multi-byte character set is defined, or using multi-byte + // encoding other than Unicode. This is because a Unicode encoding does not + // uniquely identify a CJK character set to use. p_mbenc = NULL; props = enc_canon_props(p_encoding); if (!(props & ENC_8BIT) && ((*p_pmcs != NUL) || !(props & ENC_UNICODE))) { @@ -2208,7 +2203,7 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit) if (!prt_custom_cmap) { // Check encoding and character set are compatible if ((p_mbenc->needs_charset & p_mbchar->has_charset) == 0) { - EMSG(_("E673: Incompatible multi-byte encoding and character set.")); + emsg(_("E673: Incompatible multi-byte encoding and character set.")); return FALSE; } @@ -2220,7 +2215,7 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit) } else { // Add custom CMap character set name if (*p_pmcs == NUL) { - EMSG(_("E674: printmbcharset cannot be empty with multi-byte encoding.")); + emsg(_("E674: printmbcharset cannot be empty with multi-byte encoding.")); return FALSE; } STRLCPY(prt_cmap, p_pmcs, sizeof(prt_cmap) - 2); @@ -2236,7 +2231,7 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit) STRCAT(prt_cmap, "H"); if (!mbfont_opts[OPT_MBFONT_REGULAR].present) { - EMSG(_("E675: No default font specified for multi-byte printing.")); + emsg(_("E675: No default font specified for multi-byte printing.")); return FALSE; } @@ -2399,7 +2394,7 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit) if (psettings->outfile == NULL) { prt_ps_file_name = vim_tempname(); if (prt_ps_file_name == NULL) { - EMSG(_(e_notmp)); + emsg(_(e_notmp)); return FAIL; } prt_ps_fd = os_fopen((char *)prt_ps_file_name, WRITEBIN); @@ -2411,7 +2406,7 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit) } } if (prt_ps_fd == NULL) { - EMSG(_("E324: Can't open PostScript output file")); + emsg(_("E324: Can't open PostScript output file")); mch_print_cleanup(); return FAIL; } @@ -2444,7 +2439,7 @@ static int prt_add_resource(struct prt_ps_resource_S *resource) fd_resource = os_fopen((char *)resource->filename, READBIN); if (fd_resource == NULL) { - EMSG2(_("E456: Can't open file \"%s\""), resource->filename); + semsg(_("E456: Can't open file \"%s\""), resource->filename); return FALSE; } switch (resource->type) { @@ -2464,7 +2459,7 @@ static int prt_add_resource(struct prt_ps_resource_S *resource) bytes_read = fread((char *)resource_buffer, sizeof(char_u), sizeof(resource_buffer), fd_resource); if (ferror(fd_resource)) { - EMSG2(_("E457: Can't read PostScript resource file \"%s\""), + semsg(_("E457: Can't read PostScript resource file \"%s\""), resource->filename); fclose(fd_resource); return FALSE; @@ -2526,28 +2521,26 @@ int mch_print_begin(prt_settings_T *psettings) prt_dsc_textline("Orientation", "Portrait"); prt_dsc_atend("Pages"); prt_dsc_textline("PageOrder", "Ascend"); - /* The bbox does not change with orientation - it is always in the default - * user coordinate system! We have to recalculate right and bottom - * coordinates based on the font metrics for the bbox to be accurate. */ + // The bbox does not change with orientation - it is always in the default + // user coordinate system! We have to recalculate right and bottom + // coordinates based on the font metrics for the bbox to be accurate. prt_page_margins(prt_mediasize[prt_media].width, prt_mediasize[prt_media].height, &left, &right, &top, &bottom); bbox[0] = (int)left; if (prt_portrait) { - /* In portrait printing the fixed point is the top left corner so we - * derive the bbox from that point. We have the expected cpl chars - * across the media and lpp lines down the media. - */ + // In portrait printing the fixed point is the top left corner so we + // derive the bbox from that point. We have the expected cpl chars + // across the media and lpp lines down the media. bbox[1] = (int)(top - (psettings->lines_per_page + prt_header_height()) * prt_line_height); bbox[2] = (int)(left + psettings->chars_per_line * prt_char_width + 0.5); bbox[3] = (int)(top + 0.5); } else { - /* In landscape printing the fixed point is the bottom left corner so we - * derive the bbox from that point. We have lpp chars across the media - * and cpl lines up the media. - */ + // In landscape printing the fixed point is the bottom left corner so we + // derive the bbox from that point. We have lpp chars across the media + // and cpl lines up the media. bbox[1] = (int)bottom; bbox[2] = (int)(left + ((psettings->lines_per_page + prt_header_height()) * prt_line_height) + 0.5); @@ -2574,7 +2567,7 @@ int mch_print_begin(prt_settings_T *psettings) // Search for external resources VIM supplies if (!prt_find_resource("prolog", &res_prolog)) { - EMSG(_("E456: Can't find PostScript resource file \"prolog.ps\"")); + emsg(_("E456: Can't find PostScript resource file \"prolog.ps\"")); return FALSE; } if (!prt_open_resource(&res_prolog)) { @@ -2586,7 +2579,7 @@ int mch_print_begin(prt_settings_T *psettings) if (prt_out_mbyte) { // Look for required version of multi-byte printing procset if (!prt_find_resource("cidfont", &res_cidfont)) { - EMSG(_("E456: Can't find PostScript resource file \"cidfont.ps\"")); + emsg(_("E456: Can't find PostScript resource file \"cidfont.ps\"")); return FALSE; } if (!prt_open_resource(&res_cidfont)) { @@ -2597,11 +2590,10 @@ int mch_print_begin(prt_settings_T *psettings) } } - /* Find an encoding to use for printing. - * Check 'printencoding'. If not set or not found, then use 'encoding'. If - * that cannot be found then default to "latin1". - * Note: VIM specific encoding header is always skipped. - */ + // Find an encoding to use for printing. + // Check 'printencoding'. If not set or not found, then use 'encoding'. If + // that cannot be found then default to "latin1". + // Note: VIM specific encoding header is always skipped. if (!prt_out_mbyte) { p_encoding = enc_skip(p_penc); if (*p_encoding == NUL @@ -2617,7 +2609,7 @@ int mch_print_begin(prt_settings_T *psettings) // Use latin1 as default printing encoding p_encoding = (char_u *)"latin1"; if (!prt_find_resource((char *)p_encoding, &res_encoding)) { - EMSG2(_("E456: Can't find PostScript resource file \"%s.ps\""), + semsg(_("E456: Can't find PostScript resource file \"%s.ps\""), p_encoding); return FALSE; } @@ -2626,8 +2618,8 @@ int mch_print_begin(prt_settings_T *psettings) if (!prt_open_resource(&res_encoding)) { return FALSE; } - /* For the moment there are no checks on encoding resource files to - * perform */ + // For the moment there are no checks on encoding resource files to + // perform } else { p_encoding = enc_skip(p_penc); if (*p_encoding == NUL) { @@ -2636,15 +2628,15 @@ int mch_print_begin(prt_settings_T *psettings) if (prt_use_courier) { // Include ASCII range encoding vector if (!prt_find_resource(prt_ascii_encoding, &res_encoding)) { - EMSG2(_("E456: Can't find PostScript resource file \"%s.ps\""), + semsg(_("E456: Can't find PostScript resource file \"%s.ps\""), prt_ascii_encoding); return FALSE; } if (!prt_open_resource(&res_encoding)) { return FALSE; } - /* For the moment there are no checks on encoding resource files to - * perform */ + // For the moment there are no checks on encoding resource files to + // perform } } @@ -2652,7 +2644,7 @@ int mch_print_begin(prt_settings_T *psettings) if (!(enc_canon_props(p_enc) & enc_canon_props(p_encoding) & ENC_8BIT)) { // 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\""), + semsg(_("E620: Unable to convert to print encoding \"%s\""), p_encoding); return false; } @@ -2662,7 +2654,7 @@ int mch_print_begin(prt_settings_T *psettings) if (prt_out_mbyte && prt_custom_cmap) { // Find user supplied CMap if (!prt_find_resource(prt_cmap, &res_cmap)) { - EMSG2(_("E456: Can't find PostScript resource file \"%s.ps\""), + semsg(_("E456: Can't find PostScript resource file \"%s.ps\""), prt_cmap); return FALSE; } @@ -2742,8 +2734,8 @@ int mch_print_begin(prt_settings_T *psettings) } if (!prt_out_mbyte || prt_use_courier) { - /* There will be only one Roman font encoding to be included in the PS - * file. */ + // There will be only one Roman font encoding to be included in the PS + // file. if (!prt_add_resource(&res_encoding)) { return FALSE; } @@ -2771,8 +2763,8 @@ int mch_print_begin(prt_settings_T *psettings) // Font resource inclusion and definition if (!prt_out_mbyte || prt_use_courier) { - /* When using Courier for ASCII range when printing multi-byte, need to - * pick up ASCII encoding to use with it. */ + // When using Courier for ASCII range when printing multi-byte, need to + // pick up ASCII encoding to use with it. if (prt_use_courier) { p_encoding = (char_u *)prt_ascii_encoding; } @@ -2794,12 +2786,11 @@ int mch_print_begin(prt_settings_T *psettings) prt_ps_courier_font.ps_fontname[PRT_PS_FONT_BOLDOBLIQUE]); } if (prt_out_mbyte) { - /* Define the CID fonts to be used in the job. Typically CJKV fonts do - * not have an italic form being a western style, so where no font is - * defined for these faces VIM falls back to an existing face. - * Note: if using Courier for the ASCII range then the printout will - * have bold/italic/bolditalic regardless of the setting of printmbfont. - */ + // Define the CID fonts to be used in the job. Typically CJKV fonts do + // not have an italic form being a western style, so where no font is + // defined for these faces VIM falls back to an existing face. + // Note: if using Courier for the ASCII range then the printout will + // have bold/italic/bolditalic regardless of the setting of printmbfont. prt_dsc_resources("IncludeResource", "font", prt_ps_mb_font.ps_fontname[PRT_PS_FONT_ROMAN]); if (!prt_custom_cmap) { @@ -2872,8 +2863,8 @@ void mch_print_end(prt_settings_T *psettings) prt_dsc_noarg("EOF"); - /* Write CTRL-D to close serial communication link if used. - * NOTHING MUST BE WRITTEN AFTER THIS! */ + // Write CTRL-D to close serial communication link if used. + // NOTHING MUST BE WRITTEN AFTER THIS! prt_write_file((char_u *)"\004"); if (!prt_file_error && psettings->outfile == NULL @@ -2888,7 +2879,7 @@ void mch_print_end(prt_settings_T *psettings) // Not printing to a file: use 'printexpr' to print the file. if (eval_printexpr((char *)prt_ps_file_name, (char *)psettings->arguments) == FAIL) { - EMSG(_("E365: Failed to print PostScript file")); + emsg(_("E365: Failed to print PostScript file")); } else { prt_message((char_u *)_("Print job sent.")); } @@ -2977,13 +2968,12 @@ int mch_print_text_out(char_u *const textp, size_t len) char_u *tofree = NULL; double char_width = prt_char_width; - /* Ideally VIM would create a rearranged CID font to combine a Roman and - * CJKV font to do what VIM is doing here - use a Roman font for characters - * in the ASCII range, and the original CID font for everything else. - * The problem is that GhostScript still (as of 8.13) does not support - * rearranged fonts even though they have been documented by Adobe for 7 - * years! If they ever do, a lot of this code will disappear. - */ + // Ideally VIM would create a rearranged CID font to combine a Roman and + // CJKV font to do what VIM is doing here - use a Roman font for characters + // in the ASCII range, and the original CID font for everything else. + // The problem is that GhostScript still (as of 8.13) does not support + // rearranged fonts even though they have been documented by Adobe for 7 + // years! If they ever do, a lot of this code will disappear. if (prt_use_courier) { const bool in_ascii = (len == 1 && *p < 0x80); if (prt_in_ascii) { @@ -3020,9 +3010,8 @@ int mch_print_text_out(char_u *const textp, size_t len) } } - /* Output any required changes to the graphics state, after flushing any - * text buffered so far. - */ + // Output any required changes to the graphics state, after flushing any + // text buffered so far. if (prt_attribute_change) { prt_flush_buffer(); // Reset count of number of chars that will be printed @@ -3100,16 +3089,14 @@ int mch_print_text_out(char_u *const textp, size_t len) p++; } } else { - /* Add next character to buffer of characters to output. - * Note: One printed character may require several PS characters to - * represent it, but we only count them as one printed character. - */ + // Add next character to buffer of characters to output. + // Note: One printed character may require several PS characters to + // represent it, but we only count them as one printed character. ch = *p; if (ch < 32 || ch == '(' || ch == ')' || ch == '\\') { - /* Convert non-printing characters to either their escape or octal - * sequence, ensures PS sent over a serial line does not interfere - * with the comms protocol. - */ + // Convert non-printing characters to either their escape or octal + // sequence, ensures PS sent over a serial line does not interfere + // with the comms protocol. ga_append(&prt_ps_buffer, '\\'); switch (ch) { case BS: diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c index a8e5de839a..ca6f033c47 100644 --- a/src/nvim/hashtab.c +++ b/src/nvim/hashtab.c @@ -281,11 +281,11 @@ static void hash_may_resize(hashtab_T *ht, size_t minitems) #ifdef HT_DEBUG if (ht->ht_used > ht->ht_filled) { - EMSG("hash_may_resize(): more used than filled"); + emsg("hash_may_resize(): more used than filled"); } if (ht->ht_filled >= ht->ht_mask + 1) { - EMSG("hash_may_resize(): table completely filled"); + emsg("hash_may_resize(): table completely filled"); } #endif // ifdef HT_DEBUG diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 737e668e81..3050ca02de 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -76,7 +76,7 @@ static int get_attr_entry(HlEntry entry) // compute new ones for all groups. // When called recursively, we are really out of numbers. if (recursive) { - EMSG(_("E424: Too many different highlighting attributes in use")); + emsg(_("E424: Too many different highlighting attributes in use")); return 0; } recursive = true; diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h index 12f2b62313..d4d53c4126 100644 --- a/src/nvim/highlight_defs.h +++ b/src/nvim/highlight_defs.h @@ -103,7 +103,7 @@ typedef enum { HLF_NFLOAT, // Floating window HLF_MSG, // Message area HLF_BORDER, // Floating window border - HLF_COUNT // MUST be the last one + HLF_COUNT, // MUST be the last one } hlf_T; EXTERN const char *hlf_names[] INIT(= { diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c index d731e79473..5b5f056164 100644 --- a/src/nvim/if_cscope.c +++ b/src/nvim/if_cscope.c @@ -64,7 +64,7 @@ static cscmd_T cs_cmds[] = static void cs_usage_msg(csid_e x) { - (void)EMSG2(_("E560: Usage: cs[cope] %s"), cs_cmds[(int)x].usage); + (void)semsg(_("E560: Usage: cs[cope] %s"), cs_cmds[(int)x].usage); } @@ -72,7 +72,7 @@ static enum { EXP_CSCOPE_SUBCMD, // expand ":cscope" sub-commands EXP_SCSCOPE_SUBCMD, // expand ":scscope" sub-commands EXP_CSCOPE_FIND, // expand ":cscope find" arguments - EXP_CSCOPE_KILL // expand ":cscope kill" arguments + EXP_CSCOPE_KILL, // expand ":cscope kill" arguments } expand_what; /* @@ -184,7 +184,7 @@ static void do_cscope_general(exarg_T *eap, int make_split) if (make_split) { if (!cmdp->cansplit) { - (void)MSG_PUTS(_("This cscope command does not support splitting the window.\n")); + (void)msg_puts(_("This cscope command does not support splitting the window.\n")); return; } postponed_split = -1; @@ -216,7 +216,7 @@ void ex_cstag(exarg_T *eap) int ret = FALSE; if (*eap->arg == NUL) { - (void)EMSG(_("E562: Usage: cstag <ident>")); + (void)emsg(_("E562: Usage: cstag <ident>")); return; } @@ -268,7 +268,7 @@ void ex_cstag(exarg_T *eap) } if (!ret) { - (void)EMSG(_("E257: cstag: tag not found")); + (void)emsg(_("E257: cstag: tag not found")); g_do_tagpreview = 0; } } @@ -403,12 +403,8 @@ static int cs_add(exarg_T *eap) static void cs_stat_emsg(char *fname) { - char *stat_emsg = _("E563: stat(%s) error: %d"); - char *buf = xmalloc(strlen(stat_emsg) + MAXPATHL + 10); - - (void)sprintf(buf, stat_emsg, fname, errno); - (void)EMSG(buf); - xfree(buf); + int err = errno; + (void)semsg(_("E563: stat(%s) error: %d"), fname, err); } @@ -489,7 +485,7 @@ staterr: i = cs_insert_filelist(fname, ppath, flags, &file_info); } else { if (p_csverbose) { - (void)EMSG2(_("E564: %s is not a directory or a valid cscope database"), + (void)semsg(_("E564: %s is not a directory or a valid cscope database"), fname); } goto add_err; @@ -550,7 +546,7 @@ static size_t cs_cnt_connections(void) /// @param idx connection index static void cs_reading_emsg(size_t idx) { - EMSGU(_("E262: error reading cscope connection %" PRIu64), idx); + semsg(_("E262: error reading cscope connection %" PRIu64), (uint64_t)idx); } #define CSREAD_BUFSIZE 2048 @@ -662,7 +658,7 @@ static char *cs_create_cmd(char *csoption, char *pattern) search = 9; break; default: - (void)EMSG(_("E561: unknown cscope search type")); + (void)emsg(_("E561: unknown cscope search type")); cs_usage_msg(Find); return NULL; } @@ -700,7 +696,7 @@ static int cs_create_connection(size_t i) */ to_cs[0] = to_cs[1] = from_cs[0] = from_cs[1] = -1; if (pipe(to_cs) < 0 || pipe(from_cs) < 0) { - (void)EMSG(_("E566: Could not create cscope pipes")); + (void)emsg(_("E566: Could not create cscope pipes")); err_closing: if (to_cs[0] != -1) { (void)close(to_cs[0]); @@ -719,7 +715,7 @@ err_closing: switch (csinfo[i].pid = fork()) { case -1: - (void)EMSG(_("E622: Could not fork for cscope")); + (void)emsg(_("E622: Could not fork for cscope")); goto err_closing; case 0: // child: run cscope. if (dup2(to_cs[0], STDIN_FILENO) == -1) { @@ -752,7 +748,7 @@ err_closing: if (!(pipe_stdin = CreatePipe(&stdin_rd, &stdin_wr, &sa, 0)) || !(pipe_stdout = CreatePipe(&stdout_rd, &stdout_wr, &sa, 0))) { - (void)EMSG(_("E566: Could not create cscope pipes")); + (void)emsg(_("E566: Could not create cscope pipes")); err_closing: if (pipe_stdin) { CloseHandle(stdin_rd); @@ -856,7 +852,7 @@ err_closing: if (!created) { PERROR(_("cs_create_connection exec failed")); - (void)EMSG(_("E623: Could not spawn cscope process")); + (void)emsg(_("E623: Could not spawn cscope process")); goto err_closing; } // else @@ -892,7 +888,7 @@ static int cs_find(exarg_T *eap) char *opt, *pat; if (cs_check_for_connections() == FALSE) { - (void)EMSG(_("E567: no cscope connections")); + (void)emsg(_("E567: no cscope connections")); return FALSE; } @@ -970,13 +966,7 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose, int us qfpos++; // next symbol must be + or - if (strchr(CSQF_FLAGS, *qfpos) == NULL) { - char *nf = _("E469: invalid cscopequickfix flag %c for %c"); - // strlen will be enough because we use chars - char *buf = xmalloc(strlen(nf)); - - sprintf(buf, nf, *qfpos, *(qfpos-1)); - (void)EMSG(buf); - xfree(buf); + (void)semsg(_("E469: invalid cscopequickfix flag %c for %c"), *qfpos, *(qfpos - 1));; return FALSE; } @@ -1025,18 +1015,9 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose, int us xfree(cmd); if (totmatches == 0) { - char *nf = _("E259: no matches found for cscope query %s of %s"); - char *buf; - - if (!verbose) { - xfree(nummatches); - return FALSE; + if (verbose) { + (void)semsg(_("E259: no matches found for cscope query %s of %s"), opt, pat); } - - buf = xmalloc(strlen(opt) + strlen(pat) + strlen(nf)); - sprintf(buf, nf, opt, pat); - (void)EMSG(buf); - xfree(buf); xfree(nummatches); return FALSE; } @@ -1050,7 +1031,7 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose, int us f = os_fopen((char *)tmp, "w"); if (f == NULL) { - EMSG2(_(e_notopen), tmp); + semsg(_(e_notopen), tmp); } else { cs_file_results(f, nummatches); fclose(f); @@ -1106,7 +1087,7 @@ static int cs_help(exarg_T *eap) { cscmd_T *cmdp = cs_cmds; - (void)MSG_PUTS(_("cscope commands:\n")); + (void)msg_puts(_("cscope commands:\n")); while (cmdp->name != NULL) { char *help = _(cmdp->help); int space_cnt = 30 - vim_strsize((char_u *)help); @@ -1120,7 +1101,7 @@ static int cs_help(exarg_T *eap) help, space_cnt, " ", cmdp->usage); if (strcmp(cmdp->name, "find") == 0) { - MSG_PUTS(_("\n" + msg_puts(_("\n" " a: Find assignments to this symbol\n" " c: Find functions calling this function\n" " d: Find functions called by this function\n" @@ -1161,7 +1142,7 @@ static int cs_insert_filelist(char *fname, char *ppath, char *flags, FileInfo *f if (csinfo[j].fname != NULL && os_fileid_equal_fileinfo(&(csinfo[j].file_id), file_info)) { if (p_csverbose) { - (void)EMSG(_("E568: duplicate cscope database not added")); + (void)emsg(_("E568: duplicate cscope database not added")); } return CSCOPE_FAILURE; } @@ -1267,7 +1248,7 @@ static int cs_kill(exarg_T *eap) i = (size_t)num; } else { // All negative values besides -1 are invalid. if (p_csverbose) { - (void)EMSG2(_("E261: cscope connection %s not found"), stok); + (void)semsg(_("E261: cscope connection %s not found"), stok); } return CSCOPE_FAILURE; } @@ -1283,7 +1264,7 @@ static int cs_kill(exarg_T *eap) if (!killall && (i >= csinfo_size || csinfo[i].fname == NULL)) { if (p_csverbose) { - (void)EMSG2(_("E261: cscope connection %s not found"), stok); + (void)semsg(_("E261: cscope connection %s not found"), stok); } return CSCOPE_FAILURE; } else { @@ -1428,7 +1409,7 @@ static char *cs_manage_matches(char **matches, char **contexts, size_t totmatche cs_print_tags_priv(mp, cp, cnt); break; default: // should not reach here - IEMSG(_("E570: fatal error in cs_manage_matches")); + iemsg(_("E570: fatal error in cs_manage_matches")); return NULL; } @@ -1463,7 +1444,6 @@ retry: // If the line's too long for the buffer, discard it. if ((p = strchr(buf, '\n')) == NULL) { while ((ch = getc(csinfo[cnumber].fr_fp)) != EOF && ch != '\n') { - ; } return NULL; } @@ -1521,7 +1501,7 @@ static void cs_file_results(FILE *f, int *nummatches_a) context = xmalloc(strlen(cntx) + 5); - if (strcmp(cntx, "<global>")==0) { + if (strcmp(cntx, "<global>") == 0) { strcpy(context, "<<global>>"); } else { sprintf(context, "<<%s>>", cntx); @@ -1654,16 +1634,16 @@ static void cs_print_tags_priv(char **matches, char **cntxts, char *buf = xmalloc(newsize); size_t bufsize = newsize; // Track available bufsize (void)snprintf(buf, bufsize, cstag_msg, ptag); - MSG_PUTS_ATTR(buf, HL_ATTR(HLF_T)); + msg_puts_attr(buf, HL_ATTR(HLF_T)); msg_clr_eos(); // restore matches[0] *ptag_end = '\t'; // Column headers for match number, line number and filename. - MSG_PUTS_ATTR(_("\n # line"), HL_ATTR(HLF_T)); + msg_puts_attr(_("\n # line"), HL_ATTR(HLF_T)); msg_advance(msg_col + 2); - MSG_PUTS_ATTR(_("filename / context / line\n"), HL_ATTR(HLF_T)); + msg_puts_attr(_("filename / context / line\n"), HL_ATTR(HLF_T)); for (size_t i = 0; i < num_matches; i++) { assert(strcnt(matches[i], '\t') >= 2); @@ -1690,8 +1670,8 @@ static void cs_print_tags_priv(char **matches, char **cntxts, bufsize = newsize; } (void)snprintf(buf, bufsize, csfmt_str, i + 1, lno); - MSG_PUTS_ATTR(buf, HL_ATTR(HLF_CM)); - MSG_PUTS_LONG_ATTR(cs_pathcomponents(fname), HL_ATTR(HLF_CM)); + msg_puts_attr(buf, HL_ATTR(HLF_CM)); + msg_outtrans_long_attr((char_u *)cs_pathcomponents(fname), HL_ATTR(HLF_CM)); // compute the required space for the context char *context = cntxts[i] ? cntxts[i] : globalcntx; @@ -1713,11 +1693,11 @@ static void cs_print_tags_priv(char **matches, char **cntxts, msg_putchar('\n'); } msg_advance(12); - MSG_PUTS_LONG(buf); + msg_outtrans_long_attr((char_u *)buf, 0); msg_putchar('\n'); if (extra != NULL) { msg_advance(13); - MSG_PUTS_LONG(extra); + msg_outtrans_long_attr((char_u *)extra, 0); } // restore matches[i] @@ -1777,7 +1757,7 @@ static int cs_read_prompt(size_t i) buf[bufpos - epromptlen] = NUL; // print message to user - (void)EMSG2(cs_emsg, buf); + (void)semsg(cs_emsg, buf); // send RETURN to cscope (void)putc('\n', csinfo[i].to_fp); @@ -1800,7 +1780,7 @@ static int cs_read_prompt(size_t i) if (ch == EOF) { PERROR("cs_read_prompt EOF"); if (buf != NULL && buf[0] != NUL) { - (void)EMSG2(cs_emsg, buf); + (void)semsg(cs_emsg, buf); } else if (p_csverbose) { cs_reading_emsg(i); // don't have additional information } @@ -1987,7 +1967,7 @@ static int cs_reset(exarg_T *eap) // connection number in the same line as // "Added cscope database..." snprintf(buf, ARRAY_SIZE(buf), " (#%zu)", i); - MSG_PUTS_ATTR(buf, HL_ATTR(HLF_R)); + msg_puts_attr(buf, HL_ATTR(HLF_R)); } } xfree(dblist[i]); @@ -2060,9 +2040,9 @@ static char *cs_resolve_file(size_t i, char *name) static int cs_show(exarg_T *eap) { if (cs_cnt_connections() == 0) { - MSG_PUTS(_("no cscope connections\n")); + msg_puts(_("no cscope connections\n")); } else { - MSG_PUTS_ATTR(_(" # pid database name prepend path\n"), + msg_puts_attr(_(" # pid database name prepend path\n"), HL_ATTR(HLF_T)); for (size_t i = 0; i < csinfo_size; i++) { if (csinfo[i].fname == NULL) { diff --git a/src/nvim/if_cscope_defs.h b/src/nvim/if_cscope_defs.h index 182cbc28e1..6ded89fa0b 100644 --- a/src/nvim/if_cscope_defs.h +++ b/src/nvim/if_cscope_defs.h @@ -52,13 +52,13 @@ typedef struct csi { FILE *to_fp; // to cscope: FILE. } csinfo_T; -typedef enum { Add, Find, Help, Kill, Reset, Show } csid_e; +typedef enum { Add, Find, Help, Kill, Reset, Show, } csid_e; typedef enum { Store, Get, Free, - Print + Print, } mcmd_e; #endif // NVIM_IF_CSCOPE_DEFS_H diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c index b724d82f7c..abf016b832 100644 --- a/src/nvim/keymap.c +++ b/src/nvim/keymap.c @@ -477,7 +477,7 @@ char_u *get_special_key_name(int c, int modifiers) * extract modifiers. */ if (c > 0 - && (*mb_char2len)(c) == 1) { + && utf_char2len(c) == 1) { if (table_idx < 0 && (!vim_isprintc(c) || (c & 0x7f) == ' ') && (c & 0x80)) { @@ -647,7 +647,7 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp, } else if (end - bp > 4 && STRNICMP(bp, "char-", 5) == 0) { vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, true); if (l == 0) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return 0; } bp += l + 5; @@ -677,7 +677,7 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp, // <Char-123> or <Char-033> or <Char-0x33> vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL, &n, 0, true); if (l == 0) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return 0; } key = (int)n; @@ -689,10 +689,10 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp, // Special case for a double-quoted string off = l = 2; } else { - l = mb_ptr2len(last_dash + 1); + l = utfc_ptr2len(last_dash + 1); } if (modifiers != 0 && last_dash[l + 1] == '>') { - key = PTR2CHAR(last_dash + off); + key = utf_ptr2char(last_dash + off); } else { key = get_special_key_code(last_dash + off); if (!keep_x_key) { @@ -891,7 +891,7 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len, char_u **bu // (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14) if (end - src >= 4 && STRNICMP(src, "<SID>", 5) == 0) { if (current_sctx.sc_sid <= 0) { - EMSG(_(e_usingsid)); + emsg(_(e_usingsid)); } else { src += 5; result[dlen++] = K_SPECIAL; diff --git a/src/nvim/keymap.h b/src/nvim/keymap.h index 663a7a12ec..5ff5a38614 100644 --- a/src/nvim/keymap.h +++ b/src/nvim/keymap.h @@ -245,7 +245,7 @@ enum key_extra { KE_MOUSEMOVE = 100, // mouse moved with no button down // , KE_CANCEL = 101 // return from vgetc KE_EVENT = 102, // event - KE_COMMAND = 104 // <Cmd> special key + KE_COMMAND = 104, // <Cmd> special key }; /* diff --git a/src/nvim/lib/kbtree.h b/src/nvim/lib/kbtree.h index e2a4e9edea..5d9c1095bc 100644 --- a/src/nvim/lib/kbtree.h +++ b/src/nvim/lib/kbtree.h @@ -46,20 +46,18 @@ #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 { \ +#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; \ @@ -69,231 +67,231 @@ } 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_CLEAR(x); continue; } \ - for (i = 0; i <= x->n; ++i) \ - if (__KB_PTR(b, x)[i]) { \ - if (top - stack == (int)max) { \ - max <<= 1; \ +#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_CLEAR(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_CLEAR(x); \ - } \ - } \ - XFREE_CLEAR(stack); \ + top = stack + (max>>1); \ + } \ + *top++ = __KB_PTR(b, x)[i]; \ + } \ + XFREE_CLEAR(x); \ + } \ + } \ + XFREE_CLEAR(stack); \ } while (0) -#define __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ +#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; \ + { \ + 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; \ + 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) \ +#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; \ - } \ + 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); \ + { \ + return kb_getp_##name(b, &k); \ } -#define __KB_INTERVAL(name, key_t, kbnode_t) \ +#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) \ - { \ + 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]; \ - } \ - } \ + 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); \ + { \ + kb_intervalp_##name(b, &k, lower, upper); \ } -#define __KB_PUT(name, key_t, kbnode_t, __cmp, T, ILEN) \ - /* x must be an internal node */ \ +#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; \ + { \ + 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; \ + 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; \ + __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; \ - } \ + __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) \ + { \ + 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; \ - } \ + 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; \ + 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); \ - } \ + 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); \ + { \ + kb_putp_##name(b, &k); \ } -#define __KB_DEL(name, key_t, kbnode_t, T) \ +#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]; \ + { \ + 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]; \ + --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]; \ + 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; \ + 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; \ + 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_CLEAR(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) { \ + --x->n; \ + XFREE_CLEAR(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, 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; \ + --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]; \ + __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; \ + --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], \ @@ -301,55 +299,55 @@ } 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)); \ + (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; \ + 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_CLEAR(xp); \ - xp = y; \ + --x->n; \ + XFREE_CLEAR(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]; \ + __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)); \ + (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; \ + 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_CLEAR(y); \ - } \ - } \ - return __kb_delp_aux_##name(b, xp, k, s); \ - } \ + --x->n; \ + XFREE_CLEAR(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_CLEAR(x); \ - } \ - return ret; \ - } \ + { \ + 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_CLEAR(x); \ + } \ + return ret; \ + } \ static inline key_t kb_del_##name(kbtree_##name##_t *b, key_t k) \ - { \ - return kb_delp_##name(b, &k); \ + { \ + return kb_delp_##name(b, &k); \ } #define __KB_ITR(name, key_t, kbnode_t) \ @@ -425,7 +423,7 @@ 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) \ @@ -439,12 +437,12 @@ KBTREE_INIT_IMPL(name, key_t, kbnode_##name##_t, __cmp, T, \ (sizeof(kbnode_##name##_t)+(2*T)*sizeof(void *))) -#define KBTREE_INIT_IMPL(name, key_t, kbnode_t, __cmp, T, ILEN) \ - __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) \ +#define KBTREE_INIT_IMPL(name, key_t, kbnode_t, __cmp, T, ILEN) \ + __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) diff --git a/src/nvim/lib/khash.h b/src/nvim/lib/khash.h index dd87415144..e0faf94db9 100644 --- a/src/nvim/lib/khash.h +++ b/src/nvim/lib/khash.h @@ -417,12 +417,12 @@ typedef khint_t khiter_t; } \ } -#define KHASH_DECLARE(name, khkey_t, khval_t) \ - __KHASH_TYPE(name, khkey_t, khval_t) \ +#define KHASH_DECLARE(name, khkey_t, khval_t) \ + __KHASH_TYPE(name, khkey_t, khval_t) \ __KHASH_PROTOTYPES(name, khkey_t, khval_t) #define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ - __KHASH_TYPE(name, khkey_t, khval_t) \ + __KHASH_TYPE(name, khkey_t, khval_t) \ __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) #define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ @@ -627,12 +627,12 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key) @param vvar Variable to which value will be assigned @param code Block of code to execute */ -#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \ - for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ - if (!kh_exist(h, __i)) continue; \ - (kvar) = kh_key(h, __i); \ - (vvar) = kh_val(h, __i); \ - code; \ +#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \ + for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ + if (!kh_exist(h, __i)) continue; \ + (kvar) = kh_key(h, __i); \ + (vvar) = kh_val(h, __i); \ + code; \ } } /*! @function @@ -641,11 +641,11 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key) @param vvar Variable to which value will be assigned @param code Block of code to execute */ -#define kh_foreach_value(h, vvar, code) { khint_t __i; \ - for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ - if (!kh_exist(h, __i)) continue; \ - (vvar) = kh_val(h, __i); \ - code; \ +#define kh_foreach_value(h, vvar, code) { khint_t __i; \ + for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ + if (!kh_exist(h, __i)) continue; \ + (vvar) = kh_val(h, __i); \ + code; \ } } /*! @function @@ -672,7 +672,7 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key) @abstract Instantiate a hash set containing integer keys @param name Name of the hash table [symbol] */ -#define KHASH_SET_INIT_INT(name) \ +#define KHASH_SET_INIT_INT(name) \ KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal) /*! @function @@ -680,14 +680,14 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key) @param name Name of the hash table [symbol] @param khval_t Type of values [type] */ -#define KHASH_MAP_INIT_INT(name, khval_t) \ +#define KHASH_MAP_INIT_INT(name, khval_t) \ KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal) /*! @function @abstract Instantiate a hash map containing 64-bit integer keys @param name Name of the hash table [symbol] */ -#define KHASH_SET_INIT_INT64(name) \ +#define KHASH_SET_INIT_INT64(name) \ KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal) /*! @function @@ -695,7 +695,7 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key) @param name Name of the hash table [symbol] @param khval_t Type of values [type] */ -#define KHASH_MAP_INIT_INT64(name, khval_t) \ +#define KHASH_MAP_INIT_INT64(name, khval_t) \ KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal) typedef const char *kh_cstr_t; @@ -703,7 +703,7 @@ typedef const char *kh_cstr_t; @abstract Instantiate a hash map containing const char* keys @param name Name of the hash table [symbol] */ -#define KHASH_SET_INIT_STR(name) \ +#define KHASH_SET_INIT_STR(name) \ KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal) /*! @function diff --git a/src/nvim/lib/kvec.h b/src/nvim/lib/kvec.h index eb2d9bbb77..34332ba34b 100644 --- a/src/nvim/lib/kvec.h +++ b/src/nvim/lib/kvec.h @@ -94,6 +94,17 @@ memcpy((v1).items, (v0).items, sizeof((v1).items[0]) * (v0).size); \ } while (0) +#define kv_splice(v1, v0) \ + do { \ + if ((v1).capacity < (v1).size + (v0).size) { \ + (v1).capacity = (v1).size + (v0).size; \ + kv_roundup32((v1).capacity); \ + kv_resize((v1), (v1).capacity); \ + } \ + memcpy((v1).items + (v1).size, (v0).items, sizeof((v1).items[0]) * (v0).size); \ + (v1).size = (v1).size + (v0).size; \ + } while (0) + #define kv_pushp(v) \ ((((v).size == (v).capacity) ? (kv_resize_full(v), 0) : 0), \ ((v).items + ((v).size++))) @@ -101,6 +112,7 @@ #define kv_push(v, x) \ (*kv_pushp(v) = (x)) + #define kv_a(v, i) \ (*(((v).capacity <= (size_t)(i) \ ? ((v).capacity = (v).size = (i) + 1, \ diff --git a/src/nvim/lib/queue.h b/src/nvim/lib/queue.h index 871f49c863..e5574094bc 100644 --- a/src/nvim/lib/queue.h +++ b/src/nvim/lib/queue.h @@ -38,7 +38,7 @@ typedef struct _queue { // elements results in undefined behavior. #define QUEUE_FOREACH(q, h, code) \ (q) = (h)->next; \ - while((q) != (h)) { \ + while ((q) != (h)) { \ QUEUE *next = q->next; \ code \ (q) = next; \ diff --git a/src/nvim/lib/ringbuf.h b/src/nvim/lib/ringbuf.h index 06f7830bd1..4fd110a531 100644 --- a/src/nvim/lib/ringbuf.h +++ b/src/nvim/lib/ringbuf.h @@ -29,7 +29,7 @@ : ((rb)->next > \ (rb)->first) ? (size_t)((rb)->next - \ (rb)->first) \ - : (size_t)((rb)->\ + : (size_t)((rb)-> \ next - (rb)->buf + \ (rb)->buf_end - \ (rb)->first + 1)) @@ -130,7 +130,6 @@ .buf_end = buf + size - 1, \ }; \ } \ -\ static inline void funcprefix##_rb_free(TypeName##RingBuffer *const rb) \ REAL_FATTR_UNUSED; \ static inline void funcprefix##_rb_free(TypeName##RingBuffer *const rb) \ @@ -143,14 +142,12 @@ } \ XFREE_CLEAR(rb->buf); \ } \ -\ static inline void funcprefix##_rb_dealloc(TypeName##RingBuffer *const rb) \ REAL_FATTR_UNUSED; \ static inline void funcprefix##_rb_dealloc(TypeName##RingBuffer *const rb) \ { \ XFREE_CLEAR(rb->buf); \ } \ -\ static inline void funcprefix##_rb_push(TypeName##RingBuffer *const rb, \ RBType item) \ REAL_FATTR_NONNULL_ARG(1); \ @@ -166,7 +163,6 @@ *rb->next = item; \ rb->next = _RINGBUF_NEXT(rb, rb->next); \ } \ -\ static inline ptrdiff_t funcprefix##_rb_find_idx(const TypeName##RingBuffer *const rb, \ const RBType *const item_p) \ REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE REAL_FATTR_UNUSED; \ @@ -183,21 +179,18 @@ return item_p - rb->buf + rb->buf_end - rb->first + 1; \ } \ } \ -\ static inline size_t funcprefix##_rb_size(const TypeName##RingBuffer *const rb) \ REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE; \ static inline size_t funcprefix##_rb_size(const TypeName##RingBuffer *const rb) \ { \ return (size_t)(rb->buf_end - rb->buf) + 1; \ } \ -\ static inline size_t funcprefix##_rb_length(const TypeName##RingBuffer *const rb) \ REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE; \ static inline size_t funcprefix##_rb_length(const TypeName##RingBuffer *const rb) \ { \ return _RINGBUF_LENGTH(rb); \ } \ -\ static inline RBType *funcprefix##_rb_idx_p(const TypeName##RingBuffer *const rb, \ const size_t idx) \ REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE; \ @@ -212,7 +205,6 @@ return rb->first + idx; \ } \ } \ -\ static inline RBType funcprefix##_rb_idx(const TypeName##RingBuffer *const rb, \ const size_t idx) \ REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE REAL_FATTR_UNUSED; \ @@ -221,7 +213,6 @@ { \ return *funcprefix##_rb_idx_p(rb, idx); \ } \ -\ static inline void funcprefix##_rb_insert(TypeName##RingBuffer *const rb, \ const size_t idx, \ RBType item) \ @@ -263,7 +254,6 @@ } \ rb->next = _RINGBUF_NEXT(rb, rb->next); \ } \ -\ static inline void funcprefix##_rb_remove(TypeName##RingBuffer *const rb, \ const size_t idx) \ REAL_FATTR_NONNULL_ARG(1) REAL_FATTR_UNUSED; \ diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c index ca3c4f604a..9f2372f831 100644 --- a/src/nvim/lua/converter.c +++ b/src/nvim/lua/converter.c @@ -62,7 +62,7 @@ static LuaTableProps nlua_traverse_table(lua_State *const lstate) 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); + semsg(_("E1502: Lua failed to grow stack to %i"), lua_gettop(lstate) + 2); ret.type = kObjectTypeNil; return ret; } @@ -198,7 +198,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv) kvi_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); + semsg(_("E1502: Lua failed to grow stack to %i"), lua_gettop(lstate) + 3); ret = false; break; } @@ -376,7 +376,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv) cur.tv->vval.v_float = (float_T)table_props.val; break; case kObjectTypeNil: - EMSG(_("E5100: Cannot convert given lua table: table " + emsg(_("E5100: Cannot convert given lua table: table " "should either have a sequence of positive integer keys " "or contain only string keys")); ret = false; @@ -408,13 +408,13 @@ nlua_pop_typval_table_processing_end: cur.tv->v_type = VAR_SPECIAL; cur.tv->vval.v_special = kSpecialVarNull; } else { - EMSG(_("E5101: Cannot convert given lua type")); + emsg(_("E5101: Cannot convert given lua type")); ret = false; } break; } default: - EMSG(_("E5101: Cannot convert given lua type")); + emsg(_("E5101: Cannot convert given lua type")); ret = false; break; } @@ -503,7 +503,7 @@ static bool typval_conv_special = false; #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"), \ + semsg(_("E5102: Lua failed to grow stack to %i"), \ lua_gettop(lstate) + 3); \ return false; \ } \ @@ -526,7 +526,7 @@ static bool typval_conv_special = false; #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"), \ + semsg(_("E5102: Lua failed to grow stack to %i"), \ lua_gettop(lstate) + 3); \ return false; \ } \ @@ -614,7 +614,7 @@ bool nlua_push_typval(lua_State *lstate, typval_T *const tv, bool special) 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); + semsg(_("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) { diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 59ebafd9c8..b27b1ae7a8 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -5,9 +5,7 @@ #include <lua.h> #include <lualib.h> -#include "cjson/lua_cjson.h" #include "luv/luv.h" -#include "mpack/lmpack.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" @@ -27,8 +25,8 @@ #include "nvim/getchar.h" #include "nvim/lua/converter.h" #include "nvim/lua/executor.h" +#include "nvim/lua/stdlib.h" #include "nvim/lua/treesitter.h" -#include "nvim/lua/xdiff.h" #include "nvim/macros.h" #include "nvim/map.h" #include "nvim/memline.h" @@ -36,7 +34,6 @@ #include "nvim/misc1.h" #include "nvim/msgpack_rpc/channel.h" #include "nvim/os/os.h" -#include "nvim/regexp.h" #include "nvim/screen.h" #include "nvim/undo.h" #include "nvim/version.h" @@ -83,11 +80,32 @@ static void nlua_error(lua_State *const lstate, const char *const msg) const char *const str = lua_tolstring(lstate, -1, &len); msg_ext_set_kind("lua_error"); - emsgf_multiline(msg, (int)len, str); + semsg_multiline(msg, (int)len, str); lua_pop(lstate, 1); } +/// Like lua_pcall, but use debug.traceback as errfunc. +/// +/// @param lstate Lua interpreter state +/// @param[in] nargs Number of arguments expected by the function being called. +/// @param[in] nresults Number of results the function returns. +static int nlua_pcall(lua_State *lstate, int nargs, int nresults) +{ + lua_getglobal(lstate, "debug"); + lua_getfield(lstate, -1, "traceback"); + lua_remove(lstate, -2); + lua_insert(lstate, -2 - nargs); + int status = lua_pcall(lstate, nargs, nresults, -2 - nargs); + if (status) { + lua_remove(lstate, -2); + } else { + lua_remove(lstate, -1 - nresults); + } + return status; +} + + /// Gets the version of the current Nvim build. /// /// @param lstate Lua interpreter state. @@ -99,118 +117,12 @@ static int nlua_nvim_version(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL return 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 -{ - size_t s1_len; - size_t s2_len; - const char *s1 = luaL_checklstring(lstate, 1, &s1_len); - const char *s2 = luaL_checklstring(lstate, 2, &s2_len); - char *nul1; - char *nul2; - int ret = 0; - assert(s1[s1_len] == NUL); - assert(s2[s2_len] == NUL); - do { - nul1 = memchr(s1, NUL, s1_len); - nul2 = memchr(s2, NUL, s2_len); - ret = STRICMP(s1, s2); - if (ret == 0) { - // Compare "a\0" greater then "a". - if ((nul1 == NULL) != (nul2 == NULL)) { - ret = ((nul1 != NULL) - (nul2 != NULL)); - break; - } - if (nul1 != NULL) { - assert(nul2 != NULL); - // Can't shift both strings by the same amount of bytes: lowercase - // letter may have different byte-length than uppercase. - s1_len -= (size_t)(nul1 - s1) + 1; - s2_len -= (size_t)(nul2 - s2) + 1; - s1 = nul1 + 1; - s2 = nul2 + 1; - } else { - break; - } - } else { - break; - } - } while (true); - lua_pop(lstate, 2); - lua_pushnumber(lstate, (lua_Number)((ret > 0) - (ret < 0))); - return 1; -} - -/// convert byte index to UTF-32 and UTF-16 indices -/// -/// Expects a string and an optional index. If no index is supplied, the length -/// of the string is returned. -/// -/// Returns two values: the UTF-32 and UTF-16 indices. -static int nlua_str_utfindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL -{ - size_t s1_len; - const char *s1 = luaL_checklstring(lstate, 1, &s1_len); - intptr_t idx; - if (lua_gettop(lstate) >= 2) { - idx = luaL_checkinteger(lstate, 2); - if (idx < 0 || idx > (intptr_t)s1_len) { - return luaL_error(lstate, "index out of range"); - } - } else { - idx = (intptr_t)s1_len; - } - - size_t codepoints = 0, codeunits = 0; - mb_utflen((const char_u *)s1, (size_t)idx, &codepoints, &codeunits); - - lua_pushinteger(lstate, (long)codepoints); - lua_pushinteger(lstate, (long)codeunits); - - return 2; -} - -/// convert UTF-32 or UTF-16 indices to byte index. -/// -/// Expects up to three args: string, index and use_utf16. -/// If use_utf16 is not supplied it defaults to false (use UTF-32) -/// -/// Returns the byte index. -static int nlua_str_byteindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL -{ - size_t s1_len; - const char *s1 = luaL_checklstring(lstate, 1, &s1_len); - intptr_t idx = luaL_checkinteger(lstate, 2); - if (idx < 0) { - return luaL_error(lstate, "index out of range"); - } - bool use_utf16 = false; - if (lua_gettop(lstate) >= 3) { - use_utf16 = lua_toboolean(lstate, 3); - } - - ssize_t byteidx = mb_utf_index_to_bytes((const char_u *)s1, s1_len, - (size_t)idx, use_utf16); - if (byteidx == -1) { - return luaL_error(lstate, "index out of range"); - } - - lua_pushinteger(lstate, (long)byteidx); - - return 1; -} static void nlua_luv_error_event(void **argv) { char *error = (char *)argv[0]; msg_ext_set_kind("lua_error"); - emsgf_multiline("Error executing luv callback:\n%s", error); + semsg_multiline("Error executing luv callback:\n%s", error); xfree(error); } @@ -224,7 +136,7 @@ static int nlua_luv_cfpcall(lua_State *lstate, int nargs, int nresult, int flags in_fast_callback++; int top = lua_gettop(lstate); - int status = lua_pcall(lstate, nargs, nresult, 0); + int status = nlua_pcall(lstate, nargs, nresult); if (status) { if (status == LUA_ERRMEM && !(flags & LUVF_CALLBACK_NOEXIT)) { // consider out of memory errors unrecoverable, just like xmalloc() @@ -255,7 +167,7 @@ static void nlua_schedule_event(void **argv) lua_State *const lstate = global_lstate; nlua_pushref(lstate, cb); nlua_unref(lstate, cb); - if (lua_pcall(lstate, 0, 0, 0)) { + if (nlua_pcall(lstate, 0, 0)) { nlua_error(lstate, _("Error executing vim.schedule lua callback: %.*s")); } } @@ -278,14 +190,6 @@ static int nlua_schedule(lua_State *const lstate) return 0; } -static struct luaL_Reg regex_meta[] = { - { "__gc", regex_gc }, - { "__tostring", regex_tostring }, - { "match_str", regex_match_str }, - { "match_line", regex_match_line }, - { NULL, NULL } -}; - // Dummy timer callback. Used by f_wait(). static void dummy_timer_due_cb(TimeWatcher *tw, void *data) { @@ -300,7 +204,7 @@ static void dummy_timer_close_cb(TimeWatcher *tw, void *data) static bool nlua_wait_condition(lua_State *lstate, int *status, bool *callback_result) { lua_pushvalue(lstate, 2); - *status = lua_pcall(lstate, 0, 1, 0); + *status = nlua_pcall(lstate, 0, 1); if (*status) { return true; // break on error, but keep error on stack } @@ -422,39 +326,28 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL // vim lua_newtable(lstate); + // vim.api nlua_add_api_functions(lstate); + // vim.types, vim.type_idx, vim.val_idx nlua_init_types(lstate); - // stricmp - lua_pushcfunction(lstate, &nlua_stricmp); - lua_setfield(lstate, -2, "stricmp"); - // str_utfindex - lua_pushcfunction(lstate, &nlua_str_utfindex); - lua_setfield(lstate, -2, "str_utfindex"); - // str_byteindex - lua_pushcfunction(lstate, &nlua_str_byteindex); - lua_setfield(lstate, -2, "str_byteindex"); + // neovim version lua_pushcfunction(lstate, &nlua_nvim_version); lua_setfield(lstate, -2, "version"); + // schedule lua_pushcfunction(lstate, &nlua_schedule); lua_setfield(lstate, -2, "schedule"); + // in_fast_event lua_pushcfunction(lstate, &nlua_in_fast_event); lua_setfield(lstate, -2, "in_fast_event"); + // call lua_pushcfunction(lstate, &nlua_call); lua_setfield(lstate, -2, "call"); - // regex - lua_pushcfunction(lstate, &nlua_regex); - lua_setfield(lstate, -2, "regex"); - luaL_newmetatable(lstate, "nvim_regex"); - luaL_register(lstate, NULL, regex_meta); - lua_pushvalue(lstate, -1); // [meta, meta] - lua_setfield(lstate, -2, "__index"); // [meta] - lua_pop(lstate, 1); // don't use metatable now // rpcrequest lua_pushcfunction(lstate, &nlua_rpcrequest); @@ -468,30 +361,6 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_pushcfunction(lstate, &nlua_wait); lua_setfield(lstate, -2, "wait"); - // _getvar - lua_pushcfunction(lstate, &nlua_getvar); - lua_setfield(lstate, -2, "_getvar"); - - // _setvar - lua_pushcfunction(lstate, &nlua_setvar); - lua_setfield(lstate, -2, "_setvar"); - - - // vim.loop - luv_set_loop(lstate, &main_loop.uv); - luv_set_callback(lstate, nlua_luv_cfpcall); - luaopen_luv(lstate); - lua_pushvalue(lstate, -1); - lua_setfield(lstate, -3, "loop"); - - // package.loaded.luv = vim.loop - // otherwise luv will be reinitialized when require'luv' - lua_getglobal(lstate, "package"); - lua_getfield(lstate, -1, "loaded"); - lua_pushvalue(lstate, -3); - lua_setfield(lstate, -2, "luv"); - lua_pop(lstate, 3); - // vim.NIL lua_newuserdata(lstate, 0); lua_createtable(lstate, 0, 0); @@ -512,35 +381,32 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_setfield(lstate, LUA_REGISTRYINDEX, "mpack.empty_dict"); lua_setfield(lstate, -2, "_empty_dict_mt"); - // vim.mpack - luaopen_mpack(lstate); + // internal vim._treesitter... API + nlua_add_treesitter(lstate); + + // vim.loop + luv_set_loop(lstate, &main_loop.uv); + luv_set_callback(lstate, nlua_luv_cfpcall); + luaopen_luv(lstate); lua_pushvalue(lstate, -1); - lua_setfield(lstate, -3, "mpack"); + lua_setfield(lstate, -3, "loop"); - // package.loaded.mpack = vim.mpack - // otherwise luv will be reinitialized when require'mpack' + // package.loaded.luv = vim.loop + // otherwise luv will be reinitialized when require'luv' lua_getglobal(lstate, "package"); lua_getfield(lstate, -1, "loaded"); lua_pushvalue(lstate, -3); - lua_setfield(lstate, -2, "mpack"); + lua_setfield(lstate, -2, "luv"); lua_pop(lstate, 3); - // internal vim._treesitter... API - nlua_add_treesitter(lstate); - - // vim.diff - lua_pushcfunction(lstate, &nlua_xdl_diff); - lua_setfield(lstate, -2, "diff"); - - lua_cjson_new(lstate); - lua_setfield(lstate, -2, "json"); + nlua_state_add_stdlib(lstate); lua_setglobal(lstate, "vim"); { const char *code = (char *)&shared_module[0]; if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/shared.lua") - || lua_pcall(lstate, 0, 0, 0)) { + || nlua_pcall(lstate, 0, 0)) { nlua_error(lstate, _("E5106: Error while creating shared module: %.*s")); return 1; } @@ -552,7 +418,7 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL const char *code = (char *)&inspect_module[0]; if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/inspect.lua") - || lua_pcall(lstate, 0, 1, 0)) { + || nlua_pcall(lstate, 0, 1)) { nlua_error(lstate, _("E5106: Error while creating inspect module: %.*s")); return 1; } @@ -561,7 +427,7 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL code = (char *)&lua_F_module[0]; if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/F.lua") - || lua_pcall(lstate, 0, 1, 0)) { + || nlua_pcall(lstate, 0, 1)) { nlua_error(lstate, _("E5106: Error while creating vim.F module: %.*s")); return 1; } @@ -574,7 +440,7 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL { const char *code = (char *)&vim_module[0]; if (luaL_loadbuffer(lstate, code, strlen(code), "@vim.lua") - || lua_pcall(lstate, 0, 0, 0)) { + || nlua_pcall(lstate, 0, 0)) { nlua_error(lstate, _("E5106: Error while creating vim module: %.*s")); return 1; } @@ -586,7 +452,7 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL const char *code = (char *)&lua_meta_module[0]; if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/_meta.lua") - || lua_pcall(lstate, 0, 1, 0)) { + || nlua_pcall(lstate, 0, 1)) { nlua_error(lstate, _("E5106: Error while creating vim._meta module: %.*s")); return 1; } @@ -613,7 +479,7 @@ void nlua_init(void) lua_State *lstate = luaL_newstate(); if (lstate == NULL) { - EMSG(_("E970: Failed to initialize lua interpreter")); + emsg(_("E970: Failed to initialize lua interpreter")); preserve_exit(); } luaL_openlibs(lstate); @@ -674,10 +540,10 @@ static void nlua_print_event(void **argv) } break; } - msg((char_u *)str + start); + msg(str + start); } if (len && str[len - 1] == NUL) { // Last was newline - msg((char_u *)""); + msg(""); } xfree(str); } @@ -704,6 +570,7 @@ static int nlua_print(lua_State *const lstate) for (; curargidx <= nargs; curargidx++) { lua_pushvalue(lstate, -1); // tostring lua_pushvalue(lstate, curargidx); // arg + // Do not use nlua_pcall here to avoid duplicate stack trace information if (lua_pcall(lstate, 1, 1, 0)) { errmsg = lua_tolstring(lstate, -1, &errmsg_len); goto nlua_print_error; @@ -743,7 +610,7 @@ nlua_print_error: /// debug.debug: interaction with user while debugging. /// /// @param lstate Lua interpreter state. -int nlua_debug(lua_State *lstate) +static int nlua_debug(lua_State *lstate) FUNC_ATTR_NONNULL_ALL { const typval_T input_args[] = { @@ -771,7 +638,7 @@ int nlua_debug(lua_State *lstate) 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")); - } else if (lua_pcall(lstate, 0, 0, 0)) { + } else if (nlua_pcall(lstate, 0, 0)) { nlua_error(lstate, _("E5116: Error while calling debug string: %.*s")); } tv_clear(&input); @@ -898,109 +765,6 @@ check_err: return request ? 1 : 0; } -static dict_T *nlua_get_var_scope(lua_State *lstate) { - const char *scope = luaL_checkstring(lstate, 1); - handle_T handle = (handle_T)luaL_checkinteger(lstate, 2); - dict_T *dict = NULL; - Error err = ERROR_INIT; - if (strequal(scope, "g")) { - dict = &globvardict; - } else if (strequal(scope, "v")) { - dict = &vimvardict; - } else if (strequal(scope, "b")) { - buf_T *buf = find_buffer_by_handle(handle, &err); - if (buf) { - dict = buf->b_vars; - } - } else if (strequal(scope, "w")) { - win_T *win = find_window_by_handle(handle, &err); - if (win) { - dict = win->w_vars; - } - } else if (strequal(scope, "t")) { - tabpage_T *tabpage = find_tab_by_handle(handle, &err); - if (tabpage) { - dict = tabpage->tp_vars; - } - } else { - luaL_error(lstate, "invalid scope", err.msg); - return NULL; - } - - if (ERROR_SET(&err)) { - luaL_error(lstate, "FAIL: %s", err.msg); - return NULL; - } - return dict; -} - - -static int nlua_getvar(lua_State *lstate) -{ - // non-local return if not found - dict_T *dict = nlua_get_var_scope(lstate); - size_t len; - const char *name = luaL_checklstring(lstate, 3, &len); - - dictitem_T *di = tv_dict_find(dict, name, (ptrdiff_t)len); - if (di == NULL) { - return 0; // nil - } - nlua_push_typval(lstate, &di->di_tv, false); - return 1; -} - -static int nlua_setvar(lua_State *lstate) -{ - // non-local return if not found - dict_T *dict = nlua_get_var_scope(lstate); - String key; - key.data = (char *)luaL_checklstring(lstate, 3, &key.size); - - bool del = (lua_gettop(lstate) < 4) || lua_isnil(lstate, 4); - - Error err = ERROR_INIT; - dictitem_T *di = dict_check_writable(dict, key, del, &err); - if (ERROR_SET(&err)) { - return 0; - } - - if (del) { - // Delete the key - if (di == NULL) { - // Doesn't exist, nothing to do - return 0; - } else { - // Delete the entry - tv_dict_item_remove(dict, di); - } - } else { - // Update the key - typval_T tv; - - // Convert the lua value to a vimscript type in the temporary variable - lua_pushvalue(lstate, 4); - if (!nlua_pop_typval(lstate, &tv)) { - return luaL_error(lstate, "Couldn't convert lua value"); - } - - if (di == NULL) { - // Need to create an entry - di = tv_dict_item_alloc_len(key.data, key.size); - tv_dict_add(dict, di); - } else { - // Clear the old value - tv_clear(&di->di_tv); - } - - // Update the value - tv_copy(&tv, &di->di_tv); - // Clear the temporary variable - tv_clear(&tv); - } - return 0; -} - static int nlua_nil_tostring(lua_State *lstate) { lua_pushstring(lstate, "vim.NIL"); @@ -1167,7 +931,7 @@ static void nlua_typval_exec(const char *lcmd, size_t lcmd_len, const char *name PUSH_ALL_TYPVALS(lstate, args, argcount, special); - if (lua_pcall(lstate, argcount, ret_tv ? 1 : 0, 0)) { + if (nlua_pcall(lstate, argcount, ret_tv ? 1 : 0)) { nlua_error(lstate, _("E5108: Error executing lua %.*s")); return; } @@ -1222,7 +986,7 @@ int typval_exec_lua_callable(lua_State *lstate, LuaCallable lua_cb, int argcount PUSH_ALL_TYPVALS(lstate, argvars, argcount, false); - if (lua_pcall(lstate, argcount, 1, 0)) { + if (nlua_pcall(lstate, argcount, 1)) { nlua_print(lstate); return ERROR_OTHER; } @@ -1257,7 +1021,7 @@ Object nlua_exec(const String str, const Array args, Error *err) nlua_push_Object(lstate, args.items[i], false); } - if (lua_pcall(lstate, (int)args.size, 1, 0)) { + if (nlua_pcall(lstate, (int)args.size, 1)) { size_t len; const char *errstr = lua_tolstring(lstate, -1, &len); api_set_error(err, kErrorTypeException, @@ -1290,7 +1054,7 @@ Object nlua_call_ref(LuaRef ref, const char *name, Array args, bool retval, Erro nlua_push_Object(lstate, args.items[i], false); } - if (lua_pcall(lstate, nargs, retval ? 1 : 0, 0)) { + if (nlua_pcall(lstate, nargs, retval ? 1 : 0)) { // if err is passed, the caller will deal with the error. if (err) { size_t len; @@ -1349,7 +1113,7 @@ 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")); + emsg(_("cannot save undo information")); return; } const char *const cmd = (const char *)eap->arg; @@ -1384,7 +1148,7 @@ void ex_luado(exarg_T *const eap) if (lcmd_len >= IOSIZE) { xfree(lcmd); } - if (lua_pcall(lstate, 0, 1, 0)) { + if (nlua_pcall(lstate, 0, 1)) { nlua_error(lstate, _("E5110: Error executing lua: %.*s")); return; } @@ -1396,7 +1160,7 @@ void ex_luado(exarg_T *const eap) const char *old_line = (const char *)ml_get_buf(curbuf, l, false); lua_pushstring(lstate, old_line); lua_pushnumber(lstate, (lua_Number)l); - if (lua_pcall(lstate, 2, 1, 0)) { + if (nlua_pcall(lstate, 2, 1)) { nlua_error(lstate, _("E5111: Error calling lua: %.*s")); break; } @@ -1447,7 +1211,7 @@ bool nlua_exec_file(const char *path) return false; } - if (lua_pcall(lstate, 0, 0, 0)) { + if (nlua_pcall(lstate, 0, 0)) { nlua_error(lstate, _("E5113: Error while calling lua chunk: %.*s")); return false; } @@ -1499,7 +1263,7 @@ int nlua_expand_pat(expand_T *xp, char_u *pat, int *num_results, char_u ***resul // [ vim, vim._on_key, buf ] lua_pushlstring(lstate, (const char *)pat, STRLEN(pat)); - if (lua_pcall(lstate, 1, 2, 0) != 0) { + if (nlua_pcall(lstate, 1, 2) != 0) { nlua_error(lstate, _("Error executing vim._expand_pat: %.*s")); return FAIL; @@ -1553,139 +1317,6 @@ cleanup: return ret; } -static int nlua_regex(lua_State *lstate) -{ - Error err = ERROR_INIT; - const char *text = luaL_checkstring(lstate, 1); - regprog_T *prog = NULL; - - TRY_WRAP({ - try_start(); - prog = vim_regcomp((char_u *)text, RE_AUTO | RE_MAGIC | RE_STRICT); - try_end(&err); - }); - - if (ERROR_SET(&err)) { - return luaL_error(lstate, "couldn't parse regex: %s", err.msg); - } - assert(prog); - - regprog_T **p = lua_newuserdata(lstate, sizeof(regprog_T *)); - *p = prog; - - lua_getfield(lstate, LUA_REGISTRYINDEX, "nvim_regex"); // [udata, meta] - lua_setmetatable(lstate, -2); // [udata] - return 1; -} - -static regprog_T **regex_check(lua_State *L) -{ - return luaL_checkudata(L, 1, "nvim_regex"); -} - - -static int regex_gc(lua_State *lstate) -{ - regprog_T **prog = regex_check(lstate); - vim_regfree(*prog); - return 0; -} - -static int regex_tostring(lua_State *lstate) -{ - lua_pushstring(lstate, "<regex>"); - return 1; -} - -static int regex_match(lua_State *lstate, regprog_T **prog, char_u *str) -{ - regmatch_T rm; - rm.regprog = *prog; - rm.rm_ic = false; - bool match = vim_regexec(&rm, str, 0); - *prog = rm.regprog; - - if (match) { - lua_pushinteger(lstate, (lua_Integer)(rm.startp[0]-str)); - lua_pushinteger(lstate, (lua_Integer)(rm.endp[0]-str)); - return 2; - } - return 0; -} - -static int regex_match_str(lua_State *lstate) -{ - regprog_T **prog = regex_check(lstate); - const char *str = luaL_checkstring(lstate, 2); - int nret = regex_match(lstate, prog, (char_u *)str); - - if (!*prog) { - return luaL_error(lstate, "regex: internal error"); - } - - return nret; -} - -static int regex_match_line(lua_State *lstate) -{ - regprog_T **prog = regex_check(lstate); - - int narg = lua_gettop(lstate); - if (narg < 3) { - return luaL_error(lstate, "not enough args"); - } - - long bufnr = luaL_checkinteger(lstate, 2); - long rownr = luaL_checkinteger(lstate, 3); - long start = 0, end = -1; - if (narg >= 4) { - start = luaL_checkinteger(lstate, 4); - } - if (narg >= 5) { - end = luaL_checkinteger(lstate, 5); - if (end < 0) { - return luaL_error(lstate, "invalid end"); - } - } - - buf_T *buf = bufnr ? handle_get_buffer((int)bufnr) : curbuf; - if (!buf || buf->b_ml.ml_mfp == NULL) { - return luaL_error(lstate, "invalid buffer"); - } - - if (rownr >= buf->b_ml.ml_line_count) { - return luaL_error(lstate, "invalid row"); - } - - char_u *line = ml_get_buf(buf, rownr+1, false); - size_t len = STRLEN(line); - - if (start < 0 || (size_t)start > len) { - return luaL_error(lstate, "invalid start"); - } - - char_u save = NUL; - if (end >= 0) { - if ((size_t)end > len || end < start) { - return luaL_error(lstate, "invalid end"); - } - save = line[end]; - line[end] = NUL; - } - - int nret = regex_match(lstate, prog, line+start); - - if (end >= 0) { - line[end] = save; - } - - if (!*prog) { - return luaL_error(lstate, "regex: internal error"); - } - - return nret; -} - // Required functions for lua c functions as VimL callbacks int nlua_CFunction_func_call(int argcount, typval_T *argvars, typval_T *rettv, void *state) @@ -1785,7 +1416,7 @@ void nlua_execute_on_key(int c) // [ vim, vim._on_key, buf ] lua_pushlstring(lstate, (const char *)buf, buf_len); - if (lua_pcall(lstate, 1, 0, 0)) { + if (nlua_pcall(lstate, 1, 0)) { nlua_error(lstate, _("Error executing vim.on_key Lua callback: %.*s")); } diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c new file mode 100644 index 0000000000..db79e9e7e9 --- /dev/null +++ b/src/nvim/lua/stdlib.c @@ -0,0 +1,524 @@ +// 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 <lauxlib.h> +#include <lua.h> +#include <lualib.h> + +#include "cjson/lua_cjson.h" +#include "luv/luv.h" +#include "mpack/lmpack.h" +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/api/vim.h" +#include "nvim/ascii.h" +#include "nvim/assert.h" +#include "nvim/buffer_defs.h" +#include "nvim/change.h" +#include "nvim/cursor.h" +#include "nvim/eval/userfunc.h" +#include "nvim/event/loop.h" +#include "nvim/event/time.h" +#include "nvim/ex_cmds2.h" +#include "nvim/ex_getln.h" +#include "nvim/extmark.h" +#include "nvim/func_attr.h" +#include "nvim/garray.h" +#include "nvim/getchar.h" +#include "nvim/lua/converter.h" +#include "nvim/lua/executor.h" +#include "nvim/lua/stdlib.h" +#include "nvim/lua/treesitter.h" +#include "nvim/lua/xdiff.h" +#include "nvim/macros.h" +#include "nvim/map.h" +#include "nvim/memline.h" +#include "nvim/message.h" +#include "nvim/misc1.h" +#include "nvim/msgpack_rpc/channel.h" +#include "nvim/os/os.h" +#include "nvim/regexp.h" +#include "nvim/regexp_defs.h" +#include "nvim/screen.h" +#include "nvim/types.h" +#include "nvim/undo.h" +#include "nvim/version.h" +#include "nvim/vim.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "lua/stdlib.c.generated.h" +#endif + +static int regex_match(lua_State *lstate, regprog_T **prog, char_u *str) +{ + regmatch_T rm; + rm.regprog = *prog; + rm.rm_ic = false; + bool match = vim_regexec(&rm, str, 0); + *prog = rm.regprog; + + if (match) { + lua_pushinteger(lstate, (lua_Integer)(rm.startp[0]-str)); + lua_pushinteger(lstate, (lua_Integer)(rm.endp[0]-str)); + return 2; + } + return 0; +} + +static int regex_match_str(lua_State *lstate) +{ + regprog_T **prog = regex_check(lstate); + const char *str = luaL_checkstring(lstate, 2); + int nret = regex_match(lstate, prog, (char_u *)str); + + if (!*prog) { + return luaL_error(lstate, "regex: internal error"); + } + + return nret; +} + +static int regex_match_line(lua_State *lstate) +{ + regprog_T **prog = regex_check(lstate); + + int narg = lua_gettop(lstate); + if (narg < 3) { + return luaL_error(lstate, "not enough args"); + } + + long bufnr = luaL_checkinteger(lstate, 2); + long rownr = luaL_checkinteger(lstate, 3); + long start = 0, end = -1; + if (narg >= 4) { + start = luaL_checkinteger(lstate, 4); + } + if (narg >= 5) { + end = luaL_checkinteger(lstate, 5); + if (end < 0) { + return luaL_error(lstate, "invalid end"); + } + } + + buf_T *buf = bufnr ? handle_get_buffer((int)bufnr) : curbuf; + if (!buf || buf->b_ml.ml_mfp == NULL) { + return luaL_error(lstate, "invalid buffer"); + } + + if (rownr >= buf->b_ml.ml_line_count) { + return luaL_error(lstate, "invalid row"); + } + + char_u *line = ml_get_buf(buf, rownr+1, false); + size_t len = STRLEN(line); + + if (start < 0 || (size_t)start > len) { + return luaL_error(lstate, "invalid start"); + } + + char_u save = NUL; + if (end >= 0) { + if ((size_t)end > len || end < start) { + return luaL_error(lstate, "invalid end"); + } + save = line[end]; + line[end] = NUL; + } + + int nret = regex_match(lstate, prog, line+start); + + if (end >= 0) { + line[end] = save; + } + + if (!*prog) { + return luaL_error(lstate, "regex: internal error"); + } + + return nret; +} + +static regprog_T **regex_check(lua_State *L) +{ + return luaL_checkudata(L, 1, "nvim_regex"); +} + +static int regex_gc(lua_State *lstate) +{ + regprog_T **prog = regex_check(lstate); + vim_regfree(*prog); + return 0; +} + +static int regex_tostring(lua_State *lstate) +{ + lua_pushstring(lstate, "<regex>"); + return 1; +} + +static struct luaL_Reg regex_meta[] = { + { "__gc", regex_gc }, + { "__tostring", regex_tostring }, + { "match_str", regex_match_str }, + { "match_line", regex_match_line }, + { NULL, NULL } +}; + +/// convert byte index to UTF-32 and UTF-16 indices +/// +/// Expects a string and an optional index. If no index is supplied, the length +/// of the string is returned. +/// +/// Returns two values: the UTF-32 and UTF-16 indices. +int nlua_str_utfindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + size_t s1_len; + const char *s1 = luaL_checklstring(lstate, 1, &s1_len); + intptr_t idx; + if (lua_gettop(lstate) >= 2) { + idx = luaL_checkinteger(lstate, 2); + if (idx < 0 || idx > (intptr_t)s1_len) { + return luaL_error(lstate, "index out of range"); + } + } else { + idx = (intptr_t)s1_len; + } + + size_t codepoints = 0, codeunits = 0; + mb_utflen((const char_u *)s1, (size_t)idx, &codepoints, &codeunits); + + lua_pushinteger(lstate, (long)codepoints); + lua_pushinteger(lstate, (long)codeunits); + + return 2; +} + +/// return byte indices of codepoints in a string (only supports utf-8 currently). +/// +/// Expects a string. +/// +/// Returns a list of codepoints. +static int nlua_str_utf_pos(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + size_t s1_len; + const char *s1 = luaL_checklstring(lstate, 1, &s1_len); + lua_newtable(lstate); + + size_t idx = 1; + size_t clen; + for (size_t i = 0; i < s1_len && s1[i] != NUL; i += clen) { + clen = (size_t)utf_ptr2len_len((const char_u *)(s1)+i, (int)(s1_len-i)); + lua_pushinteger(lstate, (long)i + 1); + lua_rawseti(lstate, -2, (int)idx); + idx++; + } + + return 1; +} + +/// Return the offset from the 1-indexed byte position to the first byte of the +/// current character. +/// +/// Expects a string and an int. +/// +/// Returns the byte offset to the first byte of the current character +/// pointed into by the offset. +static int nlua_str_utf_start(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + size_t s1_len; + const char *s1 = luaL_checklstring(lstate, 1, &s1_len); + long offset = luaL_checkinteger(lstate, 2); + if (offset < 0 || offset > (intptr_t)s1_len) { + return luaL_error(lstate, "index out of range"); + } + int tail_offset = mb_head_off((char_u *)s1, (char_u *)s1 + (char_u)offset - 1); + lua_pushinteger(lstate, tail_offset); + return 1; +} + +/// Return the offset from the 1-indexed byte position to the last +/// byte of the current character. +/// +/// Expects a string and an int. +/// +/// Returns the byte offset to the last byte of the current character +/// pointed into by the offset. +static int nlua_str_utf_end(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + size_t s1_len; + const char *s1 = luaL_checklstring(lstate, 1, &s1_len); + long offset = luaL_checkinteger(lstate, 2); + if (offset < 0 || offset > (intptr_t)s1_len) { + return luaL_error(lstate, "index out of range"); + } + int tail_offset = mb_tail_off((char_u *)s1, (char_u *)s1 + (char_u)offset - 1); + lua_pushinteger(lstate, tail_offset); + return 1; +} + +/// convert UTF-32 or UTF-16 indices to byte index. +/// +/// Expects up to three args: string, index and use_utf16. +/// If use_utf16 is not supplied it defaults to false (use UTF-32) +/// +/// Returns the byte index. +int nlua_str_byteindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + size_t s1_len; + const char *s1 = luaL_checklstring(lstate, 1, &s1_len); + intptr_t idx = luaL_checkinteger(lstate, 2); + if (idx < 0) { + return luaL_error(lstate, "index out of range"); + } + bool use_utf16 = false; + if (lua_gettop(lstate) >= 3) { + use_utf16 = lua_toboolean(lstate, 3); + } + + ssize_t byteidx = mb_utf_index_to_bytes((const char_u *)s1, s1_len, + (size_t)idx, use_utf16); + if (byteidx == -1) { + return luaL_error(lstate, "index out of range"); + } + + lua_pushinteger(lstate, (long)byteidx); + + return 1; +} + +int nlua_regex(lua_State *lstate) +{ + Error err = ERROR_INIT; + const char *text = luaL_checkstring(lstate, 1); + regprog_T *prog = NULL; + + TRY_WRAP({ + try_start(); + prog = vim_regcomp((char_u *)text, RE_AUTO | RE_MAGIC | RE_STRICT); + try_end(&err); + }); + + if (ERROR_SET(&err)) { + return luaL_error(lstate, "couldn't parse regex: %s", err.msg); + } + assert(prog); + + regprog_T **p = lua_newuserdata(lstate, sizeof(regprog_T *)); + *p = prog; + + lua_getfield(lstate, LUA_REGISTRYINDEX, "nvim_regex"); // [udata, meta] + lua_setmetatable(lstate, -2); // [udata] + return 1; +} + +static dict_T *nlua_get_var_scope(lua_State *lstate) +{ + const char *scope = luaL_checkstring(lstate, 1); + handle_T handle = (handle_T)luaL_checkinteger(lstate, 2); + dict_T *dict = NULL; + Error err = ERROR_INIT; + if (strequal(scope, "g")) { + dict = &globvardict; + } else if (strequal(scope, "v")) { + dict = &vimvardict; + } else if (strequal(scope, "b")) { + buf_T *buf = find_buffer_by_handle(handle, &err); + if (buf) { + dict = buf->b_vars; + } + } else if (strequal(scope, "w")) { + win_T *win = find_window_by_handle(handle, &err); + if (win) { + dict = win->w_vars; + } + } else if (strequal(scope, "t")) { + tabpage_T *tabpage = find_tab_by_handle(handle, &err); + if (tabpage) { + dict = tabpage->tp_vars; + } + } else { + luaL_error(lstate, "invalid scope", err.msg); + return NULL; + } + + if (ERROR_SET(&err)) { + luaL_error(lstate, "FAIL: %s", err.msg); + return NULL; + } + return dict; +} + + +int nlua_setvar(lua_State *lstate) +{ + // non-local return if not found + dict_T *dict = nlua_get_var_scope(lstate); + String key; + key.data = (char *)luaL_checklstring(lstate, 3, &key.size); + + bool del = (lua_gettop(lstate) < 4) || lua_isnil(lstate, 4); + + Error err = ERROR_INIT; + dictitem_T *di = dict_check_writable(dict, key, del, &err); + if (ERROR_SET(&err)) { + return 0; + } + + if (del) { + // Delete the key + if (di == NULL) { + // Doesn't exist, nothing to do + return 0; + } else { + // Delete the entry + tv_dict_item_remove(dict, di); + } + } else { + // Update the key + typval_T tv; + + // Convert the lua value to a vimscript type in the temporary variable + lua_pushvalue(lstate, 4); + if (!nlua_pop_typval(lstate, &tv)) { + return luaL_error(lstate, "Couldn't convert lua value"); + } + + if (di == NULL) { + // Need to create an entry + di = tv_dict_item_alloc_len(key.data, key.size); + tv_dict_add(dict, di); + } else { + // Clear the old value + tv_clear(&di->di_tv); + } + + // Update the value + tv_copy(&tv, &di->di_tv); + // Clear the temporary variable + tv_clear(&tv); + } + return 0; +} + +int nlua_getvar(lua_State *lstate) +{ + // non-local return if not found + dict_T *dict = nlua_get_var_scope(lstate); + size_t len; + const char *name = luaL_checklstring(lstate, 3, &len); + + dictitem_T *di = tv_dict_find(dict, name, (ptrdiff_t)len); + if (di == NULL) { + return 0; // nil + } + nlua_push_typval(lstate, &di->di_tv, false); + return 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 +{ + size_t s1_len; + size_t s2_len; + const char *s1 = luaL_checklstring(lstate, 1, &s1_len); + const char *s2 = luaL_checklstring(lstate, 2, &s2_len); + char *nul1; + char *nul2; + int ret = 0; + assert(s1[s1_len] == NUL); + assert(s2[s2_len] == NUL); + do { + nul1 = memchr(s1, NUL, s1_len); + nul2 = memchr(s2, NUL, s2_len); + ret = STRICMP(s1, s2); + if (ret == 0) { + // Compare "a\0" greater then "a". + if ((nul1 == NULL) != (nul2 == NULL)) { + ret = ((nul1 != NULL) - (nul2 != NULL)); + break; + } + if (nul1 != NULL) { + assert(nul2 != NULL); + // Can't shift both strings by the same amount of bytes: lowercase + // letter may have different byte-length than uppercase. + s1_len -= (size_t)(nul1 - s1) + 1; + s2_len -= (size_t)(nul2 - s2) + 1; + s1 = nul1 + 1; + s2 = nul2 + 1; + } else { + break; + } + } else { + break; + } + } while (true); + lua_pop(lstate, 2); + lua_pushnumber(lstate, (lua_Number)((ret > 0) - (ret < 0))); + return 1; +} + + +void nlua_state_add_stdlib(lua_State *const lstate) +{ + // stricmp + lua_pushcfunction(lstate, &nlua_stricmp); + lua_setfield(lstate, -2, "stricmp"); + // str_utfindex + lua_pushcfunction(lstate, &nlua_str_utfindex); + lua_setfield(lstate, -2, "str_utfindex"); + // str_byteindex + lua_pushcfunction(lstate, &nlua_str_byteindex); + lua_setfield(lstate, -2, "str_byteindex"); + // str_utf_pos + lua_pushcfunction(lstate, &nlua_str_utf_pos); + lua_setfield(lstate, -2, "str_utf_pos"); + // str_utf_start + lua_pushcfunction(lstate, &nlua_str_utf_start); + lua_setfield(lstate, -2, "str_utf_start"); + // str_utf_end + lua_pushcfunction(lstate, &nlua_str_utf_end); + lua_setfield(lstate, -2, "str_utf_end"); + // regex + lua_pushcfunction(lstate, &nlua_regex); + lua_setfield(lstate, -2, "regex"); + luaL_newmetatable(lstate, "nvim_regex"); + luaL_register(lstate, NULL, regex_meta); + + lua_pushvalue(lstate, -1); // [meta, meta] + lua_setfield(lstate, -2, "__index"); // [meta] + lua_pop(lstate, 1); // don't use metatable now + + // _getvar + lua_pushcfunction(lstate, &nlua_getvar); + lua_setfield(lstate, -2, "_getvar"); + + // _setvar + lua_pushcfunction(lstate, &nlua_setvar); + lua_setfield(lstate, -2, "_setvar"); + + // vim.mpack + luaopen_mpack(lstate); + lua_pushvalue(lstate, -1); + lua_setfield(lstate, -3, "mpack"); + + // package.loaded.mpack = vim.mpack + // otherwise luv will be reinitialized when require'mpack' + lua_getglobal(lstate, "package"); + lua_getfield(lstate, -1, "loaded"); + lua_pushvalue(lstate, -3); + lua_setfield(lstate, -2, "mpack"); + lua_pop(lstate, 3); + + // vim.diff + lua_pushcfunction(lstate, &nlua_xdl_diff); + lua_setfield(lstate, -2, "diff"); + + lua_cjson_new(lstate); + lua_setfield(lstate, -2, "json"); +} diff --git a/src/nvim/lua/stdlib.h b/src/nvim/lua/stdlib.h new file mode 100644 index 0000000000..17aec6714d --- /dev/null +++ b/src/nvim/lua/stdlib.h @@ -0,0 +1,10 @@ +#ifndef NVIM_LUA_STDLIB_H +#define NVIM_LUA_STDLIB_H + +#include <lua.h> + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "lua/stdlib.h.generated.h" +#endif + +#endif // NVIM_LUA_STDLIB_H diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index 02bd612149..60a000843f 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -1195,7 +1195,8 @@ int tslua_parse_query(lua_State *L) } -static const char *query_err_string(TSQueryError err) { +static const char *query_err_string(TSQueryError err) +{ switch (err) { case TSQueryErrorSyntax: return "invalid syntax"; diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua index 51b7430957..30c7034209 100644 --- a/src/nvim/lua/vim.lua +++ b/src/nvim/lua/vim.lua @@ -323,22 +323,25 @@ end do local validate = vim.validate - local function make_dict_accessor(scope) + local function make_dict_accessor(scope, handle) validate { scope = {scope, 's'}; } local mt = {} function mt:__newindex(k, v) - return vim._setvar(scope, 0, k, v) + return vim._setvar(scope, handle or 0, k, v) end function mt:__index(k) - return vim._getvar(scope, 0, k) + if handle == nil and type(k) == 'number' then + return make_dict_accessor(scope, k) + end + return vim._getvar(scope, handle or 0, k) end return setmetatable({}, mt) end - vim.g = make_dict_accessor('g') - vim.v = make_dict_accessor('v') + vim.g = make_dict_accessor('g', false) + vim.v = make_dict_accessor('v', false) vim.b = make_dict_accessor('b') vim.w = make_dict_accessor('w') vim.t = make_dict_accessor('t') diff --git a/src/nvim/macros.h b/src/nvim/macros.h index 50ee91dc36..faef0f69b2 100644 --- a/src/nvim/macros.h +++ b/src/nvim/macros.h @@ -92,30 +92,18 @@ #define REPLACE_NORMAL(s) (((s) & REPLACE_FLAG) && !((s) & VREPLACE_FLAG)) -#define UTF_COMPOSINGLIKE(p1, p2) utf_composinglike((p1), (p2)) // MB_PTR_ADV(): advance a pointer to the next character, taking care of -// multi-byte characters if needed. -// MB_PTR_BACK(): backup a pointer to the previous character, taking care of -// multi-byte characters if needed. -// MB_COPY_CHAR(f, t): copy one char from "f" to "t" and advance the pointers. -// PTR2CHAR(): get character from pointer. +// multi-byte characters if needed. Skip over composing chars. +#define MB_PTR_ADV(p) (p += utfc_ptr2len((char_u *)p)) -// Advance multi-byte pointer, skip over composing chars. -#define MB_PTR_ADV(p) (p += mb_ptr2len((char_u *)p)) // Advance multi-byte pointer, do not skip over composing chars. #define MB_CPTR_ADV(p) (p += utf_ptr2len(p)) -// Backup multi-byte pointer. Only use with "p" > "s" ! + +// MB_PTR_BACK(): backup a pointer to the previous character, taking care of +// multi-byte characters if needed. Only use with "p" > "s" ! #define MB_PTR_BACK(s, p) \ (p -= utf_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_COPY_CHAR(f, t) mb_copy_char((const char_u **)(&f), &t); - -#define MB_CHARLEN(p) mb_charlen(p) -#define MB_CHAR2LEN(c) mb_char2len(c) -#define PTR2CHAR(p) utf_ptr2char(p) #define RESET_BINDING(wp) \ do { \ @@ -204,11 +192,11 @@ /// #if defined(__clang__) && __clang__ == 1 # define PRAGMA_DIAG_PUSH_IGNORE_MISSING_PROTOTYPES \ - _Pragma("clang diagnostic push")\ + _Pragma("clang diagnostic push") \ _Pragma("clang diagnostic ignored \"-Wmissing-prototypes\"") # ifdef HAVE_WIMPLICIT_FALLTHROUGH_FLAG # define PRAGMA_DIAG_PUSH_IGNORE_IMPLICIT_FALLTHROUGH \ - _Pragma("clang diagnostic push")\ + _Pragma("clang diagnostic push") \ _Pragma("clang diagnostic ignored \"-Wimplicit-fallthrough\"") # else # define PRAGMA_DIAG_PUSH_IGNORE_IMPLICIT_FALLTHROUGH \ @@ -218,11 +206,11 @@ _Pragma("clang diagnostic pop") #elif defined(__GNUC__) # define PRAGMA_DIAG_PUSH_IGNORE_MISSING_PROTOTYPES \ - _Pragma("GCC diagnostic push")\ + _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wmissing-prototypes\"") # ifdef HAVE_WIMPLICIT_FALLTHROUGH_FLAG # define PRAGMA_DIAG_PUSH_IGNORE_IMPLICIT_FALLTHROUGH \ - _Pragma("GCC diagnostic push")\ + _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") # else # define PRAGMA_DIAG_PUSH_IGNORE_IMPLICIT_FALLTHROUGH \ diff --git a/src/nvim/main.c b/src/nvim/main.c index 00a43c9c79..921bc883cf 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -81,7 +81,7 @@ #ifndef WIN32 # include "nvim/os/pty_process_unix.h" #endif -#include "nvim/api/vim.h" +#include "nvim/api/extmark.h" // values for "window_layout" #define WIN_HOR 1 // "-o" horizontally split windows @@ -674,8 +674,7 @@ void getout(int exitval) profile_dump(); - if (did_emsg - ) { + if (did_emsg) { // give the user a chance to read the (error) message no_wait_return = FALSE; wait_return(FALSE); @@ -824,11 +823,11 @@ static void command_line_scan(mparm_T *parmp) 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)); + semsg(_("E5421: Failed to open stdin: %s"), os_strerror(fof_ret)); } if (p == NULL) { - EMSG(_(e_outofmem)); + emsg(_(e_outofmem)); } Object md = DICTIONARY_OBJ(api_metadata()); @@ -1461,9 +1460,9 @@ static void create_windows(mparm_T *parmp) did_emsg = FALSE; // avoid hit-enter prompt getout(1); } - /* We can't close the window, it would disturb what - * happens next. Clear the file name and set the arg - * index to -1 to delete it later. */ + // We can't close the window, it would disturb what + // happens next. Clear the file name and set the arg + // index to -1 to delete it later. setfname(curbuf, NULL, NULL, false); curwin->w_arg_idx = -1; swap_exists_action = SEA_NONE; @@ -1553,8 +1552,8 @@ static void edit_buffers(mparm_T *parmp, char_u *cwd) // happen when vimrc contains ":sall"). if (curbuf == firstwin->w_buffer || curbuf->b_ffname == NULL) { curwin->w_arg_idx = arg_idx; - /* Edit file from arg list, if there is one. When "Quit" selected - * at the ATTENTION prompt close the window. */ + // Edit file from arg list, if there is one. When "Quit" selected + // at the ATTENTION prompt close the window. swap_exists_did_quit = false; (void)do_ecmd(0, arg_idx < GARGCOUNT ? alist_name(&GARGLIST[arg_idx]) : NULL, @@ -1698,8 +1697,11 @@ static void do_system_initialization(void) } char *vimrc = xmalloc(dir_len + sizeof(path_tail) + 1); memcpy(vimrc, dir, dir_len); - vimrc[dir_len] = PATHSEP; - memcpy(vimrc + dir_len + 1, path_tail, sizeof(path_tail)); + if (vimrc[dir_len - 1] != PATHSEP) { + vimrc[dir_len] = PATHSEP; + dir_len += 1; + } + memcpy(vimrc + dir_len, path_tail, sizeof(path_tail)); if (do_source(vimrc, false, DOSO_NONE) != FAIL) { xfree(vimrc); xfree(config_dirs); @@ -1743,7 +1745,7 @@ static bool do_user_initialization(void) if (os_path_exists(init_lua_path) && do_source((char *)init_lua_path, true, DOSO_VIMRC)) { if (os_path_exists(user_vimrc)) { - EMSG3(_("E5422: Conflicting configs: \"%s\" \"%s\""), init_lua_path, + semsg(_("E5422: Conflicting configs: \"%s\" \"%s\""), init_lua_path, user_vimrc); } @@ -1815,7 +1817,7 @@ static void source_startup_scripts(const mparm_T *const parmp) // Do nothing. } else { if (do_source(parmp->use_vimrc, false, DOSO_NONE) != OK) { - EMSG2(_("E282: Cannot read from \"%s\""), parmp->use_vimrc); + semsg(_("E282: Cannot read from \"%s\""), parmp->use_vimrc); } } } else if (!silent_mode) { diff --git a/src/nvim/map.c b/src/nvim/map.c index 20d5570e8c..1d9abe3ef2 100644 --- a/src/nvim/map.c +++ b/src/nvim/map.c @@ -51,36 +51,28 @@ #define MAP_IMPL(T, U, ...) \ INITIALIZER_DECLARE(T, U, __VA_ARGS__); \ __KHASH_IMPL(T##_##U##_map, , T, U, 1, T##_hash, T##_eq) \ - \ void map_##T##_##U##_destroy(Map(T, U) *map) \ { \ kh_dealloc(T##_##U##_map, &map->table); \ } \ - \ U map_##T##_##U##_get(Map(T, U) *map, T key) \ { \ khiter_t k; \ - \ if ((k = kh_get(T##_##U##_map, &map->table, key)) == kh_end(&map->table)) { \ return INITIALIZER(T, U); \ } \ - \ return kh_val(&map->table, k); \ } \ - \ bool map_##T##_##U##_has(Map(T, U) *map, T key) \ { \ return kh_get(T##_##U##_map, &map->table, key) != kh_end(&map->table); \ } \ - \ T map_##T##_##U##_key(Map(T, U) *map, T key) \ { \ khiter_t k; \ - \ if ((k = kh_get(T##_##U##_map, &map->table, key)) == kh_end(&map->table)) { \ abort(); /* Caller must check map_has(). */ \ } \ - \ return kh_key(&map->table, k); \ } \ U map_##T##_##U##_put(Map(T, U) *map, T key, U value) \ @@ -88,15 +80,12 @@ int ret; \ U rv = INITIALIZER(T, U); \ khiter_t k = kh_put(T##_##U##_map, &map->table, key, &ret); \ - \ if (!ret) { \ rv = kh_val(&map->table, k); \ } \ - \ kh_val(&map->table, k) = value; \ return rv; \ } \ - \ U *map_##T##_##U##_ref(Map(T, U) *map, T key, bool put) \ { \ int ret; \ @@ -112,23 +101,18 @@ return NULL; \ } \ } \ - \ return &kh_val(&map->table, k); \ } \ - \ U map_##T##_##U##_del(Map(T, U) *map, T key) \ { \ U rv = INITIALIZER(T, U); \ khiter_t k; \ - \ if ((k = kh_get(T##_##U##_map, &map->table, key)) != kh_end(&map->table)) { \ rv = kh_val(&map->table, k); \ kh_del(T##_##U##_map, &map->table, k); \ } \ - \ return rv; \ } \ - \ void map_##T##_##U##_clear(Map(T, U) *map) \ { \ kh_clear(T##_##U##_map, &map->table); \ diff --git a/src/nvim/map.h b/src/nvim/map.h index 6ed341ac76..dbd85a4e1f 100644 --- a/src/nvim/map.h +++ b/src/nvim/map.h @@ -16,11 +16,9 @@ #define MAP_DECLS(T, U) \ KHASH_DECLARE(T##_##U##_map, T, U) \ - \ typedef struct { \ khash_t(T##_##U##_map) table; \ } Map(T, U); \ - \ Map(T, U) *map_##T##_##U##_new(void); \ void map_##T##_##U##_free(Map(T, U) *map); \ void map_##T##_##U##_destroy(Map(T, U) *map); \ diff --git a/src/nvim/mark.c b/src/nvim/mark.c index ea9acdf31a..51f4ba635f 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -564,19 +564,19 @@ static void fmarks_check_one(xfmark_T *fm, char_u *name, buf_T *buf) int check_mark(pos_T *pos) { if (pos == NULL) { - EMSG(_(e_umark)); + emsg(_(e_umark)); return FAIL; } if (pos->lnum <= 0) { // lnum is negative if mark is in another file can can't get that // file, error message already give then. if (pos->lnum == 0) { - EMSG(_(e_marknotset)); + emsg(_(e_marknotset)); } return FAIL; } if (pos->lnum > curbuf->b_ml.ml_line_count) { - EMSG(_(e_markinval)); + emsg(_(e_markinval)); return FAIL; } return OK; @@ -711,9 +711,9 @@ static void show_one_mark(int c, char_u *arg, pos_T *p, char_u *name_arg, int cu did_title = false; } else { if (arg == NULL) { - MSG(_("No marks set")); + msg(_("No marks set")); } else { - EMSG2(_("E283: No marks matching \"%s\""), arg); + semsg(_("E283: No marks matching \"%s\""), arg); } } } else if (!got_int @@ -762,9 +762,9 @@ void ex_delmarks(exarg_T *eap) // clear all marks clrallmarks(curbuf); } else if (eap->forceit) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } else if (*eap->arg == NUL) { - EMSG(_(e_argreq)); + emsg(_(e_argreq)); } else { // clear specified marks only for (p = eap->arg; *p != NUL; ++p) { @@ -779,7 +779,7 @@ void ex_delmarks(exarg_T *eap) : (digit ? ascii_isdigit(p[2]) : ASCII_ISUPPER(p[2]))) || to < from) { - EMSG2(_(e_invarg2), p); + semsg(_(e_invarg2), p); return; } p += 2; @@ -821,7 +821,7 @@ void ex_delmarks(exarg_T *eap) case ' ': break; default: - EMSG2(_(e_invarg2), p); + semsg(_(e_invarg2), p); return; } } @@ -839,7 +839,7 @@ void ex_jumps(exarg_T *eap) cleanup_jumplist(curwin, true); // Highlight title - MSG_PUTS_TITLE(_("\n jump line col file/text")); + msg_puts_title(_("\n jump line col file/text")); for (i = 0; i < curwin->w_jumplistlen && !got_int; ++i) { if (curwin->w_jumplist[i].fmark.mark.lnum != 0) { name = fm_getname(&curwin->w_jumplist[i].fmark, 16); @@ -871,7 +871,7 @@ void ex_jumps(exarg_T *eap) ui_flush(); } if (curwin->w_jumplistidx == curwin->w_jumplistlen) { - MSG_PUTS("\n>"); + msg_puts("\n>"); } } @@ -891,7 +891,7 @@ void ex_changes(exarg_T *eap) char_u *name; // Highlight title - MSG_PUTS_TITLE(_("\nchange line col text")); + msg_puts_title(_("\nchange line col text")); for (i = 0; i < curbuf->b_changelistlen && !got_int; ++i) { if (curbuf->b_changelist[i].mark.lnum != 0) { @@ -914,7 +914,7 @@ void ex_changes(exarg_T *eap) ui_flush(); } if (curwin->w_changelistidx == curbuf->b_changelistlen) { - MSG_PUTS("\n>"); + msg_puts("\n>"); } } diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c index 39c1e36147..38014ab375 100644 --- a/src/nvim/marktree.c +++ b/src/nvim/marktree.c @@ -221,9 +221,11 @@ static inline void marktree_putp_aux(MarkTree *b, mtnode_t *x, mtkey_t k) } } -uint64_t marktree_put(MarkTree *b, int row, int col, bool right_gravity) +uint64_t marktree_put(MarkTree *b, int row, int col, bool right_gravity, uint8_t decor_level) { uint64_t id = (b->next_id+=ID_INCR); + assert(decor_level < DECOR_LEVELS); + id = id | ((uint64_t)decor_level << DECOR_OFFSET); uint64_t keyid = id; if (right_gravity) { // order all right gravity keys after the left ones, for effortless @@ -235,9 +237,11 @@ uint64_t marktree_put(MarkTree *b, int row, int col, bool right_gravity) } uint64_t marktree_put_pair(MarkTree *b, int start_row, int start_col, bool start_right, int end_row, - int end_col, bool end_right) + int end_col, bool end_right, uint8_t decor_level) { uint64_t id = (b->next_id+=ID_INCR)|PAIRED; + assert(decor_level < DECOR_LEVELS); + id = id | ((uint64_t)decor_level << DECOR_OFFSET); uint64_t start_id = id|(start_right?RIGHT_GRAVITY:0); uint64_t end_id = id|END_FLAG|(end_right?RIGHT_GRAVITY:0); marktree_put_key(b, start_row, start_col, start_id); @@ -566,11 +570,11 @@ void marktree_free_node(mtnode_t *x) } /// NB: caller must check not pair! -uint64_t marktree_revise(MarkTree *b, MarkTreeIter *itr) +uint64_t marktree_revise(MarkTree *b, MarkTreeIter *itr, uint8_t decor_level) { uint64_t old_id = rawkey(itr).id; pmap_del(uint64_t)(b->id2node, ANTIGRAVITY(old_id)); - uint64_t new_id = (b->next_id += ID_INCR); + uint64_t new_id = (b->next_id += ID_INCR) + ((uint64_t)decor_level << DECOR_OFFSET); rawkey(itr).id = new_id + (RIGHT_GRAVITY&old_id); refkey(b, itr->node, itr->i); return new_id; diff --git a/src/nvim/marktree.h b/src/nvim/marktree.h index 02f73b8052..a1dcdf5164 100644 --- a/src/nvim/marktree.h +++ b/src/nvim/marktree.h @@ -75,4 +75,13 @@ typedef struct { #define MARKTREE_PAIRED_FLAG (((uint64_t)1) << 1) #define MARKTREE_END_FLAG (((uint64_t)1) << 0) +#define DECOR_LEVELS 4 +#define DECOR_OFFSET 61 +#define DECOR_MASK (((uint64_t)(DECOR_LEVELS-1)) << DECOR_OFFSET) + +static inline uint8_t marktree_decor_level(uint64_t id) +{ + return (uint8_t)((id&DECOR_MASK) >> DECOR_OFFSET); +} + #endif // NVIM_MARKTREE_H diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 62cc3b56ed..12460646ed 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -346,7 +346,6 @@ static int enc_canon_search(const char_u *name) } - /* * Find canonical encoding "name" in the list and return its properties. * Returns 0 if not found. @@ -565,7 +564,7 @@ size_t mb_string2cells(const char_u *str) { size_t clen = 0; - for (const char_u *p = str; *p != NUL; p += (*mb_ptr2len)(p)) { + for (const char_u *p = str; *p != NUL; p += utfc_ptr2len(p)) { clen += utf_ptr2cells(p); } @@ -675,16 +674,16 @@ static int utf_safe_read_char_adv(const char_u **s, size_t *n) } if (k <= *n) { - /* We have a multibyte sequence and it isn't truncated by buffer - * limits so utf_ptr2char() is safe to use. Or the first byte is - * illegal (k=0), and it's also safe to use utf_ptr2char(). */ + // We have a multibyte sequence and it isn't truncated by buffer + // limits so utf_ptr2char() is safe to use. Or the first byte is + // illegal (k=0), and it's also safe to use utf_ptr2char(). c = utf_ptr2char(*s); - /* On failure, utf_ptr2char() returns the first byte, so here we - * check equality with the first byte. The only non-ASCII character - * which equals the first byte of its own UTF-8 representation is - * U+00C3 (UTF-8: 0xC3 0x83), so need to check that special case too. - * It's safe even if n=1, else we would have k=2 > n. */ + // On failure, utf_ptr2char() returns the first byte, so here we + // check equality with the first byte. The only non-ASCII character + // which equals the first byte of its own UTF-8 representation is + // U+00C3 (UTF-8: 0xC3 0x83), so need to check that special case too. + // It's safe even if n=1, else we would have k=2 > n. if (c != (int)(**s) || (c == 0xC3 && (*s)[1] == 0x83)) { // byte sequence was successfully decoded *s += k; @@ -706,7 +705,7 @@ int mb_ptr2char_adv(const char_u **const pp) int c; c = utf_ptr2char(*pp); - *pp += (*mb_ptr2len)(*pp); + *pp += utfc_ptr2len(*pp); return c; } @@ -763,7 +762,7 @@ int utfc_ptr2char(const char_u *p, int *pcc) // Only accept a composing char when the first char isn't illegal. if ((len > 1 || *p < 0x80) && p[len] >= 0x80 - && UTF_COMPOSINGLIKE(p, p + len)) { + && utf_composinglike(p, p + len)) { cc = utf_ptr2char(p + len); for (;; ) { pcc[i++] = cc; @@ -792,9 +791,6 @@ int utfc_ptr2char(const char_u *p, int *pcc) */ int utfc_ptr2char_len(const char_u *p, int *pcc, int maxlen) { -#define IS_COMPOSING(s1, s2, s3) \ - (i == 0 ? UTF_COMPOSINGLIKE((s1), (s2)) : utf_iscomposing((s3))) - assert(maxlen > 0); int i = 0; @@ -810,7 +806,7 @@ int utfc_ptr2char_len(const char_u *p, int *pcc, int maxlen) int len_cc = utf_ptr2len_len(p + len, maxlen - len); safe = len_cc > 1 && len_cc <= maxlen - len; if (!safe || (pcc[i] = utf_ptr2char(p + len)) < 0x80 - || !IS_COMPOSING(p, p + len, pcc[i])) { + || !(i == 0 ? utf_composinglike(p, p+len) : utf_iscomposing(pcc[i]))) { break; } len += len_cc; @@ -915,7 +911,7 @@ int utfc_ptr2len(const char_u *const p) // skip all of them (otherwise the cursor would get stuck). int prevlen = 0; for (;;) { - if (p[len] < 0x80 || !UTF_COMPOSINGLIKE(p + prevlen, p + len)) { + if (p[len] < 0x80 || !utf_composinglike(p + prevlen, p + len)) { return len; } @@ -965,14 +961,14 @@ int utfc_ptr2len_len(const char_u *p, int size) /* * Next character length should not go beyond size to ensure that - * UTF_COMPOSINGLIKE(...) does not read beyond size. + * utf_composinglike(...) does not read beyond size. */ len_next_char = utf_ptr2len_len(p + len, size - len); if (len_next_char > size - len) { break; } - if (!UTF_COMPOSINGLIKE(p + prevlen, p + len)) { + if (!utf_composinglike(p + prevlen, p + len)) { break; } @@ -1582,12 +1578,12 @@ void show_utf8(void) int clen; int i; - /* Get the byte length of the char under the cursor, including composing - * characters. */ + // Get the byte length of the char under the cursor, including composing + // characters. line = get_cursor_pos_ptr(); len = utfc_ptr2len(line); if (len == 0) { - MSG("NUL"); + msg("NUL"); return; } @@ -1610,7 +1606,7 @@ void show_utf8(void) } } - msg(IObuff); + msg((char *)IObuff); } /// Return offset from "p" to the first byte of the character it points into. @@ -1625,8 +1621,8 @@ int utf_head_off(const char_u *base, const char_u *p) return 0; } - /* Skip backwards over trailing bytes: 10xx.xxxx - * Skip backwards again if on a composing char. */ + // Skip backwards over trailing bytes: 10xx.xxxx + // Skip backwards again if on a composing char. const char_u *q; for (q = p;; --q) { // Move s to the last byte of this char. @@ -1883,6 +1879,40 @@ int mb_tail_off(char_u *base, char_u *p) return i; } + +/// Return the offset from "p" to the first byte of the character it points +/// into. Can start anywhere in a stream of bytes. +/// +/// @param[in] base Pointer to start of string +/// @param[in] p Pointer to byte for which to return the offset to the previous codepoint +// +/// @return 0 if invalid sequence, else offset to previous codepoint +int mb_head_off(char_u *base, char_u *p) +{ + int i; + int j; + + if (*p == NUL) { + return 0; + } + + // Find the first character that is not 10xx.xxxx + for (i = 0; p - i > base; i--) { + if ((p[i] & 0xc0) != 0x80) { + break; + } + } + + // Find the last character that is 10xx.xxxx + for (j = 0; (p[j + 1] & 0xc0) == 0x80; j++) {} + + // Check for illegal sequence. + if (utf8len_tab[p[i]] == 1) { + return 0; + } + return i; +} + /* * Find the next illegal byte sequence. */ @@ -1915,8 +1945,8 @@ void utf_find_illegal(void) } while (*p != NUL) { - /* Illegal means that there are not enough trail bytes (checked by - * utf_ptr2len()) or too many of them (overlong sequence). */ + // Illegal means that there are not enough trail bytes (checked by + // utf_ptr2len()) or too many of them (overlong sequence). len = utf_ptr2len(p); if (*p >= 0x80 && (len == 1 || utf_char2len(utf_ptr2char(p)) != len)) { @@ -2021,7 +2051,7 @@ int mb_charlen(char_u *str) } for (count = 0; *p != NUL; count++) { - p += (*mb_ptr2len)(p); + p += utfc_ptr2len(p); } return count; @@ -2036,7 +2066,7 @@ int mb_charlen_len(char_u *str, int len) int count; for (count = 0; *p != NUL && p < str + len; count++) { - p += (*mb_ptr2len)(p); + p += utfc_ptr2len(p); } return count; @@ -2398,8 +2428,6 @@ static char_u *iconv_string(const vimconv_T *const vcp, char_u *str, size_t slen #endif // HAVE_ICONV - - /* * Setup "vcp" for conversion from "from" to "to". * The names must have been made canonical with enc_canonize(). diff --git a/src/nvim/mbyte.h b/src/nvim/mbyte.h index 9926f27411..1e5e332ad9 100644 --- a/src/nvim/mbyte.h +++ b/src/nvim/mbyte.h @@ -38,11 +38,6 @@ #define ENC_LATIN9 0x400 // Latin9 #define ENC_MACROMAN 0x800 // Mac Roman (not Macro Man! :-) -// TODO(bfredl): eventually we should keep only one of the namings -#define mb_ptr2len utfc_ptr2len -#define mb_char2len utf_char2len -#define mb_char2cells utf_char2cells - /// Flags for vimconv_T typedef enum { CONV_NONE = 0, diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c index 438340e0c4..2a0ea9a269 100644 --- a/src/nvim/memfile.c +++ b/src/nvim/memfile.c @@ -168,7 +168,7 @@ void mf_close(memfile_T *mfp, bool del_file) return; } if (mfp->mf_fd >= 0 && close(mfp->mf_fd) < 0) { - EMSG(_(e_swapclose)); + emsg(_(e_swapclose)); } if (del_file && mfp->mf_fname != NULL) { os_remove((char *)mfp->mf_fname); @@ -206,7 +206,7 @@ void mf_close_file(buf_T *buf, bool getlines) } if (close(mfp->mf_fd) < 0) { // close the file - EMSG(_(e_swapclose)); + emsg(_(e_swapclose)); } mfp->mf_fd = -1; @@ -325,7 +325,7 @@ void mf_put(memfile_T *mfp, bhdr_T *hp, bool dirty, bool infile) unsigned flags = hp->bh_flags; if ((flags & BH_LOCKED) == 0) { - IEMSG(_("E293: block was not locked")); + iemsg(_("E293: block was not locked")); } flags &= ~BH_LOCKED; if (dirty) { @@ -648,7 +648,7 @@ static int mf_write(memfile_T *mfp, bhdr_T *hp) /// write or when hitting a key. We keep on trying, in case some /// space becomes available. if (!did_swapwrite_msg) { - EMSG(_("E297: Write error in swap file")); + emsg(_("E297: Write error in swap file")); } did_swapwrite_msg = true; return FAIL; @@ -792,7 +792,7 @@ static bool mf_do_open(memfile_T *mfp, char_u *fname, int flags) if ((flags & O_CREAT) && os_fileinfo_link((char *)mfp->mf_fname, &file_info)) { mfp->mf_fd = -1; - EMSG(_("E300: Swap file already exists (symlink attack?)")); + emsg(_("E300: Swap file already exists (symlink attack?)")); } else { // try to open the file mfp->mf_fd = mch_open_rw((char *)mfp->mf_fname, flags | O_NOFOLLOW); diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 29e4a03d51..456b1013c1 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -2,7 +2,7 @@ // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com // for debugging -// #define CHECK(c, s) do { if (c) EMSG(s); } while (0) +// #define CHECK(c, s) do { if (c) emsg(s); } while (0) #define CHECK(c, s) do { } while (0) /* @@ -106,8 +106,8 @@ struct pointer_block { uint16_t pb_id; // ID for pointer block: PTR_ID uint16_t pb_count; // number of pointers in this block uint16_t pb_count_max; // maximum value for pb_count - PTR_EN pb_pointer[1]; /* list of pointers to blocks (actually longer) - * followed by empty space until end of page */ + PTR_EN pb_pointer[1]; // list of pointers to blocks (actually longer) + // followed by empty space until end of page }; /* @@ -235,7 +235,7 @@ static linenr_T lowest_marked = 0; // argument for ml_upd_block0() typedef enum { UB_FNAME = 0, // update timestamp and filename - UB_SAME_DIR // update the B0_SAME_DIR flag + UB_SAME_DIR, // update the B0_SAME_DIR flag } upd_block0_T; #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -296,7 +296,7 @@ int ml_open(buf_T *buf) */ hp = mf_new(mfp, false, 1); if (hp->bh_bnum != 0) { - IEMSG(_("E298: Didn't get block nr 0?")); + iemsg(_("E298: Didn't get block nr 0?")); goto error; } b0p = hp->bh_data; @@ -340,7 +340,7 @@ int ml_open(buf_T *buf) goto error; } if (hp->bh_bnum != 1) { - IEMSG(_("E298: Didn't get block nr 1?")); + iemsg(_("E298: Didn't get block nr 1?")); goto error; } pp = hp->bh_data; @@ -356,7 +356,7 @@ int ml_open(buf_T *buf) */ hp = ml_new_data(mfp, false, 1); if (hp->bh_bnum != 2) { - IEMSG(_("E298: Didn't get block nr 2?")); + iemsg(_("E298: Didn't get block nr 2?")); goto error; } @@ -448,13 +448,13 @@ void ml_setname(buf_T *buf) mfp->mf_fd = os_open((char *)mfp->mf_fname, O_RDWR, 0); if (mfp->mf_fd < 0) { // could not (re)open the swap file, what can we do???? - EMSG(_("E301: Oops, lost the swap file!!!")); + emsg(_("E301: Oops, lost the swap file!!!")); return; } (void)os_set_cloexec(mfp->mf_fd); } if (!success) { - EMSG(_("E302: Could not rename swap file")); + emsg(_("E302: Could not rename swap file")); } } @@ -538,7 +538,7 @@ void ml_open_file(buf_T *buf) if (*p_dir != NUL && mfp->mf_fname == NULL) { need_wait_return = true; // call wait_return later no_wait_return++; - (void)EMSG2(_("E303: Unable to open swap file for \"%s\", recovery impossible"), + (void)semsg(_("E303: Unable to open swap file for \"%s\", recovery impossible"), buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname); --no_wait_return; } @@ -654,7 +654,7 @@ static void ml_upd_block0(buf_T *buf, upd_block0_T what) } b0p = hp->bh_data; if (ml_check_b0_id(b0p) == FAIL) { - IEMSG(_("E304: ml_upd_block0(): Didn't get block 0??")); + iemsg(_("E304: ml_upd_block0(): Didn't get block 0??")); } else { if (what == UB_FNAME) { set_b0_fname(b0p, buf); @@ -814,7 +814,7 @@ void ml_recover(bool checkext) // count the number of matching swap files len = recover_names(fname, FALSE, 0, NULL); if (len == 0) { // no swap files found - EMSG2(_("E305: No swap file found for %s"), fname); + semsg(_("E305: No swap file found for %s"), fname); goto theend; } if (len == 1) { // one swap file found, use it @@ -823,7 +823,7 @@ void ml_recover(bool checkext) // list the names of the swap files (void)recover_names(fname, TRUE, 0, NULL); msg_putchar('\n'); - MSG_PUTS(_("Enter number of swap file to use (0 to quit): ")); + msg_puts(_("Enter number of swap file to use (0 to quit): ")); i = get_number(FALSE, NULL); if (i < 1 || i > len) { goto theend; @@ -865,7 +865,7 @@ void ml_recover(bool checkext) mfp = mf_open(fname_used, O_RDONLY); fname_used = p; if (mfp == NULL || mfp->mf_fd < 0) { - EMSG2(_("E306: Cannot open %s"), fname_used); + semsg(_("E306: Cannot open %s"), fname_used); goto theend; } buf->b_ml.ml_mfp = mfp; @@ -883,9 +883,9 @@ void ml_recover(bool checkext) */ if ((hp = mf_get(mfp, 0, 1)) == NULL) { msg_start(); - MSG_PUTS_ATTR(_("Unable to read block 0 from "), attr | MSG_HIST); + msg_puts_attr(_("Unable to read block 0 from "), attr | MSG_HIST); msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST); - MSG_PUTS_ATTR(_("\nMaybe no changes were made or Vim did not update the swap file."), + msg_puts_attr(_("\nMaybe no changes were made or Vim did not update the swap file."), attr | MSG_HIST); msg_end(); goto theend; @@ -894,26 +894,26 @@ void ml_recover(bool checkext) if (STRNCMP(b0p->b0_version, "VIM 3.0", 7) == 0) { msg_start(); msg_outtrans_attr(mfp->mf_fname, MSG_HIST); - MSG_PUTS_ATTR(_(" cannot be used with this version of Vim.\n"), + msg_puts_attr(_(" cannot be used with this version of Vim.\n"), MSG_HIST); - MSG_PUTS_ATTR(_("Use Vim version 3.0.\n"), MSG_HIST); + msg_puts_attr(_("Use Vim version 3.0.\n"), MSG_HIST); msg_end(); goto theend; } if (ml_check_b0_id(b0p) == FAIL) { - EMSG2(_("E307: %s does not look like a Vim swap file"), mfp->mf_fname); + semsg(_("E307: %s does not look like a Vim swap file"), mfp->mf_fname); goto theend; } if (b0_magic_wrong(b0p)) { msg_start(); msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST); - MSG_PUTS_ATTR(_(" cannot be used on this computer.\n"), + msg_puts_attr(_(" cannot be used on this computer.\n"), attr | MSG_HIST); - MSG_PUTS_ATTR(_("The file was created on "), attr | MSG_HIST); + msg_puts_attr(_("The file was created on "), attr | MSG_HIST); // avoid going past the end of a corrupted hostname b0p->b0_fname[0] = NUL; - MSG_PUTS_ATTR(b0p->b0_hname, attr | MSG_HIST); - MSG_PUTS_ATTR(_(",\nor the file has been damaged."), attr | MSG_HIST); + msg_puts_attr((char *)b0p->b0_hname, attr | MSG_HIST); + msg_puts_attr(_(",\nor the file has been damaged."), attr | MSG_HIST); msg_end(); goto theend; } @@ -929,7 +929,7 @@ void ml_recover(bool checkext) if (mfp->mf_page_size < previous_page_size) { msg_start(); msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST); - MSG_PUTS_ATTR(_(" has been damaged (page size is smaller than minimum value).\n"), + msg_puts_attr(_(" has been damaged (page size is smaller than minimum value).\n"), attr | MSG_HIST); msg_end(); goto theend; @@ -982,7 +982,7 @@ void ml_recover(bool checkext) && org_file_info.stat.st_mtim.tv_sec > swp_file_info.stat.st_mtim.tv_sec) || org_file_info.stat.st_mtim.tv_sec != mtime)) { - EMSG(_("E308: Warning: Original file may have been changed")); + emsg(_("E308: Warning: Original file may have been changed")); } ui_flush(); @@ -1052,7 +1052,7 @@ void ml_recover(bool checkext) */ if ((hp = mf_get(mfp, bnum, page_count)) == NULL) { if (bnum == 1) { - EMSG2(_("E309: Unable to read block 1 from %s"), mfp->mf_fname); + semsg(_("E309: Unable to read block 1 from %s"), mfp->mf_fname); goto theend; } ++error; @@ -1121,7 +1121,7 @@ void ml_recover(bool checkext) dp = hp->bh_data; if (dp->db_id != DATA_ID) { // block id wrong if (bnum == 1) { - EMSG2(_("E310: Block 1 ID wrong (%s not a .swp file?)"), + semsg(_("E310: Block 1 ID wrong (%s not a .swp file?)"), mfp->mf_fname); goto theend; } @@ -1232,23 +1232,23 @@ void ml_recover(bool checkext) recoverymode = FALSE; if (got_int) { - EMSG(_("E311: Recovery Interrupted")); + emsg(_("E311: Recovery Interrupted")); } else if (error) { ++no_wait_return; - MSG(">>>>>>>>>>>>>"); - EMSG(_( "E312: Errors detected while recovering; look for lines starting with ???")); + msg(">>>>>>>>>>>>>"); + emsg(_( "E312: Errors detected while recovering; look for lines starting with ???")); --no_wait_return; - MSG(_("See \":help E312\" for more information.")); - MSG(">>>>>>>>>>>>>"); + msg(_("See \":help E312\" for more information.")); + msg(">>>>>>>>>>>>>"); } else { if (curbuf->b_changed) { - MSG(_("Recovery completed. You should check if everything is OK.")); - MSG_PUTS(_("\n(You might want to write out this file under another name\n")); - MSG_PUTS(_("and run diff with the original file to check for changes)")); + msg(_("Recovery completed. You should check if everything is OK.")); + msg_puts(_("\n(You might want to write out this file under another name\n")); + msg_puts(_("and run diff with the original file to check for changes)")); } else { - MSG(_("Recovery completed. Buffer contents equals file contents.")); + msg(_("Recovery completed. Buffer contents equals file contents.")); } - MSG_PUTS(_("\nYou may want to delete the .swp file now.\n\n")); + msg_puts(_("\nYou may want to delete the .swp file now.\n\n")); cmdline_row = msg_row; } redraw_curbuf_later(NOT_VALID); @@ -1316,7 +1316,7 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out) if (list) { // use msg() to start the scrolling properly - msg((char_u *)_("Swap files found:")); + msg(_("Swap files found:")); msg_putchar('\n'); } @@ -1333,8 +1333,8 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out) if (dir_name[0] == '.' && dir_name[1] == NUL) { // check current dir if (fname == NULL) { names[0] = vim_strsave((char_u *)"*.sw?"); - /* For Unix names starting with a dot are special. MS-Windows - * supports this too, on some file systems. */ + // For Unix names starting with a dot are special. MS-Windows + // supports this too, on some file systems. names[1] = vim_strsave((char_u *)".*.sw?"); names[2] = vim_strsave((char_u *)".sw?"); num_names = 3; @@ -1343,11 +1343,11 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out) } } else { // check directory dir_name if (fname == NULL) { - names[0] = (char_u *)concat_fnames((char *)dir_name, "*.sw?", TRUE); - /* For Unix names starting with a dot are special. MS-Windows - * supports this too, on some file systems. */ - names[1] = (char_u *)concat_fnames((char *)dir_name, ".*.sw?", TRUE); - names[2] = (char_u *)concat_fnames((char *)dir_name, ".sw?", TRUE); + names[0] = (char_u *)concat_fnames((char *)dir_name, "*.sw?", true); + // For Unix names starting with a dot are special. MS-Windows + // supports this too, on some file systems. + names[1] = (char_u *)concat_fnames((char *)dir_name, ".*.sw?", true); + names[2] = (char_u *)concat_fnames((char *)dir_name, ".sw?", true); num_names = 3; } else { int len = (int)STRLEN(dir_name); @@ -1424,14 +1424,14 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out) } else if (list) { if (dir_name[0] == '.' && dir_name[1] == NUL) { if (fname == NULL) { - MSG_PUTS(_(" In current directory:\n")); + msg_puts(_(" In current directory:\n")); } else { - MSG_PUTS(_(" Using specified name:\n")); + msg_puts(_(" Using specified name:\n")); } } else { - MSG_PUTS(_(" In directory ")); + msg_puts(_(" In directory ")); msg_home_replace(dir_name); - MSG_PUTS(":\n"); + msg_puts(":\n"); } if (num_files) { @@ -1444,7 +1444,7 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out) (void)swapfile_info(files[i]); } } else { - MSG_PUTS(_(" -- none --\n")); + msg_puts(_(" -- none --\n")); } ui_flush(); } else { @@ -1542,15 +1542,15 @@ static time_t swapfile_info(char_u *fname) #ifdef UNIX // print name of owner of the file if (os_get_uname(file_info.stat.st_uid, uname, B0_UNAME_SIZE) == OK) { - MSG_PUTS(_(" owned by: ")); + msg_puts(_(" owned by: ")); msg_outtrans((char_u *)uname); - MSG_PUTS(_(" dated: ")); + msg_puts(_(" dated: ")); } else #endif - MSG_PUTS(_(" dated: ")); + msg_puts(_(" dated: ")); x = file_info.stat.st_mtim.tv_sec; char ctime_buf[50]; - MSG_PUTS(os_ctime_r(&x, ctime_buf, sizeof(ctime_buf))); + msg_puts(os_ctime_r(&x, ctime_buf, sizeof(ctime_buf))); } /* @@ -1560,55 +1560,55 @@ static time_t swapfile_info(char_u *fname) if (fd >= 0) { if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) { if (STRNCMP(b0.b0_version, "VIM 3.0", 7) == 0) { - MSG_PUTS(_(" [from Vim version 3.0]")); + msg_puts(_(" [from Vim version 3.0]")); } else if (ml_check_b0_id(&b0) == FAIL) { - MSG_PUTS(_(" [does not look like a Vim swap file]")); + msg_puts(_(" [does not look like a Vim swap file]")); } else if (!ml_check_b0_strings(&b0)) { - MSG_PUTS(_(" [garbled strings (not nul terminated)]")); + msg_puts(_(" [garbled strings (not nul terminated)]")); } else { - MSG_PUTS(_(" file name: ")); + msg_puts(_(" file name: ")); if (b0.b0_fname[0] == NUL) { - MSG_PUTS(_("[No Name]")); + msg_puts(_("[No Name]")); } else { msg_outtrans(b0.b0_fname); } - MSG_PUTS(_("\n modified: ")); - MSG_PUTS(b0.b0_dirty ? _("YES") : _("no")); + msg_puts(_("\n modified: ")); + msg_puts(b0.b0_dirty ? _("YES") : _("no")); if (*(b0.b0_uname) != NUL) { - MSG_PUTS(_("\n user name: ")); + msg_puts(_("\n user name: ")); msg_outtrans(b0.b0_uname); } if (*(b0.b0_hname) != NUL) { if (*(b0.b0_uname) != NUL) { - MSG_PUTS(_(" host name: ")); + msg_puts(_(" host name: ")); } else { - MSG_PUTS(_("\n host name: ")); + msg_puts(_("\n host name: ")); } msg_outtrans(b0.b0_hname); } if (char_to_long(b0.b0_pid) != 0L) { - MSG_PUTS(_("\n process ID: ")); + msg_puts(_("\n process ID: ")); msg_outnum(char_to_long(b0.b0_pid)); if (os_proc_running((int)char_to_long(b0.b0_pid))) { - MSG_PUTS(_(" (STILL RUNNING)")); + msg_puts(_(" (STILL RUNNING)")); process_still_running = true; } } if (b0_magic_wrong(&b0)) { - MSG_PUTS(_("\n [not usable on this computer]")); + msg_puts(_("\n [not usable on this computer]")); } } } else { - MSG_PUTS(_(" [cannot be read]")); + msg_puts(_(" [cannot be read]")); } close(fd); } else { - MSG_PUTS(_(" [cannot be opened]")); + msg_puts(_(" [cannot be opened]")); } msg_putchar('\n'); @@ -1638,7 +1638,7 @@ static time_t swapfile_unchanged(char *fname) } // the ID and magic number must be correct - if (ml_check_b0_id(&b0) == FAIL|| b0_magic_wrong(&b0)) { + if (ml_check_b0_id(&b0) == FAIL || b0_magic_wrong(&b0)) { ret = false; } @@ -1756,7 +1756,7 @@ void ml_preserve(buf_T *buf, int message, bool do_fsync) if (mfp == NULL || mfp->mf_fname == NULL) { if (message) { - EMSG(_("E313: Cannot preserve, there is no swap file")); + emsg(_("E313: Cannot preserve, there is no swap file")); } return; } @@ -1807,9 +1807,9 @@ theend: if (message) { if (status == OK) { - MSG(_("File preserved")); + msg(_("File preserved")); } else { - EMSG(_("E314: Preserve failed")); + emsg(_("E314: Preserve failed")); } } } @@ -1857,7 +1857,7 @@ char_u *ml_get_buf(buf_T *buf, linenr_T lnum, bool will_change) // Avoid giving this message for a recursive call, may happen when // the GUI redraws part of the text. recursive++; - IEMSGN(_("E315: ml_get: invalid lnum: %" PRId64), lnum); + siemsg(_("E315: ml_get: invalid lnum: %" PRId64), (int64_t)lnum); recursive--; } errorret: @@ -1893,8 +1893,8 @@ errorret: recursive++; get_trans_bufname(buf); shorten_dir(NameBuff); - iemsgf(_("E316: ml_get: cannot find line %" PRId64 " in buffer %d %s"), - lnum, buf->b_fnum, NameBuff); + siemsg(_("E316: ml_get: cannot find line %" PRId64 " in buffer %d %s"), + (int64_t)lnum, buf->b_fnum, NameBuff); recursive--; } goto errorret; @@ -2295,7 +2295,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b } pp = hp->bh_data; // must be pointer block if (pp->pb_id != PTR_ID) { - IEMSG(_("E317: pointer block id wrong 3")); + iemsg(_("E317: pointer block id wrong 3")); mf_put(mfp, hp, false, false); return FAIL; } @@ -2437,7 +2437,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b * Safety check: fallen out of for loop? */ if (stack_idx < 0) { - IEMSG(_("E318: Updated too many blocks?")); + iemsg(_("E318: Updated too many blocks?")); buf->b_ml.ml_stack_top = 0; // invalidate stack } } @@ -2563,8 +2563,7 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message) * If the file becomes empty the last line is replaced by an empty line. */ if (buf->b_ml.ml_line_count == 1) { // file becomes empty - if (message - ) { + if (message) { set_keep_msg((char_u *)_(no_lines_msg), 0); } @@ -2630,7 +2629,7 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message) } pp = hp->bh_data; // must be pointer block if (pp->pb_id != PTR_ID) { - IEMSG(_("E317: pointer block id wrong 4")); + iemsg(_("E317: pointer block id wrong 4")); mf_put(mfp, hp, false, false); return FAIL; } @@ -2846,7 +2845,7 @@ static void ml_flush_line(buf_T *buf) hp = ml_find_line(buf, lnum, ML_FIND); if (hp == NULL) { - IEMSGN(_("E320: Cannot find line %" PRId64), lnum); + siemsg(_("E320: Cannot find line %" PRId64), (int64_t)lnum); } else { dp = hp->bh_data; idx = lnum - buf->b_ml.ml_locked_low; @@ -3061,7 +3060,7 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action) pp = (PTR_BL *)(dp); // must be pointer block if (pp->pb_id != PTR_ID) { - IEMSG(_("E317: pointer block id wrong")); + iemsg(_("E317: pointer block id wrong")); goto error_block; } @@ -3100,10 +3099,10 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action) } if (idx >= (int)pp->pb_count) { // past the end: something wrong! if (lnum > buf->b_ml.ml_line_count) { - IEMSGN(_("E322: line number out of range: %" PRId64 " past the end"), - lnum - buf->b_ml.ml_line_count); + siemsg(_("E322: line number out of range: %" PRId64 " past the end"), + (int64_t)lnum - buf->b_ml.ml_line_count); } else { - IEMSGN(_("E323: line count wrong in block %" PRId64), bnum); + siemsg(_("E323: line count wrong in block %" PRId64), bnum); } goto error_block; } @@ -3182,7 +3181,7 @@ static void ml_lineadd(buf_T *buf, int count) pp = hp->bh_data; // must be pointer block if (pp->pb_id != PTR_ID) { mf_put(mfp, hp, false, false); - IEMSG(_("E317: pointer block id wrong 2")); + iemsg(_("E317: pointer block id wrong 2")); break; } pp->pb_pointer[ip->ip_index].pe_line_count += count; @@ -3215,7 +3214,7 @@ int resolve_symlink(const char_u *fname, char_u *buf) for (;; ) { // Limit symlink depth to 100, catch recursive loops. if (++depth == 100) { - EMSG2(_("E773: Symlink loop for \"%s\""), fname); + semsg(_("E773: Symlink loop for \"%s\""), fname); return FAIL; } @@ -3357,39 +3356,39 @@ static void attention_message(buf_T *buf, char_u *fname) assert(buf->b_fname != NULL); ++no_wait_return; - (void)EMSG(_("E325: ATTENTION")); - MSG_PUTS(_("\nFound a swap file by the name \"")); + (void)emsg(_("E325: ATTENTION")); + msg_puts(_("\nFound a swap file by the name \"")); msg_home_replace(fname); - MSG_PUTS("\"\n"); + msg_puts("\"\n"); const time_t swap_mtime = swapfile_info(fname); - MSG_PUTS(_("While opening file \"")); + msg_puts(_("While opening file \"")); msg_outtrans(buf->b_fname); - MSG_PUTS("\"\n"); + msg_puts("\"\n"); FileInfo file_info; if (!os_fileinfo((char *)buf->b_fname, &file_info)) { - MSG_PUTS(_(" CANNOT BE FOUND")); + msg_puts(_(" CANNOT BE FOUND")); } else { - MSG_PUTS(_(" dated: ")); + msg_puts(_(" dated: ")); time_t x = file_info.stat.st_mtim.tv_sec; char ctime_buf[50]; - MSG_PUTS(os_ctime_r(&x, ctime_buf, sizeof(ctime_buf))); + msg_puts(os_ctime_r(&x, ctime_buf, sizeof(ctime_buf))); if (swap_mtime != 0 && x > swap_mtime) { - MSG_PUTS(_(" NEWER than swap file!\n")); + msg_puts(_(" NEWER than swap file!\n")); } } - /* Some of these messages are long to allow translation to - * other languages. */ - MSG_PUTS(_("\n(1) Another program may be editing the same file. If this is" + // Some of these messages are long to allow translation to + // other languages. + msg_puts(_("\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." " Quit, or continue with caution.\n")); - MSG_PUTS(_("(2) An edit session for this file crashed.\n")); - MSG_PUTS(_(" If this is the case, use \":recover\" or \"vim -r ")); + msg_puts(_("(2) An edit session for this file crashed.\n")); + msg_puts(_(" If this is the case, use \":recover\" or \"vim -r ")); msg_outtrans(buf->b_fname); - MSG_PUTS(_("\"\n to recover the changes (see \":help recovery\").\n")); - MSG_PUTS(_(" If you did this already, delete the swap file \"")); + msg_puts(_("\"\n to recover the changes (see \":help recovery\").\n")); + msg_puts(_(" If you did this already, delete the swap file \"")); msg_outtrans(fname); - MSG_PUTS(_("\"\n to avoid this message.\n")); + msg_puts(_("\"\n to avoid this message.\n")); cmdline_row = msg_row; --no_wait_return; } @@ -3551,7 +3550,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ } // give the ATTENTION message when there is an old swap file - // for the current file, and the buffer was not recovered. */ + // for the current file, and the buffer was not recovered. if (differ == false && !(curbuf->b_flags & BF_RECOVERED) && vim_strchr(p_shm, SHM_ATTENTION) == NULL) { int choice = 0; @@ -3648,7 +3647,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ break; } } else { - MSG_PUTS("\n"); + msg_puts("\n"); if (msg_silent == 0) { // call wait_return() later need_wait_return = true; @@ -3666,7 +3665,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ */ if (fname[n - 1] == 'a') { // ".s?a" if (fname[n - 2] == 'a') { // ".saa": tried enough, give up - EMSG(_("E326: Too many swap files found")); + emsg(_("E326: Too many swap files found")); XFREE_CLEAR(fname); break; } @@ -3682,7 +3681,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ int ret; char *failed_dir; if ((ret = os_mkdir_recurse(dir_name, 0755, &failed_dir)) != 0) { - EMSG3(_("E303: Unable to create directory \"%s\" for swap file, " + semsg(_("E303: Unable to create directory \"%s\" for swap file, " "recovery impossible: %s"), failed_dir, os_strerror(ret)); xfree(failed_dir); diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 5e6c6a8189..547a9015b7 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -8,7 +8,7 @@ #include <stdbool.h> #include <string.h> -#include "nvim/api/vim.h" +#include "nvim/api/extmark.h" #include "nvim/context.h" #include "nvim/decoration.h" #include "nvim/eval.h" @@ -510,7 +510,7 @@ void do_outofmem_msg(size_t size) * message fails, e.g. when setting v:errmsg. */ did_outofmem_msg = true; - EMSGU(_("E342: Out of memory! (allocating %" PRIu64 " bytes)"), size); + semsg(_("E342: Out of memory! (allocating %" PRIu64 " bytes)"), (uint64_t)size); } } @@ -679,7 +679,7 @@ void free_all_mem(void) } eval_clear(); - api_vim_free_all_mem(); + api_extmark_free_all_mem(); ctx_free_all(); // Free all buffers. Reset 'autochdir' to avoid accessing things that diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 2250002f86..c2b6a5e402 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -38,8 +38,6 @@ #endif - - /// The character for each menu mode static char_u menu_mode_chars[] = { 'n', 'v', 's', 'o', 'i', 'c', 't' }; @@ -168,7 +166,7 @@ void ex_menu(exarg_T *eap) menu_path = (char *)arg; if (*menu_path == '.') { - EMSG2(_(e_invarg2), menu_path); + semsg(_(e_invarg2), menu_path); goto theend; } @@ -181,7 +179,7 @@ void ex_menu(exarg_T *eap) show_menus((char_u *)menu_path, modes); goto theend; } else if (*map_to != NUL && (unmenu || enable != kNone)) { - EMSG(_(e_trailing)); + emsg(_(e_trailing)); goto theend; } @@ -305,8 +303,8 @@ static int add_menu_path(const char_u *const menu_path, vimmenu_T *menuarg, parent = NULL; name = path_name; while (*name) { - /* Get name of this element in the menu hierarchy, and the simplified - * name (without mnemonic and accelerator text). */ + // Get name of this element in the menu hierarchy, and the simplified + // name (without mnemonic and accelerator text). next_name = menu_name_skip(name); map_to = menutrans_lookup(name, (int)STRLEN(name)); if (map_to != NULL) { @@ -318,7 +316,7 @@ static int add_menu_path(const char_u *const menu_path, vimmenu_T *menuarg, dname = menu_text(name, NULL, NULL); if (*dname == NUL) { // Only a mnemonic or accelerator is not valid. - EMSG(_("E792: Empty menu name")); + emsg(_("E792: Empty menu name")); goto erret; } @@ -329,13 +327,13 @@ static int add_menu_path(const char_u *const menu_path, vimmenu_T *menuarg, if (menu_name_equal(name, menu) || menu_name_equal(dname, menu)) { if (*next_name == NUL && menu->children != NULL) { if (!sys_menu) { - EMSG(_("E330: Menu path must not lead to a sub-menu")); + emsg(_("E330: Menu path must not lead to a sub-menu")); } goto erret; } if (*next_name != NUL && menu->children == NULL) { if (!sys_menu) { - EMSG(_(e_notsubmenu)); + emsg(_(e_notsubmenu)); } goto erret; } @@ -355,12 +353,12 @@ static int add_menu_path(const char_u *const menu_path, vimmenu_T *menuarg, if (menu == NULL) { if (*next_name == NUL && parent == NULL) { - EMSG(_("E331: Must not add menu items directly to menu bar")); + emsg(_("E331: Must not add menu items directly to menu bar")); goto erret; } if (menu_is_separator(dname) && *next_name != NUL) { - EMSG(_("E332: Separator cannot be part of a menu path")); + emsg(_("E332: Separator cannot be part of a menu path")); goto erret; } @@ -481,8 +479,8 @@ erret: xfree(path_name); xfree(dname); - /* Delete any empty submenu we added before discovering the error. Repeat - * for higher levels. */ + // Delete any empty submenu we added before discovering the error. Repeat + // for higher levels. while (parent != NULL && parent->children == NULL) { if (parent->parent == NULL) { menup = root_menu_ptr; @@ -519,7 +517,7 @@ static int menu_enable_recurse(vimmenu_T *menu, char_u *name, int modes, int ena if (*name == NUL || *name == '*' || menu_name_equal(name, menu)) { if (*p != NUL) { if (menu->children == NULL) { - EMSG(_(e_notsubmenu)); + emsg(_(e_notsubmenu)); return FAIL; } if (menu_enable_recurse(menu->children, p, modes, enable) == FAIL) { @@ -543,7 +541,7 @@ static int menu_enable_recurse(vimmenu_T *menu, char_u *name, int modes, int ena menu = menu->next; } if (*name != NUL && *name != '*' && menu == NULL) { - EMSG2(_(e_nomenu), name); + semsg(_(e_nomenu), name); return FAIL; } @@ -572,7 +570,7 @@ static int remove_menu(vimmenu_T **menup, char_u *name, int modes, bool silent) if (*name == NUL || menu_name_equal(name, menu)) { if (*p != NUL && menu->children == NULL) { if (!silent) { - EMSG(_(e_notsubmenu)); + emsg(_(e_notsubmenu)); } return FAIL; } @@ -582,7 +580,7 @@ static int remove_menu(vimmenu_T **menup, char_u *name, int modes, bool silent) } } else if (*name != NUL) { if (!silent) { - EMSG(_(e_othermode)); + emsg(_(e_othermode)); } return FAIL; } @@ -614,7 +612,7 @@ static int remove_menu(vimmenu_T **menup, char_u *name, int modes, bool silent) if (*name != NUL) { if (menu == NULL) { if (!silent) { - EMSG2(_(e_nomenu), name); + semsg(_(e_nomenu), name); } return FAIL; } @@ -650,8 +648,8 @@ static void free_menu(vimmenu_T **menup) menu = *menup; - /* Don't change *menup until after calling gui_mch_destroy_menu(). The - * MacOS code needs the original structure to properly delete the menu. */ + // Don't change *menup until after calling gui_mch_destroy_menu(). The + // MacOS code needs the original structure to properly delete the menu. *menup = menu->next; xfree(menu->name); xfree(menu->dname); @@ -797,10 +795,10 @@ static vimmenu_T *find_menu(vimmenu_T *menu, char_u *name, int modes) if (menu_name_equal(name, menu)) { // Found menu if (*p != NUL && menu->children == NULL) { - EMSG(_(e_notsubmenu)); + emsg(_(e_notsubmenu)); return NULL; } else if ((menu->modes & modes) == 0x0) { - EMSG(_(e_othermode)); + emsg(_(e_othermode)); return NULL; } else if (*p == NUL) { // found a full match return menu; @@ -811,7 +809,7 @@ static vimmenu_T *find_menu(vimmenu_T *menu, char_u *name, int modes) } if (menu == NULL) { - EMSG2(_(e_nomenu), name); + semsg(_(e_nomenu), name); return NULL; } // Found a match, search the sub-menu. @@ -832,7 +830,7 @@ static int show_menus(char_u *const path_name, int modes) // Now we have found the matching menu, and we list the mappings // Highlight title - MSG_PUTS_TITLE(_("\n--- Menus ---")); + msg_puts_title(_("\n--- Menus ---")); show_menus_recursive(menu->parent, modes, 0); return OK; @@ -854,11 +852,11 @@ static void show_menus_recursive(vimmenu_T *menu, int modes, int depth) return; } for (i = 0; i < depth; i++) { - MSG_PUTS(" "); + msg_puts(" "); } if (menu->priority) { msg_outnum(menu->priority); - MSG_PUTS(" "); + msg_puts(" "); } // Same highlighting as for directories!? msg_outtrans_attr(menu->name, HL_ATTR(HLF_D)); @@ -872,7 +870,7 @@ static void show_menus_recursive(vimmenu_T *menu, int modes, int depth) return; } for (i = 0; i < depth + 2; i++) { - MSG_PUTS(" "); + msg_puts(" "); } msg_putchar(menu_mode_chars[bit]); if (menu->noremap[bit] == REMAP_NONE) { @@ -892,7 +890,7 @@ static void show_menus_recursive(vimmenu_T *menu, int modes, int depth) } else { msg_putchar(' '); } - MSG_PUTS(" "); + msg_puts(" "); if (*menu->strings[bit] == NUL) { msg_puts_attr("<Nop>", HL_ATTR(HLF_8)); } else { @@ -951,7 +949,7 @@ char_u *set_context_in_menu_cmd(expand_T *xp, const char *cmd, char_u *arg, bool if (!ascii_iswhite(*p)) { if (STRNCMP(arg, "enable", 6) == 0 - && (arg[6] == NUL || ascii_iswhite(arg[6]))) { + && (arg[6] == NUL || ascii_iswhite(arg[6]))) { p = arg + 6; } else if (STRNCMP(arg, "disable", 7) == 0 && (arg[7] == NUL || ascii_iswhite(arg[7]))) { @@ -1122,8 +1120,8 @@ char_u *get_menu_names(expand_T *xp, int idx) should_advance = true; } } - /* hack on menu separators: use a 'magic' char for the separator - * so that '.' in names gets escaped properly */ + // hack on menu separators: use a 'magic' char for the separator + // so that '.' in names gets escaped properly STRCAT(tbuffer, "\001"); str = tbuffer; } else { @@ -1404,10 +1402,10 @@ static void execute_menu(const exarg_T *eap, vimmenu_T *menu) mode = "Visual"; idx = MENU_INDEX_VISUAL; - /* GEDDES: This is not perfect - but it is a - * quick way of detecting whether we are doing this from a - * selection - see if the range matches up with the visual - * select start and end. */ + // GEDDES: This is not perfect - but it is a + // quick way of detecting whether we are doing this from a + // selection - see if the range matches up with the visual + // select start and end. if ((curbuf->b_visual.vi_start.lnum == eap->line1) && (curbuf->b_visual.vi_end.lnum) == eap->line2) { // Set it up for visual mode - equivalent to gv. @@ -1434,8 +1432,8 @@ static void execute_menu(const exarg_T *eap, vimmenu_T *menu) check_cursor(); - /* Adjust the cursor to make sure it is in the correct pos - * for exclusive mode */ + // Adjust the cursor to make sure it is in the correct pos + // for exclusive mode if (*p_sel == 'e' && gchar_cursor() != NUL) { curwin->w_cursor.col++; } @@ -1466,7 +1464,7 @@ static void execute_menu(const exarg_T *eap, vimmenu_T *menu) menu->silent[idx]); } } else if (eap != NULL) { - EMSG2(_("E335: Menu not defined for %s mode"), mode); + semsg(_("E335: Menu not defined for %s mode"), mode); } } @@ -1484,10 +1482,10 @@ void ex_emenu(exarg_T *eap) while (menu != NULL) { if (menu_name_equal(name, menu)) { if (*p == NUL && menu->children != NULL) { - EMSG(_("E333: Menu path must lead to a menu item")); + emsg(_("E333: Menu path must lead to a menu item")); menu = NULL; } else if (*p != NUL && menu->children == NULL) { - EMSG(_(e_notsubmenu)); + emsg(_(e_notsubmenu)); menu = NULL; } break; @@ -1502,7 +1500,7 @@ void ex_emenu(exarg_T *eap) } xfree(saved_name); if (menu == NULL) { - EMSG2(_("E334: Menu not found: %s"), eap->arg); + semsg(_("E334: Menu not found: %s"), eap->arg); return; } @@ -1558,7 +1556,7 @@ void ex_menutranslate(exarg_T *eap) *arg = NUL; arg = menu_skip_part(to); if (arg == to) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } else { from = vim_strsave(from); from_noamp = menu_text(from, NULL, NULL); diff --git a/src/nvim/message.c b/src/nvim/message.c index c4aab18c35..7b6337bea2 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -209,7 +209,7 @@ void msg_grid_validate(void) * When terminal not initialized (yet) mch_errmsg(..) is used. * return TRUE if wait_return not called */ -int msg(char_u *s) +int msg(char *s) { return msg_attr_keep(s, 0, false, false); } @@ -218,7 +218,7 @@ int msg(char_u *s) int verb_msg(char *s) { verbose_enter(); - int n = msg_attr_keep((char_u *)s, 0, false, false); + int n = msg_attr_keep(s, 0, false, false); verbose_leave(); return n; @@ -227,7 +227,7 @@ int verb_msg(char *s) int msg_attr(const char *s, const int attr) FUNC_ATTR_NONNULL_ARG(1) { - return msg_attr_keep((char_u *)s, attr, false, false); + return msg_attr_keep(s, attr, false, false); } /// similar to msg_outtrans_attr, but support newlines and tabs. @@ -265,7 +265,7 @@ void msg_multiline_attr(const char *s, int attr, bool check_int, bool *need_clea /// @param keep set keep_msg if it doesn't scroll -bool msg_attr_keep(char_u *s, int attr, bool keep, bool multiline) +bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline) FUNC_ATTR_NONNULL_ALL { static int entered = 0; @@ -281,12 +281,12 @@ bool msg_attr_keep(char_u *s, int attr, bool keep, bool multiline) // Skip messages not match ":filter pattern". // Don't filter when there is an error. - if (!emsg_on_display && message_filtered(s)) { + if (!emsg_on_display && message_filtered((char_u *)s)) { return true; } if (attr == 0) { - set_vim_var_string(VV_STATUSMSG, (char *)s, -1); + set_vim_var_string(VV_STATUSMSG, s, -1); } /* @@ -299,37 +299,37 @@ bool msg_attr_keep(char_u *s, int attr, bool keep, bool multiline) } ++entered; - /* Add message to history (unless it's a repeated kept message or a - * truncated message) */ - if (s != keep_msg + // Add message to history (unless it's a repeated kept message or a + // truncated message) + if ((const char_u *)s != keep_msg || (*s != '<' && last_msg_hist != NULL && last_msg_hist->msg != NULL && STRCMP(s, last_msg_hist->msg))) { - add_msg_hist((const char *)s, -1, attr, multiline); + add_msg_hist(s, -1, attr, multiline); } // Truncate the message if needed. msg_start(); - buf = msg_strtrunc(s, FALSE); + buf = msg_strtrunc((char_u *)s, FALSE); if (buf != NULL) { - s = buf; + s = (const char *)buf; } bool need_clear = true; if (multiline) { - msg_multiline_attr((char *)s, attr, false, &need_clear); + msg_multiline_attr(s, attr, false, &need_clear); } else { - msg_outtrans_attr(s, attr); + msg_outtrans_attr((char_u *)s, attr); } if (need_clear) { msg_clr_eos(); } retval = msg_end(); - if (keep && retval && vim_strsize(s) < (int)(Rows - cmdline_row - 1) + if (keep && retval && vim_strsize((char_u *)s) < (int)(Rows - cmdline_row - 1) * Columns + sc_col) { - set_keep_msg(s, 0); + set_keep_msg((char_u *)s, 0); } xfree(buf); @@ -453,11 +453,11 @@ void trunc_string(char_u *s, char_u *buf, int room_in, int buflen) } /* - * Note: Caller of smgs() and smsg_attr() must check the resulting string is + * Note: Caller of smsg() and smsg_attr() must check the resulting string is * shorter than IOSIZE!!! */ -int smsg(char *s, ...) +int smsg(const char *s, ...) FUNC_ATTR_PRINTF(1, 2) { va_list arglist; @@ -465,10 +465,10 @@ int smsg(char *s, ...) va_start(arglist, s); vim_vsnprintf((char *)IObuff, IOSIZE, s, arglist); va_end(arglist); - return msg(IObuff); + return msg((char *)IObuff); } -int smsg_attr(int attr, char *s, ...) +int smsg_attr(int attr, const char *s, ...) FUNC_ATTR_PRINTF(2, 3) { va_list arglist; @@ -479,7 +479,7 @@ int smsg_attr(int attr, char *s, ...) return msg_attr((const char *)IObuff, attr); } -int smsg_attr_keep(int attr, char *s, ...) +int smsg_attr_keep(int attr, const char *s, ...) FUNC_ATTR_PRINTF(2, 3) { va_list arglist; @@ -487,7 +487,7 @@ int smsg_attr_keep(int attr, char *s, ...) va_start(arglist, s); vim_vsnprintf((char *)IObuff, IOSIZE, s, arglist); va_end(arglist); - return msg_attr_keep(IObuff, attr, true, false); + return msg_attr_keep((const char *)IObuff, attr, true, false); } /* @@ -721,7 +721,7 @@ static bool emsg_multiline(const char *s, bool multiline) // Display the error message itself. msg_nowait = false; // Wait for this msg. - return msg_attr_keep((char_u *)s, attr, false, multiline); + return msg_attr_keep(s, attr, false, multiline); } /// emsg() - display an error message @@ -730,25 +730,25 @@ static bool emsg_multiline(const char *s, bool multiline) /// When terminal not initialized (yet) mch_errmsg(..) is used. /// /// @return true if wait_return not called -bool emsg(const char_u *s) +bool emsg(const char *s) { return emsg_multiline((const char *)s, false); } void emsg_invreg(int name) { - EMSG2(_("E354: Invalid register name: '%s'"), transchar(name)); + semsg(_("E354: Invalid register name: '%s'"), transchar(name)); } /// Print an error message with unknown number of arguments -bool emsgf(const char *const fmt, ...) +bool semsg(const char *const fmt, ...) FUNC_ATTR_PRINTF(1, 2) { bool ret; va_list ap; va_start(ap, fmt); - ret = emsgfv(fmt, ap); + ret = semsgv(fmt, ap); va_end(ap); return ret; @@ -756,7 +756,7 @@ bool emsgf(const char *const fmt, ...) #define MULTILINE_BUFSIZE 8192 -bool emsgf_multiline(const char *const fmt, ...) +bool semsg_multiline(const char *const fmt, ...) { bool ret; va_list ap; @@ -777,7 +777,7 @@ bool emsgf_multiline(const char *const fmt, ...) } /// Print an error message with unknown number of arguments -static bool emsgfv(const char *fmt, va_list ap) +static bool semsgv(const char *fmt, va_list ap) { static char errbuf[IOSIZE]; if (emsg_not_now()) { @@ -786,7 +786,7 @@ static bool emsgfv(const char *fmt, va_list ap) vim_vsnprintf(errbuf, sizeof(errbuf), fmt, ap); - return emsg((const char_u *)errbuf); + return emsg(errbuf); } /// Same as emsg(...), but abort on error when ABORT_ON_INTERNAL_ERROR is @@ -794,20 +794,20 @@ static bool emsgfv(const char *fmt, va_list ap) /// detected when fuzzing vim. void iemsg(const char *s) { - emsg((char_u *)s); + emsg(s); #ifdef ABORT_ON_INTERNAL_ERROR abort(); #endif } -/// Same as emsgf(...) but abort on error when ABORT_ON_INTERNAL_ERROR is +/// Same as semsg(...) but abort on error when ABORT_ON_INTERNAL_ERROR is /// defined. It is used for internal errors only, so that they can be /// detected when fuzzing vim. -void iemsgf(const char *s, ...) +void siemsg(const char *s, ...) { va_list ap; va_start(ap, s); - (void)emsgfv(s, ap); + (void)semsgv(s, ap); va_end(ap); #ifdef ABORT_ON_INTERNAL_ERROR abort(); @@ -817,17 +817,17 @@ void iemsgf(const char *s, ...) /// Give an "Internal error" message. void internal_error(char *where) { - IEMSG2(_(e_intern2), where); + siemsg(_(e_intern2), where); } -static void msg_emsgf_event(void **argv) +static void msg_semsg_event(void **argv) { char *s = argv[0]; - (void)emsg((char_u *)s); + (void)emsg(s); xfree(s); } -void msg_schedule_emsgf(const char *const fmt, ...) +void msg_schedule_semsg(const char *const fmt, ...) FUNC_ATTR_PRINTF(1, 2) { va_list ap; @@ -836,7 +836,7 @@ void msg_schedule_emsgf(const char *const fmt, ...) va_end(ap); char *s = xstrdup((char *)IObuff); - multiqueue_put(main_loop.events, msg_emsgf_event, 1, s); + multiqueue_put(main_loop.events, msg_semsg_event, 1, s); } /* @@ -845,21 +845,21 @@ void msg_schedule_emsgf(const char *const fmt, ...) * Careful: The string may be changed by msg_may_trunc()! * Returns a pointer to the printed message, if wait_return() not called. */ -char_u *msg_trunc_attr(char_u *s, int force, int attr) +char *msg_trunc_attr(char *s, int force, int attr) { int n; // Add message to history before truncating. - add_msg_hist((const char *)s, -1, attr, false); + add_msg_hist(s, -1, attr, false); - s = msg_may_trunc(force, s); + char *ts = (char *)msg_may_trunc(force, (char_u *)s); msg_hist_off = true; - n = msg_attr((const char *)s, attr); + n = msg_attr(ts, attr); msg_hist_off = false; if (n) { - return s; + return ts; } return NULL; } @@ -1009,7 +1009,7 @@ void ex_messages(void *const eap_p) } if (*eap->arg != NUL) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -1050,7 +1050,7 @@ void ex_messages(void *const eap_p) msg_hist_off = true; for (; p != NULL && !got_int; p = p->next) { if (p->msg != NULL) { - msg_attr_keep(p->msg, p->attr, false, p->multiline); + msg_attr_keep((char *)p->msg, p->attr, false, p->multiline); } } msg_hist_off = false; @@ -1072,11 +1072,11 @@ void msg_end_prompt(void) lines_left = -1; } -/// wait for the user to hit a key (normally a return) +/// Wait for the user to hit a key (normally Enter) /// -/// if 'redraw' is true, redraw the entire screen NOT_VALID -/// if 'redraw' is false, do a normal redraw -/// if 'redraw' is -1, don't redraw at all +/// If 'redraw' is true, redraw the entire screen NOT_VALID +/// If 'redraw' is false, do a normal redraw +/// If 'redraw' is -1, don't redraw at all void wait_return(int redraw) { int c; @@ -1089,8 +1089,8 @@ void wait_return(int redraw) redraw_all_later(NOT_VALID); } - /* If using ":silent cmd", don't wait for a return. Also don't set - * need_wait_return to do it later. */ + // If using ":silent cmd", don't wait for a return. Also don't set + // need_wait_return to do it later. if (msg_silent != 0) { return; } @@ -1119,7 +1119,7 @@ void wait_return(int redraw) quit_more = FALSE; got_int = FALSE; } else if (exmode_active) { - MSG_PUTS(" "); // make sure the cursor is on the right line + msg_puts(" "); // make sure the cursor is on the right line c = CAR; // no need for a return in ex mode got_int = FALSE; } else { @@ -1140,8 +1140,8 @@ void wait_return(int redraw) hit_return_msg(); do { - /* Remember "got_int", if it is set vgetc() probably returns a - * CTRL-C, but we need to loop then. */ + // Remember "got_int", if it is set vgetc() probably returns a + // 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 @@ -1199,11 +1199,11 @@ void wait_return(int redraw) } } while ((had_got_int && c == Ctrl_C) || c == K_IGNORE - || c == K_LEFTDRAG || c == K_LEFTRELEASE + || c == K_LEFTDRAG || c == K_LEFTRELEASE || c == K_MIDDLEDRAG || c == K_MIDDLERELEASE - || c == K_RIGHTDRAG || c == K_RIGHTRELEASE - || c == K_MOUSELEFT || c == K_MOUSERIGHT - || c == K_MOUSEDOWN || c == K_MOUSEUP + || c == K_RIGHTDRAG || c == K_RIGHTRELEASE + || c == K_MOUSELEFT || c == K_MOUSERIGHT + || c == K_MOUSEDOWN || c == K_MOUSEUP || c == K_MOUSEMOVE); os_breakcheck(); /* @@ -1213,8 +1213,8 @@ void wait_return(int redraw) || c == K_X1MOUSE || c == K_X2MOUSE) { (void)jump_to_mouse(MOUSE_SETPOS, NULL, 0); } else if (vim_strchr((char_u *)"\r\n ", c) == NULL && c != Ctrl_C) { - /* Put the character back in the typeahead buffer. Don't use the - * stuff buffer, because lmaps wouldn't work. */ + // Put the character back in the typeahead buffer. Don't use the + // stuff buffer, because lmaps wouldn't work. ins_char_typebuf(c); do_redraw = true; // need a redraw even though there is // typeahead @@ -1275,10 +1275,10 @@ static void hit_return_msg(void) } msg_ext_set_kind("return_prompt"); if (got_int) { - MSG_PUTS(_("Interrupt: ")); + msg_puts(_("Interrupt: ")); } - MSG_PUTS_ATTR(_("Press ENTER or type command to continue"), HL_ATTR(HLF_R)); + msg_puts_attr(_("Press ENTER or type command to continue"), HL_ATTR(HLF_R)); if (!msg_use_printf()) { msg_clr_eos(); } @@ -1376,7 +1376,7 @@ void msg_putchar(int c) void msg_putchar_attr(int c, int attr) { - char buf[MB_MAXBYTES + 1]; + char_u buf[MB_MAXBYTES + 1]; if (IS_SPECIAL(c)) { buf[0] = (char)K_SPECIAL; @@ -1384,9 +1384,9 @@ void msg_putchar_attr(int c, int attr) buf[2] = (char)K_THIRD(c); buf[3] = NUL; } else { - buf[utf_char2bytes(c, (char_u *)buf)] = NUL; + buf[utf_char2bytes(c, buf)] = NUL; } - msg_puts_attr(buf, attr); + msg_puts_attr((const char *)buf, attr); } void msg_outnum(long n) @@ -1558,7 +1558,7 @@ void msg_make(char_u *arg) /// the character/string -- webb /// /// @param from true for LHS of a mapping -/// @param maxlen screen columns, 0 for unlimeted +/// @param maxlen screen columns, 0 for unlimited int msg_outtrans_special(const char_u *strstart, bool from, int maxlen) { if (strstart == NULL) { @@ -1569,22 +1569,22 @@ int msg_outtrans_special(const char_u *strstart, bool from, int maxlen) int attr = HL_ATTR(HLF_8); while (*str != NUL) { - const char *string; + const char *text; // Leading and trailing spaces need to be displayed in <> form. if ((str == strstart || str[1] == NUL) && *str == ' ') { - string = "<Space>"; + text = "<Space>"; str++; } else { - string = str2special((const char **)&str, from, false); + text = str2special((const char **)&str, from, false); } - const int len = vim_strsize((char_u *)string); + const int len = vim_strsize((char_u *)text); if (maxlen > 0 && retval + len >= maxlen) { break; } // Highlight special keys - msg_puts_attr(string, (len > 1 - && (*mb_ptr2len)((char_u *)string) <= 1 - ? attr : 0)); + msg_puts_attr(text, (len > 1 + && utfc_ptr2len((char_u *)text) <= 1 + ? attr : 0)); retval += len; } return retval; @@ -1824,8 +1824,8 @@ void msg_prt_line(char_u *s, int list) c_extra = NUL; c_final = NUL; c = *p_extra++; - /* Use special coloring to be able to distinguish <hex> from - * the same in plain text. */ + // Use special coloring to be able to distinguish <hex> from + // the same in plain text. attr = HL_ATTR(HLF_0); } else if (c == ' ') { if (lead != NULL && s <= lead) { @@ -1909,12 +1909,12 @@ void msg_puts_title(const char *s) * part in the middle and replace it with "..." when necessary. * Does not handle multi-byte characters! */ -void msg_puts_long_attr(char_u *longstr, int attr) +void msg_outtrans_long_attr(char_u *longstr, int attr) { - msg_puts_long_len_attr(longstr, (int)STRLEN(longstr), attr); + msg_outtrans_long_len_attr(longstr, (int)STRLEN(longstr), attr); } -void msg_puts_long_len_attr(char_u *longstr, int len, int attr) +void msg_outtrans_long_len_attr(char_u *longstr, int len, int attr) { int slen = len; int room; @@ -2155,8 +2155,8 @@ static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurs } } - /* When we displayed a char in last column need to check if there - * is still more. */ + // When we displayed a char in last column need to check if there + // is still more. if (did_last_char) { continue; } @@ -2408,7 +2408,7 @@ typedef enum { SB_CLEAR_NONE = 0, SB_CLEAR_ALL, SB_CLEAR_CMDLINE_BUSY, - SB_CLEAR_CMDLINE_DONE + SB_CLEAR_CMDLINE_DONE, } sb_clear_T; // When to clear text on next msg. @@ -2506,8 +2506,8 @@ void show_sb_text(void) { msgchunk_T *mp; - /* Only show something if there is more than one line, otherwise it looks - * weird, typing a command without output results in one line. */ + // Only show something if there is more than one line, otherwise it looks + // weird, typing a command without output results in one line. mp = msg_sb_start(last_msgchunk); if (mp == NULL || mp->sb_prev == NULL) { vim_beep(BO_MESS); @@ -2578,8 +2578,8 @@ static void t_puts(int *t_col, const char_u *t_s, const char_u *s, int attr) attr); msg_col += *t_col; *t_col = 0; - /* If the string starts with a composing character don't increment the - * column position for it. */ + // If the string starts with a composing character don't increment the + // column position for it. if (utf_iscomposing(utf_ptr2char(t_s))) { msg_col--; } @@ -2747,8 +2747,8 @@ static int do_more_prompt(int typed_char) case ':': // start new command line if (!confirm_msg_used) { - /* Since got_int is set all typeahead will be flushed, but we - * want to keep this ':', remember that in a special way. */ + // Since got_int is set all typeahead will be flushed, but we + // want to keep this ':', remember that in a special way. typeahead_noflush(':'); cmdline_row = Rows - 1; // put ':' on this line skip_redraw = true; // skip redraw once @@ -2765,8 +2765,8 @@ static int do_more_prompt(int typed_char) got_int = TRUE; quit_more = TRUE; } - /* When there is some more output (wrapping line) display that - * without another prompt. */ + // When there is some more output (wrapping line) display that + // without another prompt. lines_left = Rows - 1; break; @@ -2972,9 +2972,9 @@ void repeat_message(void) ui_cursor_goto(msg_row, msg_col); // put cursor back } else if (State == HITRETURN || State == SETWSIZE) { if (msg_row == Rows - 1) { - /* Avoid drawing the "hit-enter" prompt below the previous one, - * overwrite it. Esp. useful when regaining focus and a - * FocusGained autocmd exists but didn't draw anything. */ + // Avoid drawing the "hit-enter" prompt below the previous one, + // overwrite it. Esp. useful when regaining focus and a + // FocusGained autocmd exists but didn't draw anything. msg_didout = false; msg_col = 0; msg_clr_eos(); @@ -3308,7 +3308,7 @@ int verbose_open(void) verbose_fd = os_fopen((char *)p_vfile, "a"); if (verbose_fd == NULL) { - EMSG2(_(e_notopen), p_vfile); + semsg(_(e_notopen), p_vfile); return FAIL; } } diff --git a/src/nvim/message.h b/src/nvim/message.h index 6d4d030500..316b2df7a4 100644 --- a/src/nvim/message.h +++ b/src/nvim/message.h @@ -30,53 +30,6 @@ #define VIM_ALL 5 #define VIM_DISCARDALL 6 -/// Show plain message -#define MSG(s) msg((char_u *)(s)) - -/// Show message highlighted according to the attr -#define MSG_ATTR(s, attr) msg_attr((const char *)(s), (attr)) - -/// Display error message -/// -/// Sets error flag in process, can be transformed into an exception. -#define EMSG(s) emsg((char_u *)(s)) - -/// Like #EMSG, but for messages with one "%s" inside -#define EMSG2(s, p) emsgf((const char *)(s), (p)) - -/// Like #EMSG, but for messages with two "%s" inside -#define EMSG3(s, p, q) emsgf((const char *)(s), (p), (q)) - -/// Like #EMSG, but for messages with one "%" PRId64 inside -#define EMSGN(s, n) emsgf((const char *)(s), (int64_t)(n)) - -/// Like #EMSG, but for messages with one "%" PRIu64 inside -#define EMSGU(s, n) emsgf((const char *)(s), (uint64_t)(n)) - -/// Like #EMSG, but for internal messages -#define IEMSG(s) iemsg((const char *)(s)) - -/// Like #EMSG2, but for internal messages -#define IEMSG2(s, p) iemsgf((const char *)(s), (p)) - -/// Like #EMSGN, but for internal messages -#define IEMSGN(s, n) iemsgf((const char *)(s), (int64_t)(n)) - -/// Display message at the recorded position -#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((const char *)(s), (a)) - -/// Like #MSG_PUTS, but highlight like title -#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) - -/// Like #MSG_PUTS_ATTR, but if middle part of long messages will be replaced -#define MSG_PUTS_LONG_ATTR(s, a) msg_puts_long_attr((char_u *)(s), (a)) - typedef struct { String text; int attr; diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index 40db5b7cf3..faf0b0f633 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -100,8 +100,8 @@ int get_leader_len(char_u *line, char_u **flags, bool backward, bool include_spa */ found_one = FALSE; for (list = curbuf->b_p_com; *list; ) { - /* Get one option part into part_buf[]. Advance "list" to next - * one. Put "string" at start of string. */ + // Get one option part into part_buf[]. Advance "list" to next + // one. Put "string" at start of string. if (!got_com && flags != NULL) { *flags = list; // remember where flags started } @@ -113,16 +113,16 @@ int get_leader_len(char_u *line, char_u **flags, bool backward, bool include_spa } *string++ = NUL; // isolate flags from string - /* If we found a middle match previously, use that match when this - * is not a middle or end. */ + // If we found a middle match previously, use that match when this + // is not a middle or end. if (middle_match_len != 0 && vim_strchr(part_buf, COM_MIDDLE) == NULL && vim_strchr(part_buf, COM_END) == NULL) { break; } - /* When we already found a nested comment, only accept further - * nested comments. */ + // When we already found a nested comment, only accept further + // nested comments. if (got_com && vim_strchr(part_buf, COM_NEST) == NULL) { continue; } @@ -132,10 +132,10 @@ int get_leader_len(char_u *line, char_u **flags, bool backward, bool include_spa continue; } - /* Line contents and string must match. - * When string starts with white space, must have some white space - * (but the amount does not need to match, there might be a mix of - * TABs and spaces). */ + // Line contents and string must match. + // When string starts with white space, must have some white space + // (but the amount does not need to match, there might be a mix of + // TABs and spaces). if (ascii_iswhite(string[0])) { if (i == 0 || !ascii_iswhite(line[i - 1])) { continue; // missing white space @@ -145,23 +145,22 @@ int get_leader_len(char_u *line, char_u **flags, bool backward, bool include_spa } } for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j) { - ; } if (string[j] != NUL) { continue; // string doesn't match } - /* When 'b' flag used, there must be white space or an - * end-of-line after the string in the line. */ + // When 'b' flag used, there must be white space or an + // end-of-line after the string in the line. if (vim_strchr(part_buf, COM_BLANK) != NULL && !ascii_iswhite(line[i + j]) && line[i + j] != NUL) { continue; } - /* We have found a match, stop searching unless this is a middle - * comment. The middle comment can be a substring of the end - * comment in which case it's better to return the length of the - * end comment and its flags. Thus we keep searching with middle - * and end matches and use an end match if it matches better. */ + // We have found a match, stop searching unless this is a middle + // comment. The middle comment can be a substring of the end + // comment in which case it's better to return the length of the + // end comment and its flags. Thus we keep searching with middle + // and end matches and use an end match if it matches better. if (vim_strchr(part_buf, COM_MIDDLE) != NULL) { if (middle_match_len == 0) { middle_match_len = j; @@ -170,8 +169,8 @@ int get_leader_len(char_u *line, char_u **flags, bool backward, bool include_spa continue; } if (middle_match_len != 0 && j > middle_match_len) { - /* Use this match instead of the middle match, since it's a - * longer thus better match. */ + // Use this match instead of the middle match, since it's a + // longer thus better match. middle_match_len = 0; } @@ -183,8 +182,8 @@ int get_leader_len(char_u *line, char_u **flags, bool backward, bool include_spa } if (middle_match_len != 0) { - /* Use the previously found middle match after failing to find a - * match with an end. */ + // Use the previously found middle match after failing to find a + // match with an end. if (!got_com && flags != NULL) { *flags = saved_flags; } @@ -254,8 +253,8 @@ int get_last_leader_offset(char_u *line, char_u **flags) */ (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ","); string = vim_strchr(part_buf, ':'); - if (string == NULL) { /* If everything is fine, this cannot actually - * happen. */ + if (string == NULL) { // If everything is fine, this cannot actually + // happen. continue; } *string++ = NUL; // Isolate flags from string. @@ -276,7 +275,7 @@ int get_last_leader_offset(char_u *line, char_u **flags) } } for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j) { - /* do nothing */; + // do nothing } if (string[j] != NUL) { continue; @@ -331,11 +330,10 @@ int get_last_leader_offset(char_u *line, char_u **flags) lower_check_bound = i; - /* Let's verify whether the comment leader found is a substring - * of other comment leaders. If it is, let's adjust the - * lower_check_bound so that we make sure that we have determined - * the comment leader correctly. - */ + // Let's verify whether the comment leader found is a substring + // of other comment leaders. If it is, let's adjust the + // lower_check_bound so that we make sure that we have determined + // the comment leader correctly. while (ascii_iswhite(*com_leader)) { ++com_leader; @@ -359,8 +357,8 @@ int get_last_leader_offset(char_u *line, char_u **flags) continue; } - /* Now we have to verify whether string ends with a substring - * beginning the com_leader. */ + // Now we have to verify whether string ends with a substring + // beginning the com_leader. for (off = (len2 > i ? i : len2); off > 0 && off + len1 > len2; ) { --off; if (!STRNCMP(string + off, com_leader, len2 - off)) { @@ -497,9 +495,9 @@ int get_keystroke(MultiQueue *events) for (;; ) { // flush output before waiting ui_flush(); - /* Leave some room for check_termcode() to insert a key code into (max - * 5 chars plus NUL). And fix_input_buffer() can triple the number of - * bytes. */ + // Leave some room for check_termcode() to insert a key code into (max + // 5 chars plus NUL). And fix_input_buffer() can triple the number of + // bytes. maxlen = (buflen - 6 - len) / 3; if (buf == NULL) { buf = xmalloc((size_t)buflen); @@ -511,8 +509,8 @@ int get_keystroke(MultiQueue *events) maxlen = (buflen - 6 - len) / 3; } - /* First time: blocking wait. Second time: wait up to 100ms for a - * terminal code to complete. */ + // First time: blocking wait. Second time: wait up to 100ms for a + // terminal code to complete. n = os_inchar(buf + len, maxlen, len == 0 ? -1L : 100L, 0, events); if (n > 0) { // Replace zero and CSI by a special key code. @@ -575,8 +573,8 @@ int get_number(int colon, int *mouse_used) *mouse_used = FALSE; } - /* When not printing messages, the user won't know what to type, return a - * zero (as if CR was hit). */ + // When not printing messages, the user won't know what to type, return a + // zero (as if CR was hit). if (msg_silent != 0) { return 0; } @@ -591,7 +589,7 @@ int get_number(int colon, int *mouse_used) ++typed; } else if (c == K_DEL || c == K_KDEL || c == K_BS || c == Ctrl_H) { if (typed > 0) { - MSG_PUTS("\b \b"); + msg_puts("\b \b"); --typed; } n /= 10; @@ -631,10 +629,10 @@ int prompt_for_number(int *mouse_used) // When using ":silent" assume that <CR> was entered. if (mouse_used != NULL) { - MSG_PUTS(_("Type number and <Enter> or click with the mouse " + msg_puts(_("Type number and <Enter> or click with the mouse " "(q or empty cancels): ")); } else { - MSG_PUTS(_("Type number and <Enter> (q or empty cancels): ")); + msg_puts(_("Type number and <Enter> (q or empty cancels): ")); } /* Set the state such that text can be selected/copied/pasted and we still @@ -674,9 +672,9 @@ void msgmore(long n) return; } - /* We don't want to overwrite another important message, but do overwrite - * a previous "more lines" or "fewer lines" message, so that "5dd" and - * then "put" reports the last action. */ + // We don't want to overwrite another important message, but do overwrite + // a previous "more lines" or "fewer lines" message, so that "5dd" and + // then "put" reports the last action. if (keep_msg != NULL && !keep_msg_more) { return; } @@ -688,25 +686,19 @@ void msgmore(long n) } if (pn > p_report) { - if (pn == 1) { - if (n > 0) { - STRLCPY(msg_buf, _("1 more line"), MSG_BUF_LEN); - } else { - STRLCPY(msg_buf, _("1 line less"), MSG_BUF_LEN); - } + if (n > 0) { + vim_snprintf(msg_buf, MSG_BUF_LEN, + NGETTEXT("%ld more line", "%ld more lines", pn), + pn); } else { - if (n > 0) { - vim_snprintf(msg_buf, MSG_BUF_LEN, - _("%" PRId64 " more lines"), (int64_t)pn); - } else { - vim_snprintf(msg_buf, MSG_BUF_LEN, - _("%" PRId64 " fewer lines"), (int64_t)pn); - } + vim_snprintf(msg_buf, MSG_BUF_LEN, + NGETTEXT("%ld line less", "%ld fewer lines", pn), + pn); } if (got_int) { xstrlcat(msg_buf, _(" (Interrupted)"), MSG_BUF_LEN); } - if (msg((char_u *)msg_buf)) { + if (msg(msg_buf)) { set_keep_msg((char_u *)msg_buf, 0); keep_msg_more = true; } @@ -928,7 +920,7 @@ int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg) } if (*p_sh == NUL) { - EMSG(_(e_shellempty)); + emsg(_(e_shellempty)); retval = -1; } else { // The external command may update a tags file, clear cached tags. @@ -966,7 +958,7 @@ char_u *get_cmd_output(char_u *cmd, char_u *infile, ShellOpts flags, size_t *ret // get a name for the temp file char_u *tempname = vim_tempname(); if (tempname == NULL) { - EMSG(_(e_notmp)); + emsg(_(e_notmp)); return NULL; } @@ -987,7 +979,7 @@ char_u *get_cmd_output(char_u *cmd, char_u *infile, ShellOpts flags, size_t *ret FILE *fd = os_fopen((char *)tempname, READBIN); if (fd == NULL) { - EMSG2(_(e_notopen), tempname); + semsg(_(e_notopen), tempname); goto done; } @@ -1000,7 +992,7 @@ char_u *get_cmd_output(char_u *cmd, char_u *infile, ShellOpts flags, size_t *ret fclose(fd); os_remove((char *)tempname); if (i != len) { - EMSG2(_(e_notread), tempname); + semsg(_(e_notread), tempname); XFREE_CLEAR(buffer); } else if (ret_len == NULL) { // Change NUL into SOH, otherwise the string is truncated. diff --git a/src/nvim/move.c b/src/nvim/move.c index 64ba02064f..5114cd6d8a 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -226,9 +226,9 @@ void update_topline(win_T *wp) n = wp->w_topline + *so_ptr - wp->w_cursor.lnum; } - /* If we weren't very close to begin with, we scroll to put the - * cursor in the middle of the window. Otherwise put the cursor - * near the top of the window. */ + // If we weren't very close to begin with, we scroll to put the + // cursor in the middle of the window. Otherwise put the cursor + // near the top of the window. if (n >= halfheight) { scroll_cursor_halfway(false); } else { @@ -263,9 +263,9 @@ void update_topline(win_T *wp) || hasAnyFolding(wp))) { lineoff_T loff; - /* Cursor is (a few lines) above botline, check if there are - * 'scrolloff' window lines below the cursor. If not, need to - * scroll. */ + // Cursor is (a few lines) above botline, check if there are + // 'scrolloff' window lines below the cursor. If not, need to + // scroll. int n = wp->w_empty_rows; loff.lnum = wp->w_cursor.lnum; // In a fold go to its last line. @@ -570,8 +570,8 @@ static void curs_rows(win_T *wp) continue; // skip changed or deleted lines } if (wp->w_lines[i].wl_lnum == lnum) { - /* Check for newly inserted lines below this row, in which - * case we need to check for folded lines. */ + // Check for newly inserted lines below this row, in which + // case we need to check for folded lines. if (!wp->w_buffer->b_mod_set || wp->w_lines[i].wl_lastlnum < wp->w_cursor.lnum || wp->w_buffer->b_mod_top @@ -815,8 +815,8 @@ void curs_columns(win_T *wp, int may_scroll) if (off_left < 0 || off_right > 0) { int diff = (off_left < 0) ? -off_left: off_right; - /* When far off or not enough room on either side, put cursor in - * middle of window. */ + // When far off or not enough room on either side, put cursor in + // middle of window. int new_leftcol; if (p_ss == 0 || diff >= textwidth / 2 || off_right >= off_left) { new_leftcol = wp->w_wcol - extra - textwidth / 2; @@ -848,8 +848,8 @@ void curs_columns(win_T *wp, int may_scroll) wp->w_wcol = 0; } - /* Skip over filler lines. At the top use w_topfill, there - * may be some filler lines above the window. */ + // Skip over filler lines. At the top use w_topfill, there + // may be some filler lines above the window. if (wp->w_cursor.lnum == wp->w_topline) { wp->w_wrow += wp->w_topfill; } else { @@ -869,12 +869,12 @@ void curs_columns(win_T *wp, int may_scroll) && wp->w_cursor.lnum == wp->w_topline && width > 0 && wp->w_width_inner != 0) { - /* Cursor past end of screen. Happens with a single line that does - * not fit on screen. Find a skipcol to show the text around the - * cursor. Avoid scrolling all the time. compute value of "extra": - * 1: Less than "p_so" lines above - * 2: Less than "p_so" lines below - * 3: both of them */ + // Cursor past end of screen. Happens with a single line that does + // not fit on screen. Find a skipcol to show the text around the + // cursor. Avoid scrolling all the time. compute value of "extra": + // 1: Less than "p_so" lines above + // 2: Less than "p_so" lines below + // 3: both of them extra = 0; if (wp->w_skipcol + so * width > wp->w_virtcol) { extra = 1; @@ -1592,8 +1592,8 @@ void scroll_cursor_bot(int min_scroll, int set_topbot) - curwin->w_filler_rows; while (loff.lnum > 1) { - /* Stop when scrolled nothing or at least "min_scroll", found "extra" - * context for 'scrolloff' and counted all lines below the window. */ + // Stop when scrolled nothing or at least "min_scroll", found "extra" + // context for 'scrolloff' and counted all lines below the window. if ((((scrolled <= 0 || scrolled >= min_scroll) && extra >= (mouse_dragging > 0 ? mouse_dragging - 1 : so)) || boff.lnum + 1 > curbuf->b_ml.ml_line_count) @@ -1912,8 +1912,8 @@ int onepage(Direction dir, long count) curwin->w_topfill = 0; curwin->w_valid &= ~(VALID_WROW|VALID_CROW); } else { - /* For the overlap, start with the line just below the window - * and go upwards. */ + // For the overlap, start with the line just below the window + // and go upwards. loff.lnum = curwin->w_botline; loff.fill = win_get_fill(curwin, loff.lnum) - curwin->w_filler_rows; @@ -1948,9 +1948,9 @@ int onepage(Direction dir, long count) continue; } - /* Find the line at the top of the window that is going to be the - * line at the bottom of the window. Make sure this results in - * the same line as before doing CTRL-F. */ + // Find the line at the top of the window that is going to be the + // line at the bottom of the window. Make sure this results in + // the same line as before doing CTRL-F. loff.lnum = curwin->w_topline - 1; loff.fill = win_get_fill(curwin, loff.lnum + 1) - curwin->w_topfill; get_scroll_overlap(&loff, 1); @@ -1963,8 +1963,8 @@ int onepage(Direction dir, long count) } curwin->w_cursor.lnum = loff.lnum; - /* Find the line just above the new topline to get the right line - * at the bottom of the window. */ + // Find the line just above the new topline to get the right line + // at the bottom of the window. n = 0; while (n <= curwin->w_height_inner && loff.lnum >= 1) { topline_back(curwin, &loff); @@ -1987,13 +1987,13 @@ int onepage(Direction dir, long count) // We're at the wrong end of a fold now. (void)hasFoldingWin(curwin, loff.lnum, &loff.lnum, NULL, true, NULL); - /* Always scroll at least one line. Avoid getting stuck on - * very long lines. */ + // Always scroll at least one line. Avoid getting stuck on + // very long lines. if (loff.lnum >= curwin->w_topline && (loff.lnum > curwin->w_topline || loff.fill >= curwin->w_topfill)) { - /* First try using the maximum number of filler lines. If - * that's not enough, backup one line. */ + // First try using the maximum number of filler lines. If + // that's not enough, backup one line. loff.fill = curwin->w_topfill; if (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline)) { max_topfill(); @@ -2266,8 +2266,8 @@ void do_check_cursorbind(void) curwin->w_curswant = curswant; curwin->w_set_curswant = set_curswant; - /* Make sure the cursor is in a valid position. Temporarily set - * "restart_edit" to allow the cursor to be beyond the EOL. */ + // Make sure the cursor is in a valid position. Temporarily set + // "restart_edit" to allow the cursor to be beyond the EOL. { int restart_edit_save = restart_edit; restart_edit = true; diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 686071e25a..1effeefd32 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -414,14 +414,14 @@ static int find_command(int cmdchar) return -1; } - /* We use the absolute value of the character. Special keys have a - * negative value, but are sorted on their absolute value. */ + // We use the absolute value of the character. Special keys have a + // negative value, but are sorted on their absolute value. if (cmdchar < 0) { cmdchar = -cmdchar; } - /* If the character is in the first part: The character is the index into - * nv_cmd_idx[]. */ + // If the character is in the first part: The character is the index into + // nv_cmd_idx[]. assert(nv_max_linear < (int)NV_CMDS_SIZE); if (cmdchar <= nv_max_linear) { return nv_cmd_idx[cmdchar]; @@ -2170,7 +2170,7 @@ static void op_function(const oparg_T *oap) const bool save_finish_op = finish_op; if (*p_opfunc == NUL) { - EMSG(_("E774: 'operatorfunc' is empty")); + emsg(_("E774: 'operatorfunc' is empty")); } else { // Set '[ and '] marks to text to be operated on. curbuf->b_op_start = oap->start; @@ -2931,7 +2931,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent) find_start_of_word(&VIsual); if (*p_sel == 'e' && *get_cursor_pos_ptr() != NUL) { curwin->w_cursor.col += - (*mb_ptr2len)(get_cursor_pos_ptr()); + utfc_ptr2len(get_cursor_pos_ptr()); } find_end_of_word(&curwin->w_cursor); } @@ -2998,7 +2998,7 @@ static void find_end_of_word(pos_T *pos) } cclass = get_mouse_class(line + pos->col); while (line[pos->col] != NUL) { - col = pos->col + (*mb_ptr2len)(line + pos->col); + col = pos->col + utfc_ptr2len(line + pos->col); if (get_mouse_class(line + col) != cclass) { if (*p_sel == 'e') { pos->col = col; @@ -3225,9 +3225,9 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char_u **te if (ptr[col] == NUL || (i == 0 && this_class != 2)) { // Didn't find an identifier or text. if (find_type & FIND_STRING) { - EMSG(_("E348: No string under cursor")); + emsg(_("E348: No string under cursor")); } else { - EMSG(_(e_noident)); + emsg(_(e_noident)); } return 0; } @@ -3437,7 +3437,7 @@ void clear_showcmd(void) e = ml_get_pos(&VIsual); } while ((*p_sel != 'e') ? s <= e : s < e) { - l = (*mb_ptr2len)(s); + l = utfc_ptr2len(s); if (l == 0) { ++bytes; ++chars; @@ -3897,8 +3897,8 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_ pat = xmalloc(len + 7); - /* Put "\V" before the pattern to avoid that the special meaning of "." - * and "~" causes trouble. */ + // Put "\V" before the pattern to avoid that the special meaning of "." + // and "~" causes trouble. assert(len <= INT_MAX); sprintf((char *)pat, vim_iswordp(ptr) ? "\\V\\<%.*s\\>" : "\\V%.*s", (int)len, ptr); @@ -4252,9 +4252,9 @@ void scroll_redraw(int up, long count) check_cursor_moved(curwin); curwin->w_valid |= VALID_TOPLINE; - /* If moved back to where we were, at least move the cursor, otherwise - * we get stuck at one position. Don't move the cursor up if the - * first line of the buffer is already on the screen */ + // If moved back to where we were, at least move the cursor, otherwise + // we get stuck at one position. Don't move the cursor up if the + // first line of the buffer is already on the screen while (curwin->w_topline == prev_topline && curwin->w_topfill == prev_topfill) { if (up) { @@ -4338,7 +4338,7 @@ static void nv_zet(cmdarg_T *cap) dozet: // "zf" and "zF" are always an operator, "zd", "zo", "zO", "zc" // and "zC" only in Visual mode. "zj" and "zk" are motion - // commands. */ + // commands. if (cap->nchar != 'f' && cap->nchar != 'F' && !(VIsual_active && vim_strchr((char_u *)"dcCoO", cap->nchar)) && cap->nchar != 'j' && cap->nchar != 'k' @@ -4546,7 +4546,7 @@ dozet: } else if (foldmethodIsMarker(curwin)) { deleteFold(curwin, (linenr_T)1, curbuf->b_ml.ml_line_count, true, false); } else { - EMSG(_("E352: Cannot erase folds with current 'foldmethod'")); + emsg(_("E352: Cannot erase folds with current 'foldmethod'")); } break; @@ -4772,7 +4772,6 @@ dozet: } - /* * "Q" command. */ @@ -5003,15 +5002,15 @@ static void nv_ident(cmdarg_T *cap) return; } - /* Allocate buffer to put the command in. Inserting backslashes can - * double the length of the word. p_kp / curbuf->b_p_kp could be added - * and some numbers. */ + // Allocate buffer to put the command in. Inserting backslashes can + // double the length of the word. p_kp / curbuf->b_p_kp could be added + // and some numbers. 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); if (kp_help && *skipwhite(ptr) == NUL) { - EMSG(_(e_noident)); // found white space only + emsg(_(e_noident)); // found white space only return; } size_t buf_size = n * 2 + 30 + STRLEN(kp); @@ -5046,20 +5045,20 @@ static void nv_ident(cmdarg_T *cap) STRCAT(buf, kp); STRCAT(buf, " "); } else { - /* An external command will probably use an argument starting - * with "-" as an option. To avoid trouble we skip the "-". */ + // An external command will probably use an argument starting + // with "-" as an option. To avoid trouble we skip the "-". while (*ptr == '-' && n > 0) { ++ptr; --n; } if (n == 0) { - EMSG(_(e_noident)); // found dashes only + emsg(_(e_noident)); // found dashes only xfree(buf); return; } - /* When a count is given, turn it into a range. Is this - * really what we want? */ + // When a count is given, turn it into a range. Is this + // really what we want? bool isman = (STRCMP(kp, "man") == 0); bool isman_s = (STRCMP(kp, "man -s") == 0); if (cap->count0 != 0 && !(isman || isman_s)) { @@ -5141,8 +5140,8 @@ static void nv_ident(cmdarg_T *cap) if (vim_strchr(aux_ptr, *ptr) != NULL) { *p++ = '\\'; } - /* When current byte is a part of multibyte character, copy all - * bytes of that character. */ + // When current byte is a part of multibyte character, copy all + // bytes of that character. const size_t len = (size_t)(utfc_ptr2len(ptr) - 1); for (size_t i = 0; i < len && n > 0; i++, n--) { *p++ = *ptr++; @@ -5383,7 +5382,7 @@ static void nv_right(cmdarg_T *cap) if (virtual_active()) { oneright(); } else { - curwin->w_cursor.col += (*mb_ptr2len)(get_cursor_pos_ptr()); + curwin->w_cursor.col += utfc_ptr2len(get_cursor_pos_ptr()); } } } @@ -5415,10 +5414,9 @@ static void nv_left(cmdarg_T *cap) cap->oap->inclusive = false; for (n = cap->count1; n > 0; --n) { if (oneleft() == false) { - /* <BS> and <Del> wrap to previous line if 'whichwrap' has 'b'. - * 'h' wraps to previous line if 'whichwrap' has 'h'. - * CURS_LEFT wraps to previous line if 'whichwrap' has '<'. - */ + // <BS> and <Del> wrap to previous line if 'whichwrap' has 'b'. + // 'h' wraps to previous line if 'whichwrap' has 'h'. + // CURS_LEFT wraps to previous line if 'whichwrap' has '<'. if ((((cap->cmdchar == K_BS || cap->cmdchar == Ctrl_H) && vim_strchr(p_ww, 'b') != NULL) || (cap->cmdchar == 'h' && vim_strchr(p_ww, 'h') != NULL) @@ -5570,9 +5568,9 @@ static void nv_dollar(cmdarg_T *cap) { cap->oap->motion_type = kMTCharWise; cap->oap->inclusive = true; - /* In virtual mode when off the edge of a line and an operator - * is pending (whew!) keep the cursor where it is. - * Otherwise, send it to the end of the line. */ + // In virtual mode when off the edge of a line and an operator + // is pending (whew!) keep the cursor where it is. + // Otherwise, send it to the end of the line. if (!virtual_active() || gchar_cursor() != NUL || cap->oap->op_type == OP_NOP) { curwin->w_curswant = MAXCOL; // so we stay at the end @@ -5781,10 +5779,10 @@ static void nv_brackets(cmdarg_T *cap) * "[m" or "]m" search for prev/next start of (Java) method. * "[M" or "]M" search for prev/next end of (Java) method. */ - if ( (cap->cmdchar == '[' - && vim_strchr((char_u *)"{(*/#mM", cap->nchar) != NULL) - || (cap->cmdchar == ']' - && vim_strchr((char_u *)"})*/#mM", cap->nchar) != NULL)) { + if ((cap->cmdchar == '[' + && vim_strchr((char_u *)"{(*/#mM", cap->nchar) != NULL) + || (cap->cmdchar == ']' + && vim_strchr((char_u *)"})*/#mM", cap->nchar) != NULL)) { if (cap->nchar == '*') { cap->nchar = '/'; } @@ -6278,9 +6276,9 @@ static void nv_replace(cmdarg_T *cap) ins_char(cap->ncharC2); } } - --curwin->w_cursor.col; // cursor on the last replaced char - /* if the character on the left of the current cursor is a multi-byte - * character, move two characters left */ + curwin->w_cursor.col--; // cursor on the last replaced char + // if the character on the left of the current cursor is a multi-byte + // character, move two characters left mb_adjust_cursor(); curbuf->b_op_end = curwin->w_cursor; curwin->w_set_curswant = true; @@ -6350,7 +6348,7 @@ static void nv_Replace(cmdarg_T *cap) nv_operator(cap); } else if (!checkclearopq(cap->oap)) { if (!MODIFIABLE(curbuf)) { - EMSG(_(e_modifiable)); + emsg(_(e_modifiable)); } else { if (virtual_active()) { coladvance(getviscol()); @@ -6371,7 +6369,7 @@ static void nv_vreplace(cmdarg_T *cap) nv_replace(cap); // Do same as "r" in Visual mode for now } else if (!checkclearopq(cap->oap)) { if (!MODIFIABLE(curbuf)) { - EMSG(_(e_modifiable)); + emsg(_(e_modifiable)); } else { if (cap->extra_char == Ctrl_V) { // get another character cap->extra_char = get_literal(); @@ -6616,11 +6614,11 @@ static void nv_pcmark(cmdarg_T *cap) nv_cursormark(cap, false, pos); } else if (cap->cmdchar == 'g') { if (curbuf->b_changelistlen == 0) { - EMSG(_("E664: changelist is empty")); + emsg(_("E664: changelist is empty")); } else if (cap->count1 < 0) { - EMSG(_("E662: At start of changelist")); + emsg(_("E662: At start of changelist")); } else { - EMSG(_("E663: At end of changelist")); + emsg(_("E663: At end of changelist")); } } else { clearopbeep(cap->oap); @@ -6802,8 +6800,8 @@ static void n_start_visual_mode(int c) if (p_smd && msg_silent == 0) { redraw_cmdline = true; // show visual mode later } - /* Only need to redraw this line, unless still need to redraw an old - * Visual area (when 'lazyredraw' is set). */ + // Only need to redraw this line, unless still need to redraw an old + // Visual area (when 'lazyredraw' is set). if (curwin->w_redr_type < INVERTED) { curwin->w_old_cursor_lnum = curwin->w_cursor.lnum; curwin->w_old_visual_lnum = curwin->w_cursor.lnum; @@ -7571,8 +7569,8 @@ static void nv_home(cmdarg_T *cap) cap->count0 = 1; nv_pipe(cap); } - ins_at_eol = false; /* Don't move cursor past eol (only necessary in a - one-character line). */ + ins_at_eol = false; // Don't move cursor past eol (only necessary in a + // one-character line). } /* @@ -7589,8 +7587,8 @@ static void nv_pipe(cmdarg_T *cap) } else { curwin->w_curswant = 0; } - /* keep curswant at the column where we wanted to go, not where - * we ended; differs if line is too short */ + // keep curswant at the column where we wanted to go, not where + // we ended; differs if line is too short curwin->w_set_curswant = false; } @@ -7661,8 +7659,8 @@ static void nv_wordcmd(cmdarg_T *cap) n = fwd_word(cap->count1, cap->arg, cap->oap->op_type != OP_NOP); } - /* Don't leave the cursor on the NUL past the end of line. Unless we - * didn't move it forward. */ + // Don't leave the cursor on the NUL past the end of line. Unless we + // didn't move it forward. if (lt(startpos, curwin->w_cursor)) { adjust_cursor(cap->oap); } @@ -7711,8 +7709,8 @@ static void nv_beginline(cmdarg_T *cap) if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP) { foldOpenCursor(); } - ins_at_eol = false; /* Don't move cursor past eol (only necessary in a - one-character line). */ + ins_at_eol = false; // Don't move cursor past eol (only necessary in a + // one-character line). } /* @@ -7850,15 +7848,15 @@ static void nv_esc(cmdarg_T *cap) && !VIsual_active && no_reason) { if (anyBufIsChanged()) { - MSG(_("Type :qa! and press <Enter> to abandon all changes" + msg(_("Type :qa! and press <Enter> to abandon all changes" " and exit Nvim")); } else { - MSG(_("Type :qa and press <Enter> to exit Nvim")); + msg(_("Type :qa and press <Enter> to exit Nvim")); } } - /* Don't reset "restart_edit" when 'insertmode' is set, it won't be - * set again below when halfway through a mapping. */ + // Don't reset "restart_edit" when 'insertmode' is set, it won't be + // set again below when halfway through a mapping. if (!p_im) { restart_edit = 0; } @@ -7885,8 +7883,8 @@ static void nv_esc(cmdarg_T *cap) } clearop(cap->oap); - /* A CTRL-C is often used at the start of a menu. When 'insertmode' is - * set return to Insert mode afterwards. */ + // A CTRL-C is often used at the start of a menu. When 'insertmode' is + // set return to Insert mode afterwards. if (restart_edit == 0 && goto_im() && ex_normal_busy == 0) { restart_edit = 'a'; @@ -7927,7 +7925,7 @@ static void nv_edit(cmdarg_T *cap) nv_object(cap); } else if (!curbuf->b_p_ma && !p_im && !curbuf->terminal) { // Only give this error when 'insertmode' is off. - EMSG(_(e_modifiable)); + emsg(_(e_modifiable)); clearop(cap->oap); } else if (!checkclearopq(cap->oap)) { switch (cap->cmdchar) { @@ -7940,8 +7938,8 @@ static void nv_edit(cmdarg_T *cap) break; case 'a': // "a"ppend is like "i"nsert on the next character. - /* increment coladd when in virtual space, increment the - * column otherwise, also to append after an unprintable char */ + // increment coladd when in virtual space, increment the + // column otherwise, also to append after an unprintable char if (virtual_active() && (curwin->w_cursor.coladd > 0 || *get_cursor_pos_ptr() == NUL @@ -8209,11 +8207,10 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent) } if (VIsual_active) { - /* Putting in Visual mode: The put text replaces the selected - * text. First delete the selected text, then put the new text. - * Need to save and restore the registers that the delete - * overwrites if the old contents is being put. - */ + // Putting in Visual mode: The put text replaces the selected + // text. First delete the selected text, then put the new text. + // Need to save and restore the registers that the delete + // overwrites if the old contents is being put. was_visual = true; regname = cap->oap->regname; // '+' and '*' could be the same selection @@ -8286,14 +8283,14 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent) } } - /* When all lines were selected and deleted do_put() leaves an empty - * line that needs to be deleted now. */ + // When all lines were selected and deleted do_put() leaves an empty + // line that needs to be deleted now. if (empty && *ml_get(curbuf->b_ml.ml_line_count) == NUL) { ml_delete(curbuf->b_ml.ml_line_count, true); deleted_lines(curbuf->b_ml.ml_line_count + 1, 1); - /* If the cursor was in that line, move it to the end of the last - * line. */ + // If the cursor was in that line, move it to the end of the last + // line. if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) { curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; coladvance(MAXCOL); diff --git a/src/nvim/normal.h b/src/nvim/normal.h index fbcc6da75b..0c2b8b4d8a 100644 --- a/src/nvim/normal.h +++ b/src/nvim/normal.h @@ -19,7 +19,7 @@ typedef enum { kMTCharWise = 0, ///< character-wise movement/register kMTLineWise = 1, ///< line-wise movement/register kMTBlockWise = 2, ///< block-wise movement/register - kMTUnknown = -1 ///< Unknown or invalid motion type + kMTUnknown = -1, ///< Unknown or invalid motion type } MotionType; /* diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 3a8f7c42a5..7d7db2a8a6 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -210,7 +210,6 @@ void op_shift(oparg_T *oap, int curs_top, int amount) { long i; int first_char; - char_u *s; int block_col = 0; if (u_save((linenr_T)(oap->start.lnum - 1), @@ -249,27 +248,21 @@ void op_shift(oparg_T *oap, int curs_top, int amount) foldOpenCursor(); if (oap->line_count > p_report) { + char *op; if (oap->op_type == OP_RSHIFT) { - s = (char_u *)">"; + op = ">"; } else { - s = (char_u *)"<"; + op = "<"; } - if (oap->line_count == 1) { - if (amount == 1) { - sprintf((char *)IObuff, _("1 line %sed 1 time"), s); - } else { - sprintf((char *)IObuff, _("1 line %sed %d times"), s, amount); - } - } else { - if (amount == 1) { - sprintf((char *)IObuff, _("%" PRId64 " lines %sed 1 time"), - (int64_t)oap->line_count, s); - } else { - sprintf((char *)IObuff, _("%" PRId64 " lines %sed %d times"), - (int64_t)oap->line_count, s, amount); - } - } - msg_attr_keep(IObuff, 0, true, false); + + char *msg_line_single = NGETTEXT("%" PRId64 " line %sed %d time", + "%" PRId64 " line %sed %d times", amount); + char *msg_line_plural = NGETTEXT("%" PRId64 " lines %sed %d time", + "%" PRId64 " lines %sed %d times", amount); + vim_snprintf((char *)IObuff, IOSIZE, + NGETTEXT(msg_line_single, msg_line_plural, oap->line_count), + (int64_t)oap->line_count, op, amount); + msg_attr_keep((char *)IObuff, 0, true, false); } /* @@ -391,8 +384,8 @@ static void shift_block(oparg_T *oap, int amount) total += incr; bd.start_vcol += incr; } - /* OK, now total=all the VWS reqd, and textstart points at the 1st - * non-ws char in the block. */ + // OK, now total=all the VWS reqd, and textstart points at the 1st + // non-ws char in the block. if (!curbuf->b_p_et) { tabstop_fromto(ws_vcol, ws_vcol + total, p_ts, p_vts, &i, &j); } else { @@ -459,14 +452,14 @@ static void shift_block(oparg_T *oap, int amount) // The column to which we will shift the text. destination_col = non_white_col - shift_amount; - /* Now let's find out how much of the beginning of the line we can - * reuse without modification. */ + // Now let's find out how much of the beginning of the line we can + // reuse without modification. verbatim_copy_end = bd.textstart; verbatim_copy_width = bd.start_vcol; - /* If "bd.startspaces" is set, "bd.textstart" points to the character - * preceding the block. We have to subtract its width to obtain its - * column number. */ + // If "bd.startspaces" is set, "bd.textstart" points to the character + // preceding the block. We have to subtract its width to obtain its + // column number. if (bd.startspaces) { verbatim_copy_width -= bd.start_char_vcols; } @@ -482,9 +475,9 @@ static void shift_block(oparg_T *oap, int amount) MB_PTR_ADV(verbatim_copy_end); } - /* If "destination_col" is different from the width of the initial - * part of the line that will be copied, it means we encountered a tab - * character, which we will have to partly replace with spaces. */ + // If "destination_col" is different from the width of the initial + // part of the line that will be copied, it means we encountered a tab + // character, which we will have to partly replace with spaces. assert(destination_col - verbatim_copy_width >= 0); fill = (size_t)(destination_col - verbatim_copy_width); @@ -640,7 +633,7 @@ void op_reindent(oparg_T *oap, Indenter how) // Don't even try when 'modifiable' is off. if (!MODIFIABLE(curbuf)) { - EMSG(_(e_modifiable)); + emsg(_(e_modifiable)); return; } @@ -695,11 +688,9 @@ void op_reindent(oparg_T *oap, Indenter how) if (oap->line_count > p_report) { i = oap->line_count - (i + 1); - if (i == 1) { - MSG(_("1 line indented ")); - } else { - smsg(_("%" PRId64 " lines indented "), (int64_t)i); - } + smsg(NGETTEXT("%" PRId64 " line indented ", + "%" PRId64 " lines indented ", i), + (int64_t)i); } // set '[ and '] marks curbuf->b_op_start = oap->start; @@ -930,7 +921,7 @@ int do_record(int c) if (ui_has(kUIMessages)) { showmode(); } else { - MSG(""); + msg(""); } p = get_recorded(); if (p == NULL) { @@ -1018,7 +1009,7 @@ int do_execreg(int regname, int colon, int addcr, int silent) if (regname == '@') { // repeat previous one if (execreg_lastc == NUL) { - EMSG(_("E748: No previously used register")); + emsg(_("E748: No previously used register")); return FAIL; } regname = execreg_lastc; @@ -1036,7 +1027,7 @@ int do_execreg(int regname, int colon, int addcr, int silent) if (regname == ':') { // use last command line if (last_cmdline == NULL) { - EMSG(_(e_nolastcmd)); + emsg(_(e_nolastcmd)); return FAIL; } // don't keep the cmdline containing @: @@ -1066,7 +1057,7 @@ int do_execreg(int regname, int colon, int addcr, int silent) } else if (regname == '.') { // use last inserted text p = get_last_insert_save(); if (p == NULL) { - EMSG(_(e_noinstext)); + emsg(_(e_noinstext)); return FAIL; } retval = put_in_typebuf(p, false, colon, silent); @@ -1291,14 +1282,14 @@ bool get_spec_reg(int regname, char_u **argp, bool *allocated, bool errmsg) case ':': // last command line if (last_cmdline == NULL && errmsg) { - EMSG(_(e_nolastcmd)); + emsg(_(e_nolastcmd)); } *argp = last_cmdline; return true; case '/': // last search-pattern if (last_search_pat() == NULL && errmsg) { - EMSG(_(e_noprevre)); + emsg(_(e_noprevre)); } *argp = last_search_pat(); return true; @@ -1307,7 +1298,7 @@ bool get_spec_reg(int regname, char_u **argp, bool *allocated, bool errmsg) *argp = get_last_insert_save(); *allocated = true; if (*argp == NULL && errmsg) { - EMSG(_(e_noinstext)); + emsg(_(e_noinstext)); } return true; @@ -1424,7 +1415,7 @@ int op_delete(oparg_T *oap) } if (!MODIFIABLE(curbuf)) { - EMSG(_(e_modifiable)); + emsg(_(e_modifiable)); return FAIL; } @@ -1500,8 +1491,8 @@ int op_delete(oparg_T *oap) did_yank = true; } - /* Yank into small delete register when no named register specified - * and the delete is within one line. */ + // Yank into small delete register when no named register specified + // and the delete is within one line. if (oap->regname == 0 && oap->motion_type != kMTLineWise && oap->line_count == 1) { reg = get_yank_register('-', YREG_YANK); @@ -1659,9 +1650,8 @@ int op_delete(oparg_T *oap) n = oap->end.col - oap->start.col + 1 - !oap->inclusive; if (virtual_op) { - /* fix up things for virtualedit-delete: - * break the tabs which are going to get in our way - */ + // fix up things for virtualedit-delete: + // break the tabs which are going to get in our way char_u *curline = get_cursor_line_ptr(); int len = (int)STRLEN(curline); @@ -1788,7 +1778,7 @@ int op_replace(oparg_T *oap, int c) char_u *after_p = NULL; int had_ctrl_v_cr = false; - if ((curbuf->b_ml.ml_flags & ML_EMPTY ) || oap->empty) { + if ((curbuf->b_ml.ml_flags & ML_EMPTY) || oap->empty) { return OK; // nothing to do } if (c == REPLACE_CR_NCHAR) { @@ -1818,12 +1808,11 @@ int op_replace(oparg_T *oap, int c) continue; // nothing to replace } - /* n == number of extra chars required - * If we split a TAB, it may be replaced by several characters. - * Thus the number of characters may increase! - */ - /* If the range starts in virtual space, count the initial - * coladd offset as part of "startspaces" */ + // n == number of extra chars required + // If we split a TAB, it may be replaced by several characters. + // Thus the number of characters may increase! + // If the range starts in virtual space, count the initial + // coladd offset as part of "startspaces" if (virtual_op && bd.is_short && *bd.textstart == NUL) { pos_T vpos; @@ -1848,7 +1837,7 @@ int op_replace(oparg_T *oap, int c) // A double-wide character can be replaced only up to half the // times. - if ((*mb_char2cells)(c) > 1) { + if (utf_char2cells(c) > 1) { if ((numc & 1) && !bd.is_short) { ++bd.endspaces; ++n; @@ -1858,7 +1847,7 @@ int op_replace(oparg_T *oap, int c) // Compute bytes needed, move character count to num_chars. num_chars = numc; - numc *= (*mb_char2len)(c); + numc *= utf_char2len(c); oldp = get_cursor_line_ptr(); oldlen = (int)STRLEN(oldp); @@ -1937,11 +1926,11 @@ int op_replace(oparg_T *oap, int c) while (ltoreq(curwin->w_cursor, oap->end)) { n = gchar_cursor(); if (n != NUL) { - if ((*mb_char2len)(c) > 1 || (*mb_char2len)(n) > 1) { + if (utf_char2len(c) > 1 || utf_char2len(n) > 1) { // This is slow, but it handles replacing a single-byte // with a multi-byte and the other way around. if (curwin->w_cursor.lnum == oap->end.lnum) { - oap->end.col += (*mb_char2len)(c) - (*mb_char2len)(n); + oap->end.col += utf_char2len(c) - utf_char2len(n); } replace_character(c); } else { @@ -2075,11 +2064,9 @@ void op_tilde(oparg_T *oap) curbuf->b_op_end = oap->end; if (oap->line_count > p_report) { - if (oap->line_count == 1) { - MSG(_("1 line changed")); - } else { - smsg(_("%" PRId64 " lines changed"), (int64_t)oap->line_count); - } + smsg(NGETTEXT("%" PRId64 " line changed", + "%" PRId64 " lines changed", oap->line_count), + (int64_t)oap->line_count); } } @@ -2255,15 +2242,15 @@ void op_insert(oparg_T *oap, long count1) // When a tab was inserted, and the characters in front of the tab // have been converted to a tab as well, the column of the cursor - // might have actually been reduced, so need to adjust here. */ + // might have actually been reduced, so need to adjust here. if (t1.lnum == curbuf->b_op_start_orig.lnum && lt(curbuf->b_op_start_orig, t1)) { oap->start = curbuf->b_op_start_orig; } - /* If user has moved off this line, we don't know what to do, so do - * nothing. - * Also don't repeat the insert when Insert mode ended with CTRL-C. */ + // If user has moved off this line, we don't know what to do, so do + // nothing. + // Also don't repeat the insert when Insert mode ended with CTRL-C. if (curwin->w_cursor.lnum != oap->start.lnum || got_int) { return; } @@ -2440,8 +2427,8 @@ int op_change(oparg_T *oap) ins_len = (long)STRLEN(firstline) - pre_textlen; if (ins_len > 0) { - /* Subsequent calls to ml_get() flush the firstline data - take a - * copy of the inserted text. */ + // Subsequent calls to ml_get() flush the firstline data - take a + // copy of the inserted text. ins_text = (char_u *)xmalloc((size_t)(ins_len + 1)); STRLCPY(ins_text, firstline + bd.textcol, ins_len + 1); for (linenr = oap->start.lnum + 1; linenr <= oap->end.lnum; @@ -2450,8 +2437,8 @@ int op_change(oparg_T *oap) if (!bd.is_short || virtual_op) { pos_T vpos; - /* If the block starts in virtual space, count the - * initial coladd offset as part of "startspaces" */ + // If the block starts in virtual space, count the + // initial coladd offset as part of "startspaces" if (bd.is_short) { vpos.lnum = linenr; (void)getvpos(&vpos, oap->start_vcol); @@ -2734,17 +2721,14 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) // redisplay now, so message is not deleted update_topline_redraw(); - if (yanklines == 1) { - if (yank_type == kMTBlockWise) { - smsg(_("block of 1 line yanked%s"), namebuf); - } else { - smsg(_("1 line yanked%s"), namebuf); - } - } else if (yank_type == kMTBlockWise) { - smsg(_("block of %" PRId64 " lines yanked%s"), + if (yank_type == kMTBlockWise) { + smsg(NGETTEXT("block of %" PRId64 " line yanked%s", + "block of %" PRId64 " lines yanked%s", yanklines), (int64_t)yanklines, namebuf); } else { - smsg(_("%" PRId64 " lines yanked%s"), (int64_t)yanklines, namebuf); + smsg(NGETTEXT("%" PRId64 " line yanked%s", + "%" PRId64 " lines yanked%s", yanklines), + (int64_t)yanklines, namebuf); } } } @@ -2955,7 +2939,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) bool one_past_line = (*cursor_pos == NUL); bool eol = false; if (!one_past_line) { - eol = (*(cursor_pos + mb_ptr2len(cursor_pos)) == NUL); + eol = (*(cursor_pos + utfc_ptr2len(cursor_pos)) == NUL); } bool ve_allows = (ve_flags == VE_ALL || ve_flags == VE_ONEMORE); @@ -3091,7 +3075,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) } if (y_size == 0 || y_array == NULL) { - EMSG2(_("E353: Nothing in register %s"), + semsg(_("E353: Nothing in register %s"), regname == 0 ? (char_u *)"\"" : transchar(regname)); goto end; } @@ -3333,7 +3317,7 @@ 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) { - int bytelen = (*mb_ptr2len)(get_cursor_pos_ptr()); + int bytelen = utfc_ptr2len(get_cursor_pos_ptr()); // put it on the next of the multi-byte character. col += bytelen; @@ -3710,22 +3694,22 @@ void ex_display(exarg_T *eap) msg_puts(" "); msg_putchar('"'); msg_putchar(name); - MSG_PUTS(" "); + msg_puts(" "); int n = Columns - 11; for (size_t j = 0; j < yb->y_size && n > 1; j++) { if (j) { - MSG_PUTS_ATTR("^J", attr); + msg_puts_attr("^J", attr); n -= 2; } for (p = yb->y_array[j]; *p && (n -= ptr2cells(p)) >= 0; p++) { // -V1019 NOLINT(whitespace/line_length) - clen = (*mb_ptr2len)(p); + clen = utfc_ptr2len(p); msg_outtrans_len(p, clen); p += clen - 1; } } if (n > 1 && yb->y_type == kMTLineWise) { - MSG_PUTS_ATTR("^J", attr); + msg_puts_attr("^J", attr); } ui_flush(); // show one line at a time } @@ -3834,9 +3818,8 @@ char_u *skip_comment(char_u *line, bool process, bool include_space, bool *is_co *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. - */ + // 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 == ':') { @@ -3859,11 +3842,10 @@ char_u *skip_comment(char_u *line, bool process, bool include_space, bool *is_co return line; } - /* Find: - * - COM_END, - * - colon, - * whichever comes first. - */ + // Find: + // - COM_END, + // - colon, + // whichever comes first. while (*comment_flags) { if (*comment_flags == COM_END || *comment_flags == ':') { @@ -4145,7 +4127,6 @@ static int same_leader(linenr_T lnum, int leader1_len, char_u *leader1_flags, in */ line1 = vim_strsave(ml_get(lnum)); for (idx1 = 0; ascii_iswhite(line1[idx1]); ++idx1) { - ; } line2 = ml_get(lnum + 1); for (idx2 = 0; idx2 < leader2_len; ++idx2) { @@ -4655,8 +4636,8 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool bdp->endspaces = oap->end_vcol - oap->start_vcol + 1; } } else { - /* notice: this converts partly selected Multibyte characters to - * spaces, too. */ + // notice: this converts partly selected Multibyte characters to + // spaces, too. bdp->startspaces = bdp->start_vcol - oap->start_vcol; if (is_del && bdp->startspaces) { bdp->startspaces = bdp->start_char_vcols - bdp->startspaces; @@ -4813,11 +4794,9 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd) } if (change_cnt > p_report) { - if (change_cnt == 1) { - MSG(_("1 line changed")); - } else { - smsg(_("%" PRId64 " lines changed"), (int64_t)change_cnt); - } + smsg(NGETTEXT("%" PRId64 " lines changed", + "%" PRId64 " lines changed", change_cnt), + (int64_t)change_cnt); } } } @@ -5404,7 +5383,7 @@ void write_reg_contents_lst(int name, char_u **strings, bool must_append, Motion if (strings[0] == NULL) { s = (char_u *)""; } else if (strings[1] != NULL) { - EMSG(_("E883: search pattern and expression register may not " + emsg(_("E883: search pattern and expression register may not " "contain two or more lines")); return; } @@ -5466,7 +5445,7 @@ void write_reg_contents_ex(int name, const char_u *str, ssize_t len, bool must_a buf = buflist_findnr(num); if (buf == NULL) { - EMSGN(_(e_nobufnr), (long)num); + semsg(_(e_nobufnr), (int64_t)num); } } else { buf = buflist_findnr(buflist_findpat(str, str + STRLEN(str), @@ -5661,8 +5640,8 @@ static varnumber_T line_count_info(char_u *line, varnumber_T *wc, varnumber_T *c } else if (!ascii_isspace(line[i])) { is_word = 1; } - ++chars; - i += (*mb_ptr2len)(line + i); + chars++; + i += utfc_ptr2len(line + i); } if (is_word) { @@ -5708,7 +5687,7 @@ void cursor_pos_info(dict_T *dict) // Compute the length of the file in characters. if (curbuf->b_ml.ml_flags & ML_EMPTY) { if (dict == NULL) { - MSG(_(no_lines_msg)); + msg(_(no_lines_msg)); return; } } else { @@ -5906,7 +5885,7 @@ void cursor_pos_info(dict_T *dict) // Don't shorten this message, the user asked for it. p = p_shm; p_shm = (char_u *)""; - msg(IObuff); + msg((char *)IObuff); p_shm = p; } } @@ -5968,7 +5947,7 @@ static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing) 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); + msg(MSG_NO_CLIP); } // ... else, be silent (don't flood during :while, :redir, etc.). goto end; @@ -6206,7 +6185,7 @@ err: reg->additional_data = NULL; reg->timestamp = 0; if (errmsg) { - EMSG("clipboard: provider returned invalid data"); + emsg("clipboard: provider returned invalid data"); } *target = reg; return false; diff --git a/src/nvim/ops.h b/src/nvim/ops.h index 11049b72c0..efde7290cf 100644 --- a/src/nvim/ops.h +++ b/src/nvim/ops.h @@ -77,7 +77,7 @@ typedef int (*Indenter)(void); enum GRegFlags { kGRegNoExpr = 1, ///< Do not allow expression register. kGRegExprSrc = 2, ///< Return expression itself for "=" register. - kGRegList = 4 ///< Return list. + kGRegList = 4, ///< Return list. }; /// Definition of one register diff --git a/src/nvim/option.c b/src/nvim/option.c index f471861473..b7df856949 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -105,7 +105,7 @@ // WV_ and BV_ values get typecasted to this for the "indir" field typedef enum { PV_NONE = 0, - PV_MAXVAL = 0xffff // to avoid warnings for value out of range + PV_MAXVAL = 0xffff, // to avoid warnings for value out of range } idopt_T; /* @@ -419,7 +419,7 @@ void set_init_1(bool clean_arg) } xfree(item); } - if(mustfree) { + if (mustfree) { xfree(p); } } @@ -568,12 +568,11 @@ void set_init_1(bool clean_arg) save_file_ff(curbuf); // Buffer is unchanged - /* Detect use of mlterm. - * Mlterm is a terminal emulator akin to xterm that has some special - * abilities (bidi namely). - * NOTE: mlterm's author is being asked to 'set' a variable - * instead of an environment variable due to inheritance. - */ + // Detect use of mlterm. + // Mlterm is a terminal emulator akin to xterm that has some special + // abilities (bidi namely). + // 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("tbidi", 1L, NULL, 0); } @@ -950,8 +949,8 @@ void set_title_defaults(void) int do_set(char_u *arg, int opt_flags) { int opt_idx; - char_u *errmsg; - char_u errbuf[80]; + char *errmsg; + char errbuf[80]; char_u *startarg; int prefix; // 1: nothing, 0: "no", 2: "inv" in front of name char_u nextchar; // next non-white char after option name @@ -1072,7 +1071,7 @@ int do_set(char_u *arg, int opt_flags) nextchar = arg[len]; if (opt_idx == -1 && key == 0) { // found a mismatch: skip - errmsg = (char_u *)N_("E518: Unknown option"); + errmsg = N_("E518: Unknown option"); goto skip; } @@ -1083,7 +1082,7 @@ int do_set(char_u *arg, int opt_flags) if (vim_strchr((char_u *)"=:!&<", nextchar) == NULL && (!(options[opt_idx].flags & P_BOOL) || nextchar == '?')) { - errmsg = (char_u *)_(e_unsupportedoption); + errmsg = _(e_unsupportedoption); } goto skip; } @@ -1110,11 +1109,11 @@ int do_set(char_u *arg, int opt_flags) // Disallow changing some options from modelines. if (opt_flags & OPT_MODELINE) { if (flags & (P_SECURE | P_NO_ML)) { - errmsg = (char_u *)N_("E520: Not allowed in a modeline"); + errmsg = N_("E520: Not allowed in a modeline"); goto skip; } if ((flags & P_MLE) && !p_mle) { - errmsg = (char_u *)N_("E992: Not allowed in a modeline when 'modelineexpr' is off"); + errmsg = N_("E992: Not allowed in a modeline when 'modelineexpr' is off"); goto skip; } // In diff mode some options are overruled. This avoids that @@ -1182,7 +1181,7 @@ int do_set(char_u *arg, int opt_flags) } } } else { - errmsg = (char_u *)N_("E846: Key code not set"); + errmsg = N_("E846: Key code not set"); goto skip; } if (nextchar != '?' @@ -1233,7 +1232,7 @@ int do_set(char_u *arg, int opt_flags) } } - errmsg = (char_u *)set_bool_option(opt_idx, varp, (int)value, + errmsg = set_bool_option(opt_idx, varp, (int)value, opt_flags); } else { // Numeric or string. if (vim_strchr((const char_u *)"=:&<", nextchar) == NULL @@ -1276,11 +1275,11 @@ int do_set(char_u *arg, int opt_flags) // Allow negative, octal and hex numbers. vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true); if (i == 0 || (arg[i] != NUL && !ascii_iswhite(arg[i]))) { - errmsg = (char_u *)N_("E521: Number required after ="); + errmsg = N_("E521: Number required after ="); goto skip; } } else { - errmsg = (char_u *)N_("E521: Number required after ="); + errmsg = N_("E521: Number required after ="); goto skip; } @@ -1293,9 +1292,9 @@ int do_set(char_u *arg, int opt_flags) if (removing) { value = *(long *)varp - value; } - errmsg = (char_u *)set_num_option(opt_idx, varp, (long)value, - errbuf, sizeof(errbuf), - opt_flags); + errmsg = 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; @@ -1308,16 +1307,16 @@ int do_set(char_u *arg, int opt_flags) int comma; bool new_value_alloced = false; // new string option was allocated - /* When using ":set opt=val" for a global option - * with a local value the local value will be - * reset, use the global value here. */ + // When using ":set opt=val" for a global option + // with a local value the local value will be + // reset, use the global value here. if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 && ((int)options[opt_idx].indir & PV_BOTH)) { varp = options[opt_idx].var; } - /* The old value is kept until we are sure that the - * new value is valid. */ + // The old value is kept until we are sure that the + // new value is valid. oldval = *(char_u **)varp; // When setting the local value of a global @@ -1362,7 +1361,7 @@ int do_set(char_u *arg, int opt_flags) && (*arg == NUL || *arg == ' ')) { STRCPY(errbuf, ":help"); save_arg = arg; - arg = errbuf; + arg = (char_u *)errbuf; } /* * Convert 'backspace' number to string, for @@ -1416,7 +1415,7 @@ int do_set(char_u *arg, int opt_flags) STRLCAT(errbuf, "[,],", sizeof(errbuf)); } save_arg = arg; - arg = errbuf; + arg = (char_u *)errbuf; } /* * Remove '>' before 'dir' and 'bdir', for @@ -1493,8 +1492,8 @@ int do_set(char_u *arg, int opt_flags) } } - /* locate newval[] in origval[] when removing it - * and when adding to avoid duplicates */ + // locate newval[] in origval[] when removing it + // and when adding to avoid duplicates i = 0; // init for GCC if (removing || (flags & P_NODUP)) { i = (int)STRLEN(newval); @@ -1691,7 +1690,7 @@ skip: trans_characters(IObuff, IOSIZE); no_wait_return++; // wait_return done later - emsg(IObuff); // show error highlighted + emsg((char *)IObuff); // show error highlighted no_wait_return--; return FAIL; @@ -1724,9 +1723,9 @@ static void did_set_option(int opt_idx, int opt_flags, int new_value, int value_ { options[opt_idx].flags |= P_WAS_SET; - /* When an option is set in the sandbox, from a modeline or in secure mode - * set the P_INSECURE flag. Otherwise, if a new value is stored reset the - * flag. */ + // When an option is set in the sandbox, from a modeline or in secure mode + // set the P_INSECURE flag. Otherwise, if a new value is stored reset the + // flag. uint32_t *p = insecure_flag(curwin, opt_idx, opt_flags); if (!value_checked && (secure || sandbox != 0 @@ -1737,10 +1736,10 @@ static void did_set_option(int opt_idx, int opt_flags, int new_value, int value_ } } -static char_u *illegal_char(char_u *errbuf, size_t errbuflen, int c) +static char *illegal_char(char *errbuf, size_t errbuflen, int c) { if (errbuf == NULL) { - return (char_u *)""; + return ""; } vim_snprintf((char *)errbuf, errbuflen, _("E539: Illegal character <%s>"), (char *)transchar(c)); @@ -1762,7 +1761,7 @@ static int string_to_key(char_u *arg) /// Check value of 'cedit' and set cedit_key. /// Returns NULL if value is OK, error message otherwise. -static char_u *check_cedit(void) +static char *check_cedit(void) { int n; @@ -2143,7 +2142,7 @@ void set_string_option_direct(const char *name, int opt_idx, const char_u *val, idx = findoption(name); if (idx < 0) { // Not found (should not happen). internal_error("set_string_option_direct()"); - IEMSG2(_("For option %s"), name); + siemsg(_("For option %s"), name); return; } } @@ -2240,9 +2239,9 @@ static char *set_string_option(const int opt_idx, const char *const value, const char *const saved_newval = xstrdup(s); int value_checked = false; - char *const r = (char *)did_set_string_option(opt_idx, (char_u **)varp, (int)true, - (char_u *)oldval, - NULL, 0, opt_flags, &value_checked); + char *const r = did_set_string_option(opt_idx, (char_u **)varp, (int)true, + (char_u *)oldval, + NULL, 0, opt_flags, &value_checked); if (r == NULL) { did_set_option(opt_idx, opt_flags, true, value_checked); } @@ -2315,11 +2314,11 @@ static bool valid_spellfile(const char_u *val) /// @param errbuflen length of errors buffer /// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL /// @param value_checked value was checked to be safe, no need to set P_INSECURE -static char_u *did_set_string_option(int opt_idx, char_u **varp, bool new_value_alloced, - char_u *oldval, char_u *errbuf, size_t errbuflen, - int opt_flags, int *value_checked) +static char *did_set_string_option(int opt_idx, char_u **varp, bool new_value_alloced, + char_u *oldval, char *errbuf, size_t errbuflen, + int opt_flags, int *value_checked) { - char_u *errmsg = NULL; + char *errmsg = NULL; char_u *s, *p; int did_chartab = false; char_u **gvarp; @@ -2371,7 +2370,7 @@ static char_u *did_set_string_option(int opt_idx, char_u **varp, bool new_value_ } else if (varp == &p_bex || varp == &p_pm) { // 'backupext' and 'patchmode' if (STRCMP(*p_bex == '.' ? p_bex + 1 : p_bex, *p_pm == '.' ? p_pm + 1 : p_pm) == 0) { - errmsg = (char_u *)N_("E589: 'backupext' and 'patchmode' are equal"); + errmsg = N_("E589: 'backupext' and 'patchmode' are equal"); } } else if (varp == &curwin->w_p_briopt) { // 'breakindentopt' if (briopt_check(curwin) == FAIL) { @@ -2459,11 +2458,11 @@ static char_u *did_set_string_option(int opt_idx, char_u **varp, bool new_value_ } else { FOR_ALL_TAB_WINDOWS(tp, wp) { if (set_chars_option(wp, &wp->w_p_lcs, true) != NULL) { - errmsg = (char_u *)_("E834: Conflicts with value of 'listchars'"); + errmsg = _("E834: Conflicts with value of 'listchars'"); goto ambw_end; } if (set_chars_option(wp, &wp->w_p_fcs, true) != NULL) { - errmsg = (char_u *)_("E835: Conflicts with value of 'fillchars'"); + errmsg = _("E835: Conflicts with value of 'fillchars'"); goto ambw_end; } } @@ -2636,9 +2635,9 @@ ambw_end: s++; } if (*s++ == NUL) { - errmsg = (char_u *)N_("E524: Missing colon"); + errmsg = N_("E524: Missing colon"); } else if (*s == ',' || *s == NUL) { - errmsg = (char_u *)N_("E525: Zero length string"); + errmsg = N_("E525: Zero length string"); } if (errmsg != NULL) { break; @@ -2716,7 +2715,7 @@ ambw_end: transchar_byte(*(s - 1))); errmsg = errbuf; } else { - errmsg = (char_u *)""; + errmsg = ""; } break; } @@ -2725,20 +2724,20 @@ ambw_end: s++; } else if (*s) { if (errbuf != NULL) { - errmsg = (char_u *)N_("E527: Missing comma"); + errmsg = N_("E527: Missing comma"); } else { - errmsg = (char_u *)""; + errmsg = ""; } break; } } if (*p_shada && errmsg == NULL && get_shada_parameter('\'') < 0) { - errmsg = (char_u *)N_("E528: Must specify a ' value"); + errmsg = N_("E528: Must specify a ' value"); } } else if (gvarp == &p_sbr) { // 'showbreak' for (s = *varp; *s; ) { if (ptr2cells(s) != 1) { - errmsg = (char_u *)N_("E595: 'showbreak' contains unprintable or wide character"); + errmsg = N_("E595: 'showbreak' contains unprintable or wide character"); } MB_PTR_ADV(s); } @@ -2907,7 +2906,7 @@ ambw_end: *--s); errmsg = errbuf; } else { - errmsg = (char_u *)""; + errmsg = ""; } break; } @@ -2934,7 +2933,7 @@ ambw_end: // When changing the 'signcolumn' to or from 'number', recompute the // width of the number column if 'number' or 'relativenumber' is set. if (((*oldval == 'n' && *(oldval + 1) == 'u') - || (*curwin->w_p_scl == 'n' && *(curwin->w_p_scl + 1) =='u')) + || (*curwin->w_p_scl == 'n' && *(curwin->w_p_scl + 1) == 'u')) && (curwin->w_p_nu || curwin->w_p_rnu)) { curwin->w_nrwidth_line_count = 0; } @@ -3011,7 +3010,7 @@ ambw_end: } else if (gvarp == &curwin->w_allbuf_opt.wo_fmr) { // 'foldmarker' p = vim_strchr(*varp, ','); if (p == NULL) { - errmsg = (char_u *)N_("E536: comma required"); + errmsg = N_("E536: comma required"); } else if (p == *varp || p[1] == NUL) { errmsg = e_invarg; } else if (foldmethodIsMarker(curwin)) { @@ -3019,7 +3018,7 @@ ambw_end: } } else if (gvarp == &p_cms) { // 'commentstring' if (**varp != NUL && strstr((char *)(*varp), "%s") == NULL) { - errmsg = (char_u *)N_("E537: 'commentstring' must be empty or contain %s"); + errmsg = N_("E537: 'commentstring' must be empty or contain %s"); } } else if (varp == &p_fdo) { // 'foldopen' if (opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, true) != OK) { @@ -3344,7 +3343,7 @@ int check_signcolumn(char_u *val) /// Handle setting 'colorcolumn' or 'textwidth' in window "wp". /// /// @return error message, NULL if it's OK. -char_u *check_colorcolumn(win_T *wp) +char *check_colorcolumn(win_T *wp) { char_u *s; int col; @@ -3429,7 +3428,7 @@ void check_blending(win_T *wp) /// /// @param varp either &curwin->w_p_lcs or &curwin->w_p_fcs /// @return error message, NULL if it's OK. -static char_u *set_chars_option(win_T *wp, char_u **varp, bool set) +static char *set_chars_option(win_T *wp, char_u **varp, bool set) { int round, i, len, entries; char_u *p, *s; @@ -3531,7 +3530,7 @@ static char_u *set_chars_option(win_T *wp, char_u **varp, bool set) // TODO(bfredl): use schar_T representation and utfc_ptr2len int c1len = utf_ptr2len(s); c1 = mb_cptr2char_adv((const char_u **)&s); - if (mb_char2cells(c1) > 1 || (c1len == 1 && c1 > 127)) { + if (utf_char2cells(c1) > 1 || (c1len == 1 && c1 > 127)) { return e_invarg; } if (tab[i].cp == &wp->w_p_lcs_chars.tab2) { @@ -3540,13 +3539,13 @@ static char_u *set_chars_option(win_T *wp, char_u **varp, bool set) } int c2len = utf_ptr2len(s); c2 = mb_cptr2char_adv((const char_u **)&s); - if (mb_char2cells(c2) > 1 || (c2len == 1 && c2 > 127)) { + if (utf_char2cells(c2) > 1 || (c2len == 1 && c2 > 127)) { return e_invarg; } if (!(*s == ',' || *s == NUL)) { int c3len = utf_ptr2len(s); c3 = mb_cptr2char_adv((const char_u **)&s); - if (mb_char2cells(c3) > 1 || (c3len == 1 && c3 > 127)) { + if (utf_char2cells(c3) > 1 || (c3len == 1 && c3 > 127)) { return e_invarg; } } @@ -3581,7 +3580,7 @@ static char_u *set_chars_option(win_T *wp, char_u **varp, bool set) while (*s != NUL && *s != ',') { int c1len = utf_ptr2len(s); c1 = mb_cptr2char_adv((const char_u **)&s); - if (mb_char2cells(c1) > 1 || (c1len == 1 && c1 > 127)) { + if (utf_char2cells(c1) > 1 || (c1len == 1 && c1 > 127)) { return e_invarg; } multispace_len++; @@ -3616,10 +3615,10 @@ static char_u *set_chars_option(win_T *wp, char_u **varp, bool set) /// Check validity of options with the 'statusline' format. /// Return error message or NULL. -char_u *check_stl_option(char_u *s) +char *check_stl_option(char_u *s) { int groupdepth = 0; - static char_u errbuf[80]; + static char errbuf[80]; while (*s) { // Check for valid keys after % sequences @@ -3670,19 +3669,19 @@ char_u *check_stl_option(char_u *s) s++; } if (*s != '}') { - return (char_u *)N_("E540: Unclosed expression sequence"); + return N_("E540: Unclosed expression sequence"); } } } if (groupdepth != 0) { - return (char_u *)N_("E542: unbalanced groups"); + return N_("E542: unbalanced groups"); } return NULL; } -static char_u *did_set_spell_option(bool is_spellfile) +static char *did_set_spell_option(bool is_spellfile) { - char_u *errmsg = NULL; + char *errmsg = NULL; if (is_spellfile) { int l = (int)STRLEN(curwin->w_s->b_p_spf); @@ -3706,7 +3705,7 @@ static char_u *did_set_spell_option(bool is_spellfile) /// Set curbuf->b_cap_prog to the regexp program for 'spellcapcheck'. /// Return error message when failed, NULL when OK. -static char_u *compile_cap_prog(synblock_T *synblock) +static char *compile_cap_prog(synblock_T *synblock) FUNC_ATTR_NONNULL_ALL { regprog_T *rp = synblock->b_cap_prog; @@ -3833,7 +3832,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va // 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 (char *)e_unsupportedoption; + return 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; @@ -4019,9 +4018,9 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va } } else if ((int *)varp == &curwin->w_p_spell) { // 'spell' if (curwin->w_p_spell) { - char_u *errmsg = did_set_spelllang(curwin); + char *errmsg = did_set_spelllang(curwin); if (errmsg != NULL) { - EMSG(_(errmsg)); + emsg(_(errmsg)); } } } @@ -4138,10 +4137,10 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va /// @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, +static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf, size_t errbuflen, int opt_flags) { - char_u *errmsg = NULL; + char *errmsg = NULL; long old_value = *(long *)varp; long old_Rows = Rows; // remember old Rows long *pp = (long *)varp; @@ -4149,12 +4148,12 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char_u *errbu // Disallow changing some options from secure mode. if ((secure || sandbox != 0) && (options[opt_idx].flags & P_SECURE)) { - return (char *)e_secure; + return e_secure; } // Many number options assume their value is in the signed int range. if (value < INT_MIN || value > INT_MAX) { - return (char *)e_invarg; + return e_invarg; } // Options that need some validation. @@ -4923,12 +4922,12 @@ char *set_option_value(const char *const name, const long number, const char *co opt_idx = findoption(name); if (opt_idx < 0) { - EMSG2(_("E355: Unknown option: %s"), name); + semsg(_("E355: Unknown option: %s"), name); } else { uint32_t flags = options[opt_idx].flags; // Disallow changing some options in the sandbox if (sandbox > 0 && (flags & P_SECURE)) { - EMSG(_(e_sandbox)); + emsg(_(e_sandbox)); return NULL; } if (flags & P_STRING) { @@ -4950,7 +4949,7 @@ char *set_option_value(const char *const name, const long number, const char *co // 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. - EMSG3(_("E521: Number required: &%s = '%s'"), + semsg(_("E521: Number required: &%s = '%s'"), name, string); return NULL; // do nothing as we hit an error } @@ -5018,11 +5017,11 @@ static void showoptions(int all, int opt_flags) // Highlight title if (opt_flags & OPT_GLOBAL) { - MSG_PUTS_TITLE(_("\n--- Global option values ---")); + msg_puts_title(_("\n--- Global option values ---")); } else if (opt_flags & OPT_LOCAL) { - MSG_PUTS_TITLE(_("\n--- Local option values ---")); + msg_puts_title(_("\n--- Local option values ---")); } else { - MSG_PUTS_TITLE(_("\n--- Options ---")); + msg_puts_title(_("\n--- Options ---")); } // Do the loop two times: @@ -5153,13 +5152,13 @@ static void showoneopt(vimoption_T *p, int opt_flags) // for 'modified' we also need to check if 'ff' or 'fenc' changed. if ((p->flags & P_BOOL) && ((int *)varp == &curbuf->b_changed ? !curbufIsChanged() : !*(int *)varp)) { - MSG_PUTS("no"); + msg_puts("no"); } else if ((p->flags & P_BOOL) && *(int *)varp < 0) { - MSG_PUTS("--"); + msg_puts("--"); } else { - MSG_PUTS(" "); + msg_puts(" "); } - MSG_PUTS(p->fullname); + msg_puts(p->fullname); if (!(p->flags & P_BOOL)) { msg_putchar('='); // put value string in NameBuff @@ -5260,8 +5259,8 @@ int makeset(FILE *fd, int opt_flags, int local_only) } } - /* Round 1: fresh value for window-local options. - * Round 2: other values */ + // Round 1: fresh value for window-local options. + // Round 2: other values for (; round <= 2; varp = varp_local, round++) { if (round == 1 || (opt_flags & OPT_GLOBAL)) { cmd = "set"; @@ -5360,7 +5359,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, uint6 home_replace(NULL, *valuep, buf, size, false); // If the option value is longer than MAXPATHL, we need to append - // search comma separated part of the option separately, so that it + // each comma separated part of the option separately, so that it // can be expanded when read back. if (size >= MAXPATHL && (flags & P_COMMA) != 0 && vim_strchr(*valuep, ',') != NULL) { @@ -5489,7 +5488,7 @@ void unset_global_local_option(char *name, void *from) int opt_idx = findoption(name); if (opt_idx < 0) { - EMSG2(_("E355: Unknown option: %s"), name); + semsg(_("E355: Unknown option: %s"), name); return; } p = &(options[opt_idx]); @@ -5945,7 +5944,7 @@ static char_u *get_varp(vimoption_T *p) case PV_WINBL: return (char_u *)&(curwin->w_p_winbl); default: - IEMSG(_("E356: get_varp ERROR")); + iemsg(_("E356: get_varp ERROR")); } // always return a valid pointer to avoid a crash! return (char_u *)&(curbuf->b_p_wm); @@ -6238,13 +6237,13 @@ void buf_copy_options(buf_T *buf, int flags) buf->b_p_sua = vim_strsave(p_sua); buf->b_p_keymap = vim_strsave(p_keymap); buf->b_kmap_state |= KEYMAP_INIT; - /* This isn't really an option, but copying the langmap and IME - * state from the current buffer is better than resetting it. */ + // This isn't really an option, but copying the langmap and IME + // state from the current buffer is better than resetting it. buf->b_p_iminsert = p_iminsert; buf->b_p_imsearch = p_imsearch; - /* options that are normally global but also have a local value - * are not copied, start using the global value */ + // options that are normally global but also have a local value + // are not copied, start using the global value buf->b_p_ar = -1; buf->b_p_ul = NO_LOCAL_UNDOLEVEL; buf->b_p_bkc = empty_option; @@ -6496,8 +6495,8 @@ void set_context_in_set_cmd(expand_T *xp, char_u *arg, int opt_flags) } } - /* For an option that is a list of file names, find the start of the - * last file name. */ + // For an option that is a list of file names, find the start of the + // last file name. for (p = arg + STRLEN(arg) - 1; p > xp->xp_pattern; p--) { // count number of backslashes before ' ' or ',' if (*p == ' ' || *p == ',') { @@ -6531,10 +6530,9 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u *** 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 - * loop == 1: copy the matching options into allocated memory - */ + // do this loop twice: + // loop == 0: count the number of matching options + // loop == 1: copy the matching options into allocated memory for (loop = 0; loop <= 1; loop++) { regmatch->rm_ic = ic; if (xp->xp_context != EXPAND_BOOL_SETTINGS) { @@ -6820,7 +6818,7 @@ static void langmap_set(void) } } if (to == NUL) { - EMSG2(_("E357: 'langmap': Matching character missing for %s"), + semsg(_("E357: 'langmap': Matching character missing for %s"), transchar(from)); return; } @@ -6840,7 +6838,7 @@ static void langmap_set(void) p = p2; if (p[0] != NUL) { if (p[0] != ',') { - EMSG2(_("E358: 'langmap': Extra characters after semicolon: %s"), + semsg(_("E358: 'langmap': Extra characters after semicolon: %s"), p); return; } @@ -7317,9 +7315,9 @@ bool tabstop_set(char_u *var, long **array) if (strtol((char *)cp, (char **)&end, 10) <= 0) { if (cp != end) { - EMSG(_(e_positive)); + emsg(_(e_positive)); } else { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } return false; } @@ -7332,7 +7330,7 @@ bool tabstop_set(char_u *var, long **array) valcount++; continue; } - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return false; } @@ -7342,7 +7340,7 @@ bool tabstop_set(char_u *var, long **array) t = 1; for (cp = var; *cp != NUL;) { (*array)[t++] = atoi((char *)cp); - while (*cp != NUL && *cp != ',') { + while (*cp != NUL && *cp != ',') { cp++; } if (*cp != NUL) { diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index 358bfc20dc..19cb33a354 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -838,7 +838,7 @@ enum { BV_WM, BV_VSTS, BV_VTS, - BV_COUNT // must be the last one + BV_COUNT, // must be the last one }; /* @@ -891,7 +891,7 @@ enum { WV_FCS, WV_LCS, WV_WINBL, - WV_COUNT // must be the last one + WV_COUNT, // must be the last one }; // Value for b_p_ul indicating the global value must be used. diff --git a/src/nvim/os/dl.c b/src/nvim/os/dl.c index b2e3994d10..7d095d31e3 100644 --- a/src/nvim/os/dl.c +++ b/src/nvim/os/dl.c @@ -49,7 +49,7 @@ bool os_libcall(const char *libname, const char *funcname, const char *argv, int // open the dynamic loadable library if (uv_dlopen(libname, &lib)) { - EMSG2(_("dlerror = \"%s\""), uv_dlerror(&lib)); + semsg(_("dlerror = \"%s\""), uv_dlerror(&lib)); uv_dlclose(&lib); return false; } @@ -57,7 +57,7 @@ bool os_libcall(const char *libname, const char *funcname, const char *argv, int // find and load the requested function in the library gen_fn fn; if (uv_dlsym(&lib, funcname, (void **)&fn)) { - EMSG2(_("dlerror = \"%s\""), uv_dlerror(&lib)); + semsg(_("dlerror = \"%s\""), uv_dlerror(&lib)); uv_dlclose(&lib); return false; } diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index 0f363ecfc3..727b10f7a7 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -250,7 +250,7 @@ void os_copy_fullenv(char **env, size_t env_size) char *utf8_str; int conversion_result = utf16_to_utf8(p, -1, &utf8_str); if (conversion_result != 0) { - EMSG2("utf16_to_utf8 failed: %d", conversion_result); + semsg("utf16_to_utf8 failed: %d", conversion_result); break; } p += l + 1; @@ -297,7 +297,7 @@ char *os_getenvname_at_index(size_t index) char *utf8_str; int conversion_result = utf16_to_utf8(p, -1, &utf8_str); if (conversion_result != 0) { - EMSG2("utf16_to_utf8 failed: %d", conversion_result); + semsg("utf16_to_utf8 failed: %d", conversion_result); break; } @@ -375,7 +375,7 @@ void os_get_hostname(char *hostname, size_t size) if (GetComputerNameW(host_utf16, &host_wsize) == 0) { *hostname = '\0'; DWORD err = GetLastError(); - EMSG2("GetComputerNameW failed: %d", err); + semsg("GetComputerNameW failed: %d", err); return; } host_utf16[host_wsize] = '\0'; @@ -383,13 +383,13 @@ void os_get_hostname(char *hostname, size_t size) char *host_utf8; int conversion_result = utf16_to_utf8(host_utf16, -1, &host_utf8); if (conversion_result != 0) { - EMSG2("utf16_to_utf8 failed: %d", conversion_result); + semsg("utf16_to_utf8 failed: %d", conversion_result); return; } xstrlcpy(hostname, host_utf8, size); xfree(host_utf8); #else - EMSG("os_get_hostname failed: missing uname()"); + emsg("os_get_hostname failed: missing uname()"); *hostname = '\0'; #endif } @@ -481,7 +481,7 @@ void init_homedir(void) var = (char *)IObuff; } if (os_chdir(os_buf) != 0) { - EMSG(_(e_prev_dir)); + emsg(_(e_prev_dir)); } } } diff --git a/src/nvim/os/fileio.c b/src/nvim/os/fileio.c index 1ae6ca4244..b1710737d0 100644 --- a/src/nvim/os/fileio.c +++ b/src/nvim/os/fileio.c @@ -426,6 +426,6 @@ int msgpack_file_write(void *data, const char *buf, size_t len) /// @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)); + semsg(_("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 7c53cd4f07..426dc422c2 100644 --- a/src/nvim/os/fileio.h +++ b/src/nvim/os/fileio.h @@ -68,7 +68,7 @@ enum { /// Read or write buffer size /// /// Currently equal to (IOSIZE - 1), but they do not need to be connected. - kRWBufferSize = 1024 + kRWBufferSize = 1024, }; #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 9675cfbb0f..3ff13c2b3f 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -1212,7 +1212,7 @@ char *os_resolve_shortcut(const char *fname) wchar_t *p; const int r = utf8_to_utf16(fname, -1, &p); if (r != 0) { - EMSG2("utf8_to_utf16 failed: %d", r); + semsg("utf8_to_utf16 failed: %d", r); } else if (p != NULL) { // Get a pointer to the IPersistFile interface. hr = pslw->lpVtbl->QueryInterface(pslw, &IID_IPersistFile, (void **)&ppf); @@ -1239,7 +1239,7 @@ char *os_resolve_shortcut(const char *fname) if (hr == S_OK && wsz[0] != NUL) { const int r2 = utf16_to_utf8(wsz, -1, &rfname); if (r2 != 0) { - EMSG2("utf16_to_utf8 failed: %d", r2); + semsg("utf16_to_utf8 failed: %d", r2); } } @@ -1274,7 +1274,7 @@ bool os_is_reparse_point_include(const char *path) const int r = utf8_to_utf16(path, -1, &utf16_path); if (r != 0) { - EMSG2("utf8_to_utf16 failed: %d", r); + semsg("utf8_to_utf16 failed: %d", r); return false; } diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index 4c6e9ee4d3..5b231f205b 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -30,7 +30,7 @@ typedef enum { kInputNone, kInputAvail, - kInputEof + kInputEof, } InbufPollResult; static Stream read_stream = { .closed = true }; // Input before UI starts. @@ -401,7 +401,7 @@ static InbufPollResult inbuf_poll(int ms, MultiQueue *events) prof_inchar_enter(); } - if ((ms == - 1 || ms > 0) && events != main_loop.events && !input_eof) { + if ((ms == -1 || ms > 0) && events != main_loop.events && !input_eof) { // The pending input provoked a blocking wait. Do special events now. #6247 blocking = true; multiqueue_process_events(ch_before_blocking_events); diff --git a/src/nvim/os/pty_conpty_win.c b/src/nvim/os/pty_conpty_win.c index 0625d6994e..f9478d951f 100644 --- a/src/nvim/os/pty_conpty_win.c +++ b/src/nvim/os/pty_conpty_win.c @@ -96,7 +96,7 @@ conpty_t *os_conpty_init(char **in_name, char **out_name, uint16_t width, uint16 goto failed; } assert(width <= SHRT_MAX); - assert(height <= SHRT_MAX); + assert(height <= SHRT_MAX); COORD size = { (int16_t)width, (int16_t)height }; HRESULT hr; hr = pCreatePseudoConsole(size, in_read, out_write, 0, &conpty_object->pty); @@ -107,7 +107,7 @@ conpty_t *os_conpty_init(char **in_name, char **out_name, uint16_t width, uint16 conpty_object->si_ex.StartupInfo.cb = sizeof(conpty_object->si_ex); size_t bytes_required; - InitializeProcThreadAttributeList(NULL, 1, 0, & bytes_required); + InitializeProcThreadAttributeList(NULL, 1, 0, &bytes_required); conpty_object->si_ex.lpAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)xmalloc(bytes_required); if (!InitializeProcThreadAttributeList(conpty_object->si_ex.lpAttributeList, diff --git a/src/nvim/os/pty_process_win.h b/src/nvim/os/pty_process_win.h index 3f6cc58e3e..d1737fd63a 100644 --- a/src/nvim/os/pty_process_win.h +++ b/src/nvim/os/pty_process_win.h @@ -10,7 +10,7 @@ typedef enum { kWinpty, - kConpty + kConpty, } PtyType; typedef struct pty_process { diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 2bff65b241..6ef0aa1091 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -159,7 +159,7 @@ int os_expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file // get a name for the temp file if ((tempname = vim_tempname()) == NULL) { - EMSG(_(e_notmp)); + emsg(_(e_notmp)); return FAIL; } @@ -341,7 +341,7 @@ int os_expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file if (!(flags & EW_SILENT)) { msg_putchar('\n'); // clear bottom line quickly cmdline_row = Rows - 1; // continue on last line - MSG(_(e_wildexpand)); + msg(_(e_wildexpand)); msg_start(); // don't overwrite this message } @@ -358,7 +358,7 @@ int os_expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file if (fd == NULL) { // Something went wrong, perhaps a file name with a special char. if (!(flags & EW_SILENT)) { - MSG(_(e_wildexpand)); + msg(_(e_wildexpand)); msg_start(); // don't overwrite this message } xfree(tempname); @@ -389,7 +389,7 @@ int os_expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file os_remove((char *)tempname); if (readlen != len) { // unexpected read error - EMSG2(_(e_notread), tempname); + semsg(_(e_notread), tempname); xfree(tempname); xfree(buffer); return FAIL; @@ -670,7 +670,7 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args) } if (!emsg_silent && exitcode != 0 && !(opts & kShellOptSilent)) { - MSG_PUTS(_("\nshell returned ")); + msg_puts(_("\nshell returned ")); msg_outnum(exitcode); msg_putchar('\n'); } @@ -742,9 +742,9 @@ static int do_os_system(char **argv, const char *input, size_t len, char **outpu loop_poll_events(&main_loop, 0); // Failed, probably 'shell' is not executable. if (!silent) { - MSG_PUTS(_("\nshell failed to start: ")); + msg_puts(_("\nshell failed to start: ")); msg_outtrans((char_u *)os_strerror(status)); - MSG_PUTS(": "); + msg_puts(": "); msg_outtrans((char_u *)prog); msg_putchar('\n'); } @@ -1180,7 +1180,7 @@ static void shell_write_cb(Stream *stream, void *data, int status) if (status) { // Can happen if system() tries to send input to a shell command that was // backgrounded (:call system("cat - &", "foo")). #3529 #5241 - msg_schedule_emsgf(_("E5677: Error writing input to shell-command: %s"), + msg_schedule_semsg(_("E5677: Error writing input to shell-command: %s"), uv_err_name(status)); } stream_close(stream, NULL, NULL); diff --git a/src/nvim/os/users.c b/src/nvim/os/users.c index fd7ead68da..9952e2b387 100644 --- a/src/nvim/os/users.c +++ b/src/nvim/os/users.c @@ -64,7 +64,7 @@ int os_get_usernames(garray_T *users) char *user; int conversion_result = utf16_to_utf8(uinfo[i].usri0_name, -1, &user); if (conversion_result != 0) { - EMSG2("utf16_to_utf8 failed: %d", conversion_result); + semsg("utf16_to_utf8 failed: %d", conversion_result); break; } add_user(users, user, false); diff --git a/src/nvim/path.c b/src/nvim/path.c index 5b1793b111..1085f7a10c 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -359,8 +359,8 @@ int path_fnamencmp(const char *const fname1, const char *const fname2, size_t le const char *p1 = fname1; const char *p2 = fname2; while (len > 0) { - c1 = PTR2CHAR((const char_u *)p1); - c2 = PTR2CHAR((const char_u *)p2); + c1 = utf_ptr2char((const char_u *)p1); + c2 = utf_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)) { @@ -631,7 +631,7 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff, && (vim_strchr((char_u *)"*?[{~$", *path_end) != NULL #ifndef WIN32 || (!p_fic && (flags & EW_ICASE) - && isalpha(PTR2CHAR(path_end))) + && isalpha(utf_ptr2char(path_end))) #endif )) { e = p; @@ -1011,8 +1011,7 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern) // /file.txt / /file.txt // c:\file.txt c:\ .\file.txt short_name = path_shorten_fname(path, curdir); - if (short_name != NULL && short_name > path + 1 - ) { + if (short_name != NULL && short_name > path + 1) { STRCPY(path, "."); add_pathsep((char *)path); STRMOVE(path + STRLEN(path), short_name); @@ -1506,8 +1505,9 @@ void simplify_filename(char_u *filename) if (vim_ispathsep(*p)) { relative = false; - do + do{ ++p; + } while (vim_ispathsep(*p)); } start = p; // remember start after "c:/" or "/" or "///" @@ -1701,7 +1701,7 @@ char_u *find_file_name_in_path(char_u *ptr, size_t len, int options, long count, if (file_name == NULL && (options & FNAME_MESS)) { char_u c = ptr[len]; ptr[len] = NUL; - EMSG2(_("E447: Can't find file \"%s\" in path"), ptr); + semsg(_("E447: Can't find file \"%s\" in path"), ptr); ptr[len] = c; } @@ -1937,8 +1937,8 @@ int pathcmp(const char *p, const char *q, int maxlen) const char *s = NULL; for (i = 0, j = 0; maxlen < 0 || (i < maxlen && j < maxlen);) { - c1 = PTR2CHAR((char_u *)p + i); - c2 = PTR2CHAR((char_u *)q + j); + c1 = utf_ptr2char((char_u *)p + i); + c2 = utf_ptr2char((char_u *)q + j); // End of "p": check if "q" also ends or just has a slash. if (c1 == NUL) { @@ -1980,8 +1980,8 @@ int pathcmp(const char *p, const char *q, int maxlen) return 0; } - c1 = PTR2CHAR((char_u *)s + i); - c2 = PTR2CHAR((char_u *)s + i + utfc_ptr2len((char_u *)s + i)); + c1 = utf_ptr2char((char_u *)s + i); + c2 = utf_ptr2char((char_u *)s + i + utfc_ptr2len((char_u *)s + i)); // ignore a trailing slash, but not "//" or ":/" if (c2 == NUL && i > 0 @@ -2081,7 +2081,7 @@ int expand_wildcards_eval(char_u **pat, int *num_file, char_u ***file, int flags int ret = FAIL; char_u *eval_pat = NULL; char_u *exp_pat = *pat; - char_u *ignored_msg; + char *ignored_msg; size_t usedlen; if (*exp_pat == '%' || *exp_pat == '#' || *exp_pat == '<') { @@ -2257,7 +2257,7 @@ int path_full_dir_name(char *directory, char *buffer, size_t len) if (os_chdir(old_dir) != SUCCESS) { // That shouldn't happen, since we've tested if it works. retval = FAIL; - EMSG(_(e_prev_dir)); + emsg(_(e_prev_dir)); } return retval; diff --git a/src/nvim/path.h b/src/nvim/path.h index 5d81e68caa..1006ef9ffb 100644 --- a/src/nvim/path.h +++ b/src/nvim/path.h @@ -33,7 +33,7 @@ typedef enum file_comparison { kDifferentFiles = 2, ///< Both exist and are different files. kBothFilesMissing = 4, ///< Both don't exist. kOneFileMissing = 6, ///< One of them doesn't exist. - kEqualFileNames = 7 ///< Both don't exist and file names are same. + kEqualFileNames = 7, ///< Both don't exist and file names are same. } FileComparison; #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/plines.c b/src/nvim/plines.c index 5b0418ed92..a061f76f34 100644 --- a/src/nvim/plines.c +++ b/src/nvim/plines.c @@ -54,7 +54,7 @@ int plines_win(win_T *wp, linenr_T lnum, bool winheight) /// @return Number of filler lines above lnum int win_get_fill(win_T *wp, linenr_T lnum) { - int virt_lines = decor_virtual_lines(wp, lnum); + int virt_lines = decor_virt_lines(wp, lnum, NULL); // be quick when there are no filler lines if (diffopt_filler()) { @@ -69,7 +69,7 @@ int win_get_fill(win_T *wp, linenr_T lnum) bool win_may_fill(win_T *wp) { - return (wp->w_p_diff && diffopt_filler()) || wp->w_buffer->b_virt_line_mark; + return (wp->w_p_diff && diffopt_filler()) || wp->w_buffer->b_virt_line_blocks; } /// @param winheight when true limit to window height @@ -424,7 +424,7 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he col %= numberextra; } if (*sbr != NUL) { - sbrlen = (colnr_T)MB_CHARLEN(sbr); + sbrlen = (colnr_T)mb_charlen(sbr); if (col >= sbrlen) { col -= sbrlen; } diff --git a/src/nvim/po/da.po b/src/nvim/po/da.po index 23d60087f2..dfcc052288 100644 --- a/src/nvim/po/da.po +++ b/src/nvim/po/da.po @@ -5720,9 +5720,6 @@ msgstr "" "\n" "--- Terminal-taster ---" -msgid "Cannot open $VIMRUNTIME/rgb.txt" -msgstr "Kan ikke åbne $VIMRUNTIME/rgb.txt" - #, c-format msgid "Kill job in \"%s\"?" msgstr "Dræb job i \"%s\"?" diff --git a/src/nvim/po/ga.po b/src/nvim/po/ga.po index abbb9c6583..ff16a87dbc 100644 --- a/src/nvim/po/ga.po +++ b/src/nvim/po/ga.po @@ -5793,9 +5793,6 @@ msgstr "" "\n" "--- Eochracha teirminil ---" -msgid "Cannot open $VIMRUNTIME/rgb.txt" -msgstr "N fidir $VIMRUNTIME/rgb.txt a oscailt" - msgid "new shell started\n" msgstr "tosaodh blaosc nua\n" diff --git a/src/nvim/po/tr.po b/src/nvim/po/tr.po index e1fef00863..ac96b8b3e4 100644 --- a/src/nvim/po/tr.po +++ b/src/nvim/po/tr.po @@ -5563,9 +5563,6 @@ msgstr "" "\n" "--- Uçbirim düğmeleri ---" -msgid "Cannot open $VIMRUNTIME/rgb.txt" -msgstr "$VIMRUNTIME/rgb.txt açılamıyor" - #, c-format msgid "E181: Invalid attribute: %s" msgstr "E181: Geçersiz öznitelik: %s" diff --git a/src/nvim/pos.h b/src/nvim/pos.h index 2fbd049aa0..d17e27906e 100644 --- a/src/nvim/pos.h +++ b/src/nvim/pos.h @@ -14,13 +14,13 @@ typedef int colnr_T; #define PRIdCOLNR "d" /// Maximal (invalid) line number -enum { MAXLNUM = 0x7fffffff }; +enum { MAXLNUM = 0x7fffffff, }; /// Maximal column number -enum { MAXCOL = INT_MAX }; +enum { MAXCOL = INT_MAX, }; // Minimum line number -enum { MINLNUM = 1 }; +enum { MINLNUM = 1, }; // minimum column number -enum { MINCOL = 1 }; +enum { MINCOL = 1, }; /* * position in file or buffer diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 53be2c04e2..950d187ad5 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -82,7 +82,7 @@ typedef enum { QFLT_QUICKFIX, ///< Quickfix list - global list QFLT_LOCATION, ///< Location list - per window list - QFLT_INTERNAL ///< Internal - Temporary list used by + QFLT_INTERNAL, ///< Internal - Temporary list used by // getqflist()/getloclist() } qfltype_T; @@ -322,8 +322,7 @@ int qf_init(win_T *wp, const char_u *restrict efile, char_u *restrict errorforma // Maximum number of bytes allowed per line while reading an errorfile. static const size_t LINE_MAXLEN = 4096; -static struct fmtpattern -{ +static struct fmtpattern { char_u convchar; char *pattern; } fmt_pat[FMT_PATTERNS] = @@ -346,23 +345,19 @@ static struct fmtpattern /// pattern specifier is supplied in "efmpat". The converted pattern is stored /// in "regpat". Returns a pointer to the location after the pattern. static char_u *efmpat_to_regpat(const char_u *efmpat, char_u *regpat, efm_T *efminfo, int idx, - int round, char_u *errmsg, size_t errmsglen) + int round) FUNC_ATTR_NONNULL_ALL { if (efminfo->addr[idx]) { // Each errorformat pattern can occur only once - snprintf((char *)errmsg, errmsglen, - _("E372: Too many %%%c in format string"), *efmpat); - EMSG(errmsg); + semsg(_("E372: Too many %%%c in format string"), *efmpat); return NULL; } if ((idx && idx < 6 && vim_strchr((char_u *)"DXOPQ", efminfo->prefix) != NULL) || (idx == 6 && vim_strchr((char_u *)"OPQ", efminfo->prefix) == NULL)) { - snprintf((char *)errmsg, errmsglen, - _("E373: Unexpected %%%c in format string"), *efmpat); - EMSG(errmsg); + semsg(_("E373: Unexpected %%%c in format string"), *efmpat); return NULL; } efminfo->addr[idx] = (char_u)++ round; @@ -406,8 +401,7 @@ static char_u *efmpat_to_regpat(const char_u *efmpat, char_u *regpat, efm_T *efm /// Convert a scanf like format in 'errorformat' to a regular expression. /// Returns a pointer to the location after the pattern. -static char_u *scanf_fmt_to_regpat(const char_u **pefmp, const char_u *efm, int len, char_u *regpat, - char_u *errmsg, size_t errmsglen) +static char_u *scanf_fmt_to_regpat(const char_u **pefmp, const char_u *efm, int len, char_u *regpat) FUNC_ATTR_NONNULL_ALL { const char_u *efmp = *pefmp; @@ -422,7 +416,7 @@ static char_u *scanf_fmt_to_regpat(const char_u **pefmp, const char_u *efm, int while (efmp < efm + len && (*regpat++ = *++efmp) != ']') { } if (efmp == efm + len) { - EMSG(_("E374: Missing ] in format string")); + emsg(_("E374: Missing ] in format string")); return NULL; } } @@ -432,10 +426,7 @@ static char_u *scanf_fmt_to_regpat(const char_u **pefmp, const char_u *efm, int *regpat++ = '\\'; *regpat++ = '+'; } else { - // TODO(vim): scanf()-like: %*ud, %*3c, %*f, ... ? - snprintf((char *)errmsg, errmsglen, - _("E375: Unsupported %%%c in format string"), *efmp); - EMSG(errmsg); + semsg(_("E375: Unsupported %%%c in format string"), *efmp); return NULL; } @@ -445,8 +436,7 @@ static char_u *scanf_fmt_to_regpat(const char_u **pefmp, const char_u *efm, int } /// Analyze/parse an errorformat prefix. -static const char_u *efm_analyze_prefix(const char_u *efmp, efm_T *efminfo, char_u *errmsg, - size_t errmsglen) +static const char_u *efm_analyze_prefix(const char_u *efmp, efm_T *efminfo) FUNC_ATTR_NONNULL_ALL { if (vim_strchr((char_u *)"+-", *efmp) != NULL) { @@ -455,9 +445,7 @@ static const char_u *efm_analyze_prefix(const char_u *efmp, efm_T *efminfo, char if (vim_strchr((char_u *)"DXAEWINCZGOPQ", *efmp) != NULL) { efminfo->prefix = *efmp; } else { - snprintf((char *)errmsg, errmsglen, - _("E376: Invalid %%%c in format string prefix"), *efmp); - EMSG(errmsg); + semsg(_("E376: Invalid %%%c in format string prefix"), *efmp); return NULL; } @@ -466,8 +454,7 @@ static const char_u *efm_analyze_prefix(const char_u *efmp, efm_T *efminfo, char // Converts a 'errorformat' string to regular expression pattern -static int efm_to_regpat(const char_u *efm, int len, efm_T *fmt_ptr, char_u *regpat, char_u *errmsg, - size_t errmsglen) +static int efm_to_regpat(const char_u *efm, int len, efm_T *fmt_ptr, char_u *regpat) FUNC_ATTR_NONNULL_ALL { // Build regexp pattern from current 'errorformat' option @@ -484,15 +471,14 @@ static int efm_to_regpat(const char_u *efm, int len, efm_T *fmt_ptr, char_u *reg } } if (idx < FMT_PATTERNS) { - ptr = efmpat_to_regpat(efmp, ptr, fmt_ptr, idx, round, errmsg, - errmsglen); + ptr = efmpat_to_regpat(efmp, ptr, fmt_ptr, idx, round); if (ptr == NULL) { return FAIL; } round++; } else if (*efmp == '*') { efmp++; - ptr = scanf_fmt_to_regpat(&efmp, efm, len, ptr, errmsg, errmsglen); + ptr = scanf_fmt_to_regpat(&efmp, efm, len, ptr); if (ptr == NULL) { return FAIL; } @@ -505,14 +491,12 @@ static int efm_to_regpat(const char_u *efm, int len, efm_T *fmt_ptr, char_u *reg } else if (efmp == efm + 1) { // analyse prefix // prefix is allowed only at the beginning of the errorformat // option part - efmp = efm_analyze_prefix(efmp, fmt_ptr, errmsg, errmsglen); + efmp = efm_analyze_prefix(efmp, fmt_ptr); if (efmp == NULL) { return FAIL; } } else { - snprintf((char *)errmsg, CMDBUFFSIZE + 1, - _("E377: Invalid %%%c in format string"), *efmp); - EMSG(errmsg); + semsg(_("E377: Invalid %%%c in format string"), *efmp); return FAIL; } } else { // copy normal character @@ -591,9 +575,6 @@ static efm_T *parse_efm_option(char_u *efm) efm_T *fmt_last = NULL; int len; - size_t errmsglen = CMDBUFFSIZE + 1; - char_u *errmsg = xmalloc(errmsglen); - // Get some space to modify the format string into. size_t sz = efm_regpat_bufsz(efm); char_u *fmtstr = xmalloc(sz); @@ -611,7 +592,7 @@ static efm_T *parse_efm_option(char_u *efm) // Isolate one part in the 'errorformat' option len = efm_option_part_len(efm); - if (efm_to_regpat(efm, len, fmt_ptr, fmtstr, errmsg, errmsglen) == FAIL) { + if (efm_to_regpat(efm, len, fmt_ptr, fmtstr) == FAIL) { goto parse_efm_error; } if ((fmt_ptr->prog = vim_regcomp(fmtstr, RE_MAGIC + RE_STRING)) == NULL) { @@ -622,7 +603,7 @@ static efm_T *parse_efm_option(char_u *efm) } if (fmt_first == NULL) { // nothing found - EMSG(_("E378: 'errorformat' contains no pattern")); + emsg(_("E378: 'errorformat' contains no pattern")); } goto parse_efm_end; @@ -632,7 +613,6 @@ parse_efm_error: parse_efm_end: xfree(fmtstr); - xfree(errmsg); return fmt_first; } @@ -1027,7 +1007,7 @@ static int qf_setup_state(qfstate_T *pstate, char_u *restrict enc, const char_u if (efile != NULL && (pstate->fd = os_fopen((const char *)efile, "r")) == NULL) { - EMSG2(_(e_openerrf), efile); + semsg(_(e_openerrf), efile); return FAIL; } @@ -1171,7 +1151,7 @@ static int qf_init_ext(qf_info_T *qi, int qf_idx, const char_u *restrict efile, retval = qfl->qf_count; goto qf_init_end; } - EMSG(_(e_readerrf)); + emsg(_(e_readerrf)); error2: if (!adding) { // Error when creating a new list. Free the new list @@ -1237,7 +1217,7 @@ static void qf_new_list(qf_info_T *qi, const char_u *qf_title) // If the current entry is not the last entry, delete entries beyond // the current entry. This makes it possible to browse in a tree-like - // way with ":grep'. + // way with ":grep". while (qi->qf_listcount > qi->qf_curlist + 1) { qf_free(&qi->qf_lists[--qi->qf_listcount]); } @@ -1564,7 +1544,7 @@ static int qf_parse_dir_pfx(int idx, qffields_T *fields, qf_list_T *qfl) { if (idx == 'D') { // enter directory if (*fields->namebuf == NUL) { - EMSG(_("E379: Missing or empty directory name")); + emsg(_("E379: Missing or empty directory name")); return QF_FAIL; } qfl->qf_directory = qf_push_dir(fields->namebuf, &qfl->qf_dir_stack, false); @@ -1748,7 +1728,7 @@ static void decr_quickfix_busy(void) } #ifdef ABORT_ON_INTERNAL_ERROR if (quickfix_busy < 0) { - EMSG("quickfix_busy has become negative"); + emsg("quickfix_busy has become negative"); abort(); } #endif @@ -1758,7 +1738,7 @@ static void decr_quickfix_busy(void) void check_quickfix_busy(void) { if (quickfix_busy != 0) { - EMSGN("quickfix_busy not zero on exit: %" PRId64, (int64_t)quickfix_busy); + semsg("quickfix_busy not zero on exit: %" PRId64, (int64_t)quickfix_busy); # ifdef ABORT_ON_INTERNAL_ERROR abort(); # endif @@ -1894,7 +1874,7 @@ static qf_info_T *qf_cmd_get_stack(exarg_T *eap, int print_emsg) qi = GET_LOC_LIST(curwin); if (qi == NULL) { if (print_emsg) { - EMSG(_(e_loclist)); + emsg(_(e_loclist)); } return NULL; } @@ -2361,7 +2341,7 @@ static qfline_T *get_nth_valid_entry(qf_list_T *qfl, int errornr, int dir, int * qf_ptr = prev_qf_ptr; qf_idx = prev_index; if (err != NULL) { - EMSG(_(err)); + emsg(_(err)); return NULL; } break; @@ -2379,7 +2359,7 @@ static qfline_T *get_nth_valid_entry(qf_list_T *qfl, int errornr, int dir, int * static qfline_T *get_nth_entry(qf_list_T *qfl, int errornr, int *new_qfidx) { qfline_T *qf_ptr = qfl->qf_ptr; - int qf_idx = qfl->qf_index;; + int qf_idx = qfl->qf_index; // New error number is less than the current error number while (errornr < qf_idx && qf_idx > 1 && qf_ptr->qf_prev != NULL) { @@ -2722,13 +2702,13 @@ static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, win // If a location list, check whether the associated window is still // present. if (qfl_type == QFLT_LOCATION && !win_valid_any_tab(oldwin)) { - EMSG(_("E924: Current window was closed")); + emsg(_("E924: Current window was closed")); *opened_window = false; return NOTDONE; } if (qfl_type == QFLT_QUICKFIX && !qflist_valid(NULL, save_qfid)) { - EMSG(_(e_current_quickfix_list_was_changed)); + emsg(_(e_current_quickfix_list_was_changed)); return NOTDONE; } @@ -2736,9 +2716,9 @@ static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, win || old_changetick != qfl->qf_changedtick || !is_qf_entry_present(qfl, qf_ptr)) { if (qfl_type == QFLT_QUICKFIX) { - EMSG(_(e_current_quickfix_list_was_changed)); + emsg(_(e_current_quickfix_list_was_changed)); } else { - EMSG(_(e_current_location_list_was_changed)); + emsg(_(e_current_location_list_was_changed)); } return NOTDONE; } @@ -2810,7 +2790,7 @@ static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, buf msg_scroll = false; } msg_ext_set_kind("quickfix"); - msg_attr_keep(IObuff, 0, true, false); + msg_attr_keep((char *)IObuff, 0, true, false); msg_scroll = (int)i; } @@ -2837,9 +2817,9 @@ static int qf_jump_open_window(qf_info_T *qi, qfline_T *qf_ptr, bool newwin, int || old_changetick != qfl->qf_changedtick || !is_qf_entry_present(qfl, qf_ptr)) { if (qfl_type == QFLT_QUICKFIX) { - EMSG(_(e_current_quickfix_list_was_changed)); + emsg(_(e_current_quickfix_list_was_changed)); } else { - EMSG(_(e_current_location_list_was_changed)); + emsg(_(e_current_location_list_was_changed)); } return FAIL; } @@ -2862,9 +2842,9 @@ static int qf_jump_open_window(qf_info_T *qi, qfline_T *qf_ptr, bool newwin, int || old_changetick != qfl->qf_changedtick || !is_qf_entry_present(qfl, qf_ptr)) { if (qfl_type == QFLT_QUICKFIX) { - EMSG(_(e_current_quickfix_list_was_changed)); + emsg(_(e_current_quickfix_list_was_changed)); } else { - EMSG(_(e_current_location_list_was_changed)); + emsg(_(e_current_location_list_was_changed)); } return FAIL; } @@ -2951,7 +2931,7 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, boo } if (qf_stack_empty(qi) || qf_list_empty(qf_get_curlist(qi))) { - EMSG(_(e_quickfix)); + emsg(_(e_quickfix)); return; } @@ -3124,7 +3104,7 @@ void qf_list(exarg_T *eap) } if (qf_stack_empty(qi) || qf_list_empty(qf_get_curlist(qi))) { - EMSG(_(e_quickfix)); + emsg(_(e_quickfix)); return; } @@ -3134,7 +3114,7 @@ void qf_list(exarg_T *eap) plus = true; } if (!get_list_range(&arg, &idx1, &idx2) || *arg != NUL) { - EMSG(_(e_trailing)); + emsg(_(e_trailing)); return; } qfl = qf_get_curlist(qi); @@ -3254,7 +3234,7 @@ static void qf_msg(qf_info_T *qi, int which, char *lead) xstrlcat((char *)buf, title, IOSIZE); } trunc_string(buf, buf, Columns - 1, IOSIZE); - msg(buf); + msg((char *)buf); } /// ":colder [count]": Up in the quickfix stack. @@ -3279,13 +3259,13 @@ void qf_age(exarg_T *eap) while (count--) { if (eap->cmdidx == CMD_colder || eap->cmdidx == CMD_lolder) { if (qi->qf_curlist == 0) { - EMSG(_("E380: At bottom of quickfix stack")); + emsg(_("E380: At bottom of quickfix stack")); break; } --qi->qf_curlist; } else { if (qi->qf_curlist >= qi->qf_listcount - 1) { - EMSG(_("E381: At top of quickfix stack")); + emsg(_("E381: At top of quickfix stack")); break; } ++qi->qf_curlist; @@ -3303,7 +3283,7 @@ void qf_history(exarg_T *eap) if (eap->addr_count > 0) { if (qi == NULL) { - EMSG(_(e_loclist)); + emsg(_(e_loclist)); return; } @@ -3313,14 +3293,14 @@ void qf_history(exarg_T *eap) qf_msg(qi, qi->qf_curlist, ""); qf_update_buffer(qi, NULL); } else { - EMSG(_(e_invrange)); + emsg(_(e_invrange)); } return; } if (qf_stack_empty(qi)) { - MSG(_("No entries")); + msg(_("No entries")); } else { for (i = 0; i < qi->qf_listcount; i++) { qf_msg(qi, i, i == qi->qf_curlist ? "> " : " "); @@ -3489,7 +3469,7 @@ void qf_view_result(bool split) qi = GET_LOC_LIST(curwin); } if (qf_list_empty(qf_get_curlist(qi))) { - EMSG(_(e_quickfix)); + emsg(_(e_quickfix)); return; } @@ -3643,12 +3623,12 @@ static int qf_open_new_cwindow(qf_info_T *qi, int height) if (qf_buf != NULL) { // Use the existing quickfix buffer if (do_ecmd(qf_buf->b_fnum, NULL, NULL, NULL, ECMD_ONE, - ECMD_HIDE + ECMD_OLDBUF, oldwin) == FAIL) { + ECMD_HIDE + ECMD_OLDBUF + ECMD_NOWINENTER, oldwin) == FAIL) { return FAIL; } } else { // Create a new quickfix buffer - if (do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, oldwin) == FAIL) { + if (do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE + ECMD_NOWINENTER, oldwin) == FAIL) { return FAIL; } } @@ -4293,7 +4273,7 @@ static char *make_get_fullcmd(const char_u *makecmd, const char_u *fname) msg_didout = false; } msg_start(); - MSG_PUTS(":!"); + msg_puts(":!"); msg_outtrans((char_u *)cmd); // show what we are doing return cmd; @@ -4384,7 +4364,7 @@ static char_u *get_mef_name(void) if (*p_mef == NUL) { name = vim_tempname(); if (name == NULL) { - EMSG(_(e_notmp)); + emsg(_(e_notmp)); } return name; } @@ -4958,7 +4938,7 @@ void ex_cbelow(exarg_T *eap) int buf_has_flag; if (eap->addr_count > 0 && eap->line2 <= 0) { - EMSG(_(e_invrange)); + emsg(_(e_invrange)); return; } @@ -4970,7 +4950,7 @@ void ex_cbelow(exarg_T *eap) buf_has_flag = BUF_HAS_LL_ENTRY; } if (!(curbuf->b_has_qf_entry & buf_has_flag)) { - EMSG(_(e_quickfix)); + emsg(_(e_quickfix)); return; } @@ -4981,7 +4961,7 @@ void ex_cbelow(exarg_T *eap) qfl = qf_get_curlist(qi); // check if the list has valid errors if (!qf_list_has_valid_entries(qfl)) { - EMSG(_(e_quickfix)); + emsg(_(e_quickfix)); return; } @@ -5012,7 +4992,7 @@ void ex_cbelow(exarg_T *eap) if (errornr > 0) { qf_jump(qi, 0, errornr, false); } else { - EMSG(_(e_no_more_items)); + emsg(_(e_no_more_items)); } } @@ -5136,7 +5116,7 @@ static void vgr_init_regmatch(regmmatch_T *regmatch, char_u *s) if (s == NULL || *s == NUL) { // Pattern is empty, use last search pattern. if (last_search_pat() == NULL) { - EMSG(_(e_noprevre)); + emsg(_(e_noprevre)); return; } regmatch->regprog = vim_regcomp(last_search_pat(), RE_MAGIC); @@ -5196,7 +5176,7 @@ static bool vgr_qflist_valid(win_T *wp, qf_info_T *qi, unsigned qfid, char_u *ti if (!qflist_valid(wp, qfid)) { if (wp != NULL) { // An autocmd has freed the location list - EMSG(_(e_current_location_list_was_changed)); + emsg(_(e_current_location_list_was_changed)); return false; } else { // Quickfix list is not found, create a new one. @@ -5355,7 +5335,7 @@ void ex_vimgrep(exarg_T *eap) char_u *title = vim_strsave(qf_cmdtitle(*eap->cmdlinep)); p = skip_vimgrep_pat(eap->arg, &s, &flags); if (p == NULL) { - EMSG(_(e_invalpat)); + emsg(_(e_invalpat)); goto theend; } @@ -5366,7 +5346,7 @@ void ex_vimgrep(exarg_T *eap) p = skipwhite(p); if (*p == NUL) { - EMSG(_("E683: File name missing or invalid pattern")); + emsg(_("E683: File name missing or invalid pattern")); goto theend; } @@ -5382,7 +5362,7 @@ void ex_vimgrep(exarg_T *eap) goto theend; } if (fcount == 0) { - EMSG(_(e_nomatch)); + emsg(_(e_nomatch)); goto theend; } @@ -5528,7 +5508,7 @@ void ex_vimgrep(exarg_T *eap) target_dir); } } else { - EMSG2(_(e_nomatch2), s); + semsg(_(e_nomatch2), s); } decr_quickfix_busy(); @@ -6252,7 +6232,7 @@ static int qf_add_entry_from_dict(qf_list_T *qfl, const dict_T *d, bool first_en if (bufnum != 0 && (buflist_findnr(bufnum) == NULL)) { if (!did_bufnr_emsg) { did_bufnr_emsg = true; - EMSGN(_("E92: Buffer %" PRId64 " not found"), bufnum); + semsg(_("E92: Buffer %" PRId64 " not found"), (int64_t)bufnum); } valid = false; bufnum = 0; @@ -6660,7 +6640,7 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, dict_T *wh // A dict argument cannot be specified with a non-empty list argument if (list != NULL && tv_list_len(list) != 0 && what != NULL) { - EMSG2(_(e_invarg2), _("cannot have both a list and a \"what\" argument")); + semsg(_(e_invarg2), _("cannot have both a list and a \"what\" argument")); return FAIL; } @@ -6761,12 +6741,12 @@ static int cbuffer_process_args(exarg_T *eap, buf_T **bufp, linenr_T *line1, lin } if (buf == NULL) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return FAIL; } if (buf->b_ml.ml_mfp == NULL) { - EMSG(_("E681: Buffer is not loaded")); + emsg(_("E681: Buffer is not loaded")); return FAIL; } @@ -6777,7 +6757,7 @@ static int cbuffer_process_args(exarg_T *eap, buf_T **bufp, linenr_T *line1, lin if (eap->line1 < 1 || eap->line1 > buf->b_ml.ml_line_count || eap->line2 < 1 || eap->line2 > buf->b_ml.ml_line_count) { - EMSG(_(e_invrange)); + emsg(_(e_invrange)); return FAIL; } @@ -6937,7 +6917,7 @@ void ex_cexpr(exarg_T *eap) } decr_quickfix_busy(); } else { - EMSG(_("E777: String or List expected")); + emsg(_("E777: String or List expected")); } cleanup: tv_clear(&tv); @@ -7150,7 +7130,7 @@ void ex_helpgrep(exarg_T *eap) if (!qf_list_empty(qf_get_curlist(qi))) { qf_jump(qi, 0, 0, false); } else { - EMSG2(_(e_nomatch2), eap->arg); + semsg(_(e_nomatch2), eap->arg); } decr_quickfix_busy(); @@ -7168,4 +7148,3 @@ void ex_helpgrep(exarg_T *eap) } } - diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 24dc86e034..bec3bc9648 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -461,15 +461,15 @@ static int toggle_Magic(int x) */ #define UCHARAT(p) ((int)*(char_u *)(p)) -/* Used for an error (down from) vim_regcomp(): give the error message, set - * rc_did_emsg and return NULL */ -#define EMSG_RET_NULL(m) return (EMSG(m), rc_did_emsg = true, (void *)NULL) -#define IEMSG_RET_NULL(m) return (IEMSG(m), rc_did_emsg = true, (void *)NULL) -#define EMSG_RET_FAIL(m) return (EMSG(m), rc_did_emsg = true, FAIL) +// Used for an error (down from) vim_regcomp(): give the error message, set +// rc_did_emsg and return NULL +#define EMSG_RET_NULL(m) return (emsg(m), rc_did_emsg = true, (void *)NULL) +#define IEMSG_RET_NULL(m) return (iemsg(m), rc_did_emsg = true, (void *)NULL) +#define EMSG_RET_FAIL(m) return (emsg(m), rc_did_emsg = true, FAIL) #define EMSG2_RET_NULL(m, c) \ - return (EMSG2((m), (c) ? "" : "\\"), rc_did_emsg = true, (void *)NULL) + return (semsg((m), (c) ? "" : "\\"), rc_did_emsg = true, (void *)NULL) #define EMSG2_RET_FAIL(m, c) \ - return (EMSG2((m), (c) ? "" : "\\"), rc_did_emsg = true, FAIL) + return (semsg((m), (c) ? "" : "\\"), rc_did_emsg = true, FAIL) #define EMSG_ONE_RET_NULL EMSG2_RET_NULL(_( \ "E369: invalid item in %s%%[]"), reg_magic == MAGIC_ALL) @@ -715,9 +715,9 @@ static int reg_magic; /* magicness of the pattern: */ #define MAGIC_ON 3 /* "\m" or 'magic' */ #define MAGIC_ALL 4 /* "\v" very magic */ -static int reg_string; /* matching with a string instead of a buffer - line */ -static int reg_strict; /* "[abc" is illegal */ +static int reg_string; // matching with a string instead of a buffer + // line +static int reg_strict; // "[abc" is illegal /* * META contains all characters that may be magic, except '^' and '$'. @@ -741,10 +741,10 @@ static char_u META_flags[] = { 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1 }; -static int curchr; /* currently parsed character */ -/* Previous character. Note: prevchr is sometimes -1 when we are not at the - * start, eg in /[ ^I]^ the pattern was never found even if it existed, - * because ^ was taken to be magic -- webb */ +static int curchr; // currently parsed character +// Previous character. Note: prevchr is sometimes -1 when we are not at the +// start, eg in /[ ^I]^ the pattern was never found even if it existed, +// because ^ was taken to be magic -- webb static int prevchr; static int prevprevchr; /* previous-previous character */ static int nextchr; /* used for ungetchr() */ @@ -783,7 +783,7 @@ static int get_equi_class(char_u **pp) char_u *p = *pp; if (p[1] == '=' && p[2] != NUL) { - l = (*mb_ptr2len)(p + 2); + l = utfc_ptr2len(p + 2); if (p[l + 2] == '=' && p[l + 3] == ']') { c = utf_ptr2char(p + 2); *pp += l + 4; @@ -1144,7 +1144,7 @@ static char_u *skip_anyof(char_u *p) if (*p == ']' || *p == '-') ++p; while (*p != NUL && *p != ']') { - if ((l = (*mb_ptr2len)(p)) > 1) { + if ((l = utfc_ptr2len(p)) > 1) { p += l; } else if (*p == '-') { p++; @@ -1237,7 +1237,7 @@ static int seen_endbrace(int refnum) } if (*p == NUL) { - EMSG(_("E65: Illegal back reference")); + emsg(_("E65: Illegal back reference")); rc_did_emsg = true; return false; } @@ -1767,7 +1767,7 @@ static char_u *regpiece(int *flagp) else sprintf((char *)IObuff, _("E62: Nested %s%c"), reg_magic == MAGIC_ALL ? "" : "\\", no_Magic(peekchr())); - EMSG_RET_NULL(IObuff); + EMSG_RET_NULL((char *)IObuff); } return ret; @@ -1929,7 +1929,7 @@ static char_u *regatom(int *flagp) sprintf((char *)IObuff, _("E64: %s%c follows nothing"), (c == '*' ? reg_magic >= MAGIC_ON : reg_magic == MAGIC_ALL) ? "" : "\\", c); - EMSG_RET_NULL(IObuff); + EMSG_RET_NULL((char *)IObuff); /* NOTREACHED */ case Magic('~'): /* previous substitute pattern */ @@ -2255,8 +2255,8 @@ collection: if (startc > endc) { EMSG_RET_NULL(_(e_reverse_range)); } - if ((*mb_char2len)(startc) > 1 - || (*mb_char2len)(endc) > 1) { + if (utf_char2len(startc) > 1 + || utf_char2len(endc) > 1) { // Limit to a range of 256 chars if (endc > startc + 256) { EMSG_RET_NULL(_(e_large_class)); @@ -2509,8 +2509,9 @@ do_multibyte: /* Need to get composing character too. */ for (;; ) { l = utf_ptr2len(regparse); - if (!UTF_COMPOSINGLIKE(regparse, regparse + l)) + if (!utf_composinglike(regparse, regparse + l)) { break; + } regmbc(utf_ptr2char(regparse)); skipchr(); } @@ -2835,21 +2836,22 @@ static int peekchr(void) curchr = Magic(curchr); break; case '*': - /* * is not magic as the very first character, eg "?*ptr", when - * after '^', eg "/^*ptr" and when after "\(", "\|", "\&". But - * "\(\*" is not magic, thus must be magic if "after_slash" */ + // * is not magic as the very first character, eg "?*ptr", when + // after '^', eg "/^*ptr" and when after "\(", "\|", "\&". But + // "\(\*" is not magic, thus must be magic if "after_slash" if (reg_magic >= MAGIC_ON && !at_start && !(prev_at_start && prevchr == Magic('^')) && (after_slash || (prevchr != Magic('(') && prevchr != Magic('&') - && prevchr != Magic('|')))) + && prevchr != Magic('|')))) { curchr = Magic('*'); + } break; case '^': - /* '^' is only magic as the very first character and if it's after - * "\(", "\|", "\&' or "\n" */ + // '^' is only magic as the very first character and if it's after + // "\(", "\|", "\&' or "\n" if (reg_magic >= MAGIC_OFF && (at_start || reg_magic == MAGIC_ALL @@ -2865,8 +2867,8 @@ static int peekchr(void) } break; case '$': - /* '$' is only magic as the very last char and if it's in front of - * either "\|", "\)", "\&", or "\n" */ + // '$' is only magic as the very last char and if it's in front of + // either "\|", "\)", "\&", or "\n" if (reg_magic >= MAGIC_OFF) { char_u *p = regparse + 1; bool is_magic_all = (reg_magic == MAGIC_ALL); @@ -3152,7 +3154,7 @@ static int read_limits(long *minval, long *maxval) if (*regparse != '}') { sprintf((char *)IObuff, _("E554: Syntax error in %s{...}"), reg_magic == MAGIC_ALL ? "" : "\\"); - EMSG_RET_FAIL(IObuff); + EMSG_RET_FAIL((char *)IObuff); } /* @@ -3482,7 +3484,7 @@ static long bt_regexec_both(char_u *line, /* Be paranoid... */ if (prog == NULL || line == NULL) { - IEMSG(_(e_null)); + iemsg(_(e_null)); goto theend; } @@ -3584,7 +3586,7 @@ static long bt_regexec_both(char_u *line, if (rex.line[col] == NUL) { break; } - col += (*mb_ptr2len)(rex.line + col); + col += utfc_ptr2len(rex.line + col); // Check for timeout once in a twenty times to avoid overhead. if (tm != NULL && ++tm_count == 20) { tm_count = 0; @@ -4126,7 +4128,7 @@ static bool regmatch( break; case PRINT: - if (!vim_isprintc(PTR2CHAR(rex.input))) { + if (!vim_isprintc(utf_ptr2char(rex.input))) { status = RA_NOMATCH; } else { ADVANCE_REGINPUT(); @@ -4134,7 +4136,7 @@ static bool regmatch( break; case SPRINT: - if (ascii_isdigit(*rex.input) || !vim_isprintc(PTR2CHAR(rex.input))) { + if (ascii_isdigit(*rex.input) || !vim_isprintc(utf_ptr2char(rex.input))) { status = RA_NOMATCH; } else { ADVANCE_REGINPUT(); @@ -4293,7 +4295,7 @@ static bool regmatch( // Check for following composing character, unless %C // follows (skips over all composing chars). if (status != RA_NOMATCH - && UTF_COMPOSINGLIKE(rex.input, rex.input + len) + && utf_composinglike(rex.input, rex.input + len) && !rex.reg_icombine && OP(next) != RE_COMPOSING) { // raaron: This code makes a composing character get @@ -4325,7 +4327,7 @@ static bool regmatch( const char_u *opnd = OPERAND(scan); // Safety check (just in case 'encoding' was changed since // compiling the program). - if ((len = (*mb_ptr2len)(opnd)) < 2) { + if ((len = utfc_ptr2len(opnd)) < 2) { status = RA_NOMATCH; break; } @@ -4729,7 +4731,7 @@ static bool regmatch( * follows. The code is below. Parameters are stored in * a regstar_T on the regstack. */ if ((long)((unsigned)regstack.ga_len >> 10) >= p_mmp) { - EMSG(_(e_maxmempat)); + emsg(_(e_maxmempat)); status = RA_FAIL; } else { ga_grow(®stack, sizeof(regstar_T)); @@ -4767,7 +4769,7 @@ static bool regmatch( case NOBEHIND: /* Need a bit of room to store extra positions. */ if ((long)((unsigned)regstack.ga_len >> 10) >= p_mmp) { - EMSG(_(e_maxmempat)); + emsg(_(e_maxmempat)); status = RA_FAIL; } else { ga_grow(®stack, sizeof(regbehind_T)); @@ -4815,7 +4817,7 @@ static bool regmatch( break; default: - IEMSG(_(e_re_corr)); + iemsg(_(e_re_corr)); #ifdef REGEXP_DEBUG printf("Illegal op code %d\n", op); #endif @@ -5173,7 +5175,7 @@ static bool regmatch( * We get here only if there's trouble -- normally "case END" is * the terminating point. */ - IEMSG(_(e_re_corr)); + iemsg(_(e_re_corr)); #ifdef REGEXP_DEBUG printf("Premature EOL\n"); #endif @@ -5195,7 +5197,7 @@ static regitem_T *regstack_push(regstate_T state, char_u *scan) regitem_T *rp; if ((long)((unsigned)regstack.ga_len >> 10) >= p_mmp) { - EMSG(_(e_maxmempat)); + emsg(_(e_maxmempat)); return NULL; } ga_grow(®stack, sizeof(regitem_T)); @@ -5268,7 +5270,7 @@ regrepeat ( case SIDENT: case SIDENT + ADD_NL: while (count < maxcount) { - if (vim_isIDc(PTR2CHAR(scan)) && (testval || !ascii_isdigit(*scan))) { + if (vim_isIDc(utf_ptr2char(scan)) && (testval || !ascii_isdigit(*scan))) { MB_PTR_ADV(scan); } else if (*scan == NUL) { if (!REG_MULTI || !WITH_NL(OP(p)) || rex.lnum > rex.reg_maxline @@ -5325,7 +5327,7 @@ regrepeat ( case SFNAME: case SFNAME + ADD_NL: while (count < maxcount) { - if (vim_isfilec(PTR2CHAR(scan)) && (testval || !ascii_isdigit(*scan))) { + if (vim_isfilec(utf_ptr2char(scan)) && (testval || !ascii_isdigit(*scan))) { MB_PTR_ADV(scan); } else if (*scan == NUL) { if (!REG_MULTI || !WITH_NL(OP(p)) || rex.lnum > rex.reg_maxline @@ -5363,7 +5365,7 @@ regrepeat ( if (got_int) { break; } - } else if (vim_isprintc(PTR2CHAR(scan)) == 1 + } else if (vim_isprintc(utf_ptr2char(scan)) == 1 && (testval || !ascii_isdigit(*scan))) { MB_PTR_ADV(scan); } else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) { @@ -5391,7 +5393,7 @@ do_class: if (got_int) { break; } - } else if ((l = (*mb_ptr2len)(scan)) > 1) { + } else if ((l = utfc_ptr2len(scan)) > 1) { if (testval != 0) { break; } @@ -5506,12 +5508,12 @@ do_class: /* Safety check (just in case 'encoding' was changed since * compiling the program). */ - if ((len = (*mb_ptr2len)(opnd)) > 1) { + if ((len = utfc_ptr2len(opnd)) > 1) { if (rex.reg_ic) { cf = utf_fold(utf_ptr2char(opnd)); } - while (count < maxcount && (*mb_ptr2len)(scan) >= len) { - for (i = 0; i < len; ++i) { + while (count < maxcount && utfc_ptr2len(scan) >= len) { + for (i = 0; i < len; i++) { if (opnd[i] != scan[i]) { break; } @@ -5580,7 +5582,7 @@ do_class: break; default: // Oh dear. Called inappropriately. - IEMSG(_(e_re_corr)); + iemsg(_(e_re_corr)); #ifdef REGEXP_DEBUG printf("Called regrepeat with op code %d\n", OP(p)); #endif @@ -5630,7 +5632,7 @@ static int prog_magic_wrong(void) } if (UCHARAT(((bt_regprog_T *)prog)->program) != REGMAGIC) { - EMSG(_(e_re_corr)); + emsg(_(e_re_corr)); return true; } return false; @@ -5811,8 +5813,8 @@ static int match_with_backref(linenr_T start_lnum, colnr_T start_col, linenr_T e if (bytelen != NULL) *bytelen = 0; for (;; ) { - /* Since getting one line may invalidate the other, need to make copy. - * Slow! */ + // Since getting one line may invalidate the other, need to make copy. + // Slow! if (rex.line != reg_tofree) { len = (int)STRLEN(rex.line); if (reg_tofree == NULL || len >= (int)reg_tofreelen) { @@ -6445,9 +6447,9 @@ static int cstrncmp(char_u *s1, char_u *s2, int *n) return result; } -/*************************************************************** -* regsub stuff * -***************************************************************/ +//////////////////////////////////////////////////////////////// +// regsub stuff // +//////////////////////////////////////////////////////////////// /* This stuff below really confuses cc on an SGI -- webb */ @@ -6512,9 +6514,10 @@ char_u *regtilde(char_u *source, int magic) memmove(tmpsub, newsub, (size_t)len); /* interpret tilde */ memmove(tmpsub + len, reg_prev_sub, (size_t)prevlen); - /* copy postfix */ - if (!magic) - ++p; /* back off \ */ + // copy postfix + if (!magic) { + p++; // back off backslash + } STRCPY(tmpsub + len + prevlen, p + 1); if (newsub != source) /* already allocated newsub */ @@ -6530,7 +6533,7 @@ char_u *regtilde(char_u *source, int magic) if (*p == '\\' && p[1]) { // skip escaped characters p++; } - p += (*mb_ptr2len)(p) - 1; + p += utfc_ptr2len(p) - 1; } } @@ -6687,7 +6690,7 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, // Be paranoid... if ((source == NULL && expr == NULL) || dest == NULL) { - EMSG(_(e_null)); + emsg(_(e_null)); return 0; } if (prog_magic_wrong()) @@ -6941,7 +6944,7 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, } } else if (*s == NUL) { // we hit NUL. if (copy) { - IEMSG(_(e_re_damg)); + iemsg(_(e_re_damg)); } goto exit; } else { @@ -7227,7 +7230,7 @@ regprog_T *vim_regcomp(char_u *expr_arg, int re_flags) regname[newengine]); #endif } else { - EMSG(_( + emsg(_( "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be used ")); regexp_engine = AUTOMATIC_ENGINE; } @@ -7261,7 +7264,7 @@ regprog_T *vim_regcomp(char_u *expr_arg, int re_flags) fprintf(f, "Syntax error in \"%s\"\n", expr); fclose(f); } else - EMSG2("(NFA) Could not open \"%s\" to write !!!", + semsg("(NFA) Could not open \"%s\" to write !!!", BT_REGEXP_DEBUG_LOG_NAME); } #endif @@ -7300,8 +7303,8 @@ static void report_re_switch(char_u *pat) { if (p_verbose > 0) { verbose_enter(); - MSG_PUTS(_("Switching to backtracking RE engine for pattern: ")); - MSG_PUTS(pat); + msg_puts(_("Switching to backtracking RE engine for pattern: ")); + msg_puts((char *)pat); verbose_leave(); } } @@ -7326,7 +7329,7 @@ static bool vim_regexec_string(regmatch_T *rmp, char_u *line, colnr_T col, // Cannot use the same prog recursively, it contains state. if (rmp->regprog->re_in_use) { - EMSG(_(e_recursive)); + emsg(_(e_recursive)); return false; } rmp->regprog->re_in_use = true; @@ -7423,7 +7426,7 @@ long vim_regexec_multi( // Cannot use the same prog recursively, it contains state. if (rmp->regprog->re_in_use) { - EMSG(_(e_recursive)); + emsg(_(e_recursive)); return false; } rmp->regprog->re_in_use = true; diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index c8b7190b4a..5df5cc5975 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -48,14 +48,14 @@ enum { NFA_MATCH, NFA_EMPTY, /* matches 0-length */ - NFA_START_COLL, /* [abc] start */ - NFA_END_COLL, /* [abc] end */ - NFA_START_NEG_COLL, /* [^abc] start */ - NFA_END_NEG_COLL, /* [^abc] end (postfix only) */ - NFA_RANGE, /* range of the two previous items - * (postfix only) */ - NFA_RANGE_MIN, /* low end of a range */ - NFA_RANGE_MAX, /* high end of a range */ + NFA_START_COLL, // [abc] start + NFA_END_COLL, // [abc] end + NFA_START_NEG_COLL, // [^abc] start + NFA_END_NEG_COLL, // [^abc] end (postfix only) + NFA_RANGE, // range of the two previous items + // (postfix only) + NFA_RANGE_MIN, // low end of a range + NFA_RANGE_MAX, // high end of a range NFA_CONCAT, // concatenate two previous items (postfix // only) @@ -88,9 +88,9 @@ enum { NFA_END_INVISIBLE, NFA_END_INVISIBLE_NEG, NFA_END_PATTERN, - NFA_COMPOSING, /* Next nodes in NFA are part of the - composing multibyte char */ - NFA_END_COMPOSING, /* End of a composing char in the NFA */ + NFA_COMPOSING, // Next nodes in NFA are part of the + // composing multibyte char + NFA_END_COMPOSING, // End of a composing char in the NFA NFA_ANY_COMPOSING, // \%C: Any composing characters. NFA_OPT_CHARS, /* \%[abc] */ @@ -256,9 +256,9 @@ static char_u e_ill_char_class[] = N_( "E877: (NFA regexp) Invalid character class: %" PRId64); static char_u e_value_too_large[] = N_("E951: \\% value too large"); -/* Since the out pointers in the list are always - * uninitialized, we use the pointers themselves - * as storage for the Ptrlists. */ +// Since the out pointers in the list are always +// uninitialized, we use the pointers themselves +// as storage for the Ptrlists. typedef union Ptrlist Ptrlist; union Ptrlist { Ptrlist *next; @@ -310,9 +310,9 @@ struct nfa_pim_S { typedef struct { nfa_state_T *state; int count; - nfa_pim_T pim; /* if pim.result != NFA_PIM_UNUSED: postponed - * invisible match */ - regsubs_T subs; /* submatch info, only party used */ + nfa_pim_T pim; // if pim.result != NFA_PIM_UNUSED: postponed + // invisible match + regsubs_T subs; // submatch info, only party used } nfa_thread_T; // nfa_list_T contains the alternative NFA execution states. @@ -543,7 +543,7 @@ static char_u *nfa_get_match_text(nfa_state_T *start) return NULL; /* just in case */ p = p->out; while (p->c > 0) { - len += MB_CHAR2LEN(p->c); + len += utf_char2len(p->c); p = p->out; } if (p->c != NFA_MCLOSE || p->out->c != NFA_MATCH) @@ -1244,11 +1244,11 @@ static int nfa_regatom(void) p = vim_strchr(classchars, no_Magic(c)); if (p == NULL) { if (extra == NFA_ADD_NL) { - EMSGN(_(e_ill_char_class), c); + semsg(_(e_ill_char_class), (int64_t)c); rc_did_emsg = true; return FAIL; } - IEMSGN("INTERNAL: Unknown character class char: %" PRId64, c); + siemsg("INTERNAL: Unknown character class char: %" PRId64, (int64_t)c); return FAIL; } // When '.' is followed by a composing char ignore the dot, so that @@ -1286,7 +1286,7 @@ static int nfa_regatom(void) case Magic('|'): case Magic('&'): case Magic(')'): - EMSGN(_(e_misplaced), no_Magic(c)); // -V1037 + semsg(_(e_misplaced), (int64_t)no_Magic(c)); // -V1037 return FAIL; case Magic('='): @@ -1296,7 +1296,7 @@ static int nfa_regatom(void) case Magic('*'): case Magic('{'): // these should follow an atom, not form an atom - EMSGN(_(e_misplaced), no_Magic(c)); + semsg(_(e_misplaced), (int64_t)no_Magic(c)); return FAIL; case Magic('~'): @@ -1306,13 +1306,14 @@ static int nfa_regatom(void) // Previous substitute pattern. // Generated as "\%(pattern\)". if (reg_prev_sub == NULL) { - EMSG(_(e_nopresub)); + emsg(_(e_nopresub)); return FAIL; } for (lp = reg_prev_sub; *lp != NUL; MB_CPTR_ADV(lp)) { - EMIT(PTR2CHAR(lp)); - if (lp != reg_prev_sub) + EMIT(utf_ptr2char(lp)); + if (lp != reg_prev_sub) { EMIT(NFA_CONCAT); + } } EMIT(NFA_NOPEN); break; @@ -1383,7 +1384,7 @@ static int nfa_regatom(void) re_has_z = REX_SET; break; default: - emsgf(_("E867: (NFA) Unknown operator '\\z%c'"), + semsg(_("E867: (NFA) Unknown operator '\\z%c'"), no_Magic(c)); return FAIL; } @@ -1489,7 +1490,7 @@ static int nfa_regatom(void) while (ascii_isdigit(c)) { if (n > (INT32_MAX - (c - '0')) / 10) { // overflow. - EMSG(_(e_value_too_large)); + emsg(_(e_value_too_large)); return FAIL; } n = n * 10 + (c - '0'); @@ -1516,7 +1517,7 @@ static int nfa_regatom(void) limit = INT32_MAX / MB_MAXBYTES; } if (n >= limit) { - EMSG(_(e_value_too_large)); + emsg(_(e_value_too_large)); return FAIL; } EMIT((int)n); @@ -1529,7 +1530,7 @@ static int nfa_regatom(void) break; } } - emsgf(_("E867: (NFA) Unknown operator '\\%%%c'"), + semsg(_("E867: (NFA) Unknown operator '\\%%%c'"), no_Magic(c)); return FAIL; } @@ -1675,13 +1676,13 @@ collection: } /* Try collating class like [. .] */ if (collclass != 0) { - startc = collclass; /* allow [.a.]-x as a range */ - /* Will emit the proper atom at the end of the - * while loop. */ + startc = collclass; // allow [.a.]-x as a range + // Will emit the proper atom at the end of the + // while loop. } } - /* Try a range like 'a-x' or '\t-z'. Also allows '-' as a - * start character. */ + // Try a range like 'a-x' or '\t-z'. Also allows '-' as a + // start character. if (*regparse == '-' && oldstartc != -1) { emit_range = true; startc = oldstartc; @@ -1689,11 +1690,10 @@ collection: continue; // reading the end of the range } - /* Now handle simple and escaped characters. - * Only "\]", "\^", "\]" and "\\" are special in Vi. Vim - * accepts "\t", "\e", etc., but only when the 'l' flag in - * 'cpoptions' is not included. - */ + // Now handle simple and escaped characters. + // Only "\]", "\^", "\]" and "\\" are special in Vi. Vim + // accepts "\t", "\e", etc., but only when the 'l' flag in + // 'cpoptions' is not included. if (*regparse == '\\' && regparse + 1 <= endp && (vim_strchr(REGEXP_INRANGE, regparse[1]) != NULL @@ -1723,9 +1723,10 @@ collection: } } - /* Normal printable char */ - if (startc == -1) - startc = PTR2CHAR(regparse); + // Normal printable char + if (startc == -1) { + startc = utf_ptr2char(regparse); + } /* Previous char was '-', so this char is end of range. */ if (emit_range) { @@ -1736,18 +1737,19 @@ collection: } if (endc > startc + 2) { - /* Emit a range instead of the sequence of - * individual characters. */ - if (startc == 0) - /* \x00 is translated to \x0a, start at \x01. */ + // Emit a range instead of the sequence of + // individual characters. + if (startc == 0) { + // \x00 is translated to \x0a, start at \x01. EMIT(1); - else - --post_ptr; /* remove NFA_CONCAT */ + } else { + post_ptr--; // remove NFA_CONCAT + } EMIT(endc); EMIT(NFA_RANGE); EMIT(NFA_CONCAT); - } else if ((*mb_char2len)(startc) > 1 - || (*mb_char2len)(endc) > 1) { + } else if (utf_char2len(startc) > 1 + || utf_char2len(endc) > 1) { // Emit the characters in the range. // "startc" was already emitted, so skip it. for (c = startc + 1; c <= endc; c++) { @@ -1755,8 +1757,8 @@ collection: EMIT(NFA_CONCAT); } } else { - /* Emit the range. "startc" was already emitted, so - * skip it. */ + // Emit the range. "startc" was already emitted, so + // skip it. for (c = startc + 1; c <= endc; c++) { EMIT(c); EMIT(NFA_CONCAT); @@ -1765,19 +1767,20 @@ collection: emit_range = false; startc = -1; } else { - /* This char (startc) is not part of a range. Just - * emit it. - * Normally, simply emit startc. But if we get char - * code=0 from a collating char, then replace it with - * 0x0a. - * This is needed to completely mimic the behaviour of - * the backtracking engine. */ + // This char (startc) is not part of a range. Just + // emit it. + // Normally, simply emit startc. But if we get char + // code=0 from a collating char, then replace it with + // 0x0a. + // This is needed to completely mimic the behaviour of + // the backtracking engine. if (startc == NFA_NEWL) { - /* Line break can't be matched as part of the - * collection, add an OR below. But not for negated - * range. */ - if (!negated) + // Line break can't be matched as part of the + // collection, add an OR below. But not for negated + // range. + if (!negated) { extra = NFA_ADD_NL; + } } else { if (got_coll_char == true && startc == 0) { EMIT(0x0a); @@ -1827,18 +1830,18 @@ collection: nfa_do_multibyte: // plen is length of current char with composing chars - if ((*mb_char2len)(c) != (plen = utfc_ptr2len(old_regparse)) + if (utf_char2len(c) != (plen = utfc_ptr2len(old_regparse)) || utf_iscomposing(c)) { int i = 0; - /* A base character plus composing characters, or just one - * or more composing characters. - * This requires creating a separate atom as if enclosing - * the characters in (), where NFA_COMPOSING is the ( and - * NFA_END_COMPOSING is the ). Note that right now we are - * building the postfix form, not the NFA itself; - * a composing char could be: a, b, c, NFA_COMPOSING - * where 'b' and 'c' are chars with codes > 256. */ + // A base character plus composing characters, or just one + // or more composing characters. + // This requires creating a separate atom as if enclosing + // the characters in (), where NFA_COMPOSING is the ( and + // NFA_END_COMPOSING is the ). Note that right now we are + // building the postfix form, not the NFA itself; + // a composing char could be: a, b, c, NFA_COMPOSING + // where 'b' and 'c' are chars with codes > 256. */ for (;; ) { EMIT(c); if (i > 0) @@ -1954,7 +1957,7 @@ static int nfa_regpiece(void) break; } if (i == 0) { - emsgf(_("E869: (NFA) Unknown operator '\\@%c'"), op); + semsg(_("E869: (NFA) Unknown operator '\\@%c'"), op); return FAIL; } EMIT(i); @@ -2751,7 +2754,7 @@ static void st_error(int *postfix, int *end, int *p) fclose(df); } #endif - EMSG(_("E874: (NFA) Could not pop the stack!")); + emsg(_("E874: (NFA) Could not pop the stack!")); } /* @@ -2971,8 +2974,8 @@ static int nfa_max_width(nfa_state_T *startstate, int depth) if (state->c < 0) /* don't know what this is */ return -1; - /* normal character */ - len += MB_CHAR2LEN(state->c); + // normal character + len += utf_char2len(state->c); break; } @@ -3109,9 +3112,9 @@ static nfa_state_T *post2nfa(int *postfix, int *end, int nfa_calc_size) case NFA_END_COLL: case NFA_END_NEG_COLL: - /* On the stack is the sequence starting with NFA_START_COLL or - * NFA_START_NEG_COLL and all possible characters. Patch it to - * add the output to the start. */ + // On the stack is the sequence starting with NFA_START_COLL or + // NFA_START_NEG_COLL and all possible characters. Patch it to + // add the output to the start. if (nfa_calc_size == true) { nstate++; break; @@ -3233,12 +3236,12 @@ static nfa_state_T *post2nfa(int *postfix, int *end, int nfa_calc_size) if (before) n = *++p; /* get the count */ - /* The \@= operator: match the preceding atom with zero width. - * The \@! operator: no match for the preceding atom. - * The \@<= operator: match for the preceding atom. - * The \@<! operator: no match for the preceding atom. - * Surrounds the preceding atom with START_INVISIBLE and - * END_INVISIBLE, similarly to MOPEN. */ + // The \@= operator: match the preceding atom with zero width. + // The \@! operator: no match for the preceding atom. + // The \@<= operator: match for the preceding atom. + // The \@<! operator: no match for the preceding atom. + // Surrounds the preceding atom with START_INVISIBLE and + // END_INVISIBLE, similarly to MOPEN. if (nfa_calc_size == true) { nstate += pattern ? 4 : 2; @@ -3269,11 +3272,12 @@ static nfa_state_T *post2nfa(int *postfix, int *end, int nfa_calc_size) patch(e.out, s1); PUSH(frag(s, list1(&s1->out))); if (before) { - if (n <= 0) - /* See if we can guess the maximum width, it avoids a - * lot of pointless tries. */ + if (n <= 0) { + // See if we can guess the maximum width, it avoids a + // lot of pointless tries. n = nfa_max_width(e.start, 0); - s->val = n; /* store the count */ + } + s->val = n; // store the count } } break; @@ -3516,8 +3520,8 @@ static void nfa_postprocess(nfa_regprog_T *prog) directly = ch_follows * 10 < ch_invisible; } } else { - /* normal invisible, first do the one with the - * highest failure chance */ + // normal invisible, first do the one with the + // highest failure chance directly = ch_follows < ch_invisible; } } @@ -4012,8 +4016,8 @@ static regsubs_T *addstate( case NFA_ZEND: case NFA_SPLIT: case NFA_EMPTY: - /* These nodes are not added themselves but their "out" and/or - * "out1" may be added below. */ + // These nodes are not added themselves but their "out" and/or + // "out1" may be added below. break; case NFA_BOL: @@ -4051,21 +4055,20 @@ static regsubs_T *addstate( case NFA_ZOPEN9: case NFA_NOPEN: case NFA_ZSTART: - /* These nodes need to be added so that we can bail out when it - * was added to this list before at the same position to avoid an - * endless loop for "\(\)*" */ + // These nodes need to be added so that we can bail out when it + // was added to this list before at the same position to avoid an + // endless loop for "\(\)*" default: if (state->lastlist[nfa_ll_index] == l->id && state->c != NFA_SKIP) { - /* This state is already in the list, don't add it again, - * unless it is an MOPEN that is used for a backreference or - * when there is a PIM. For NFA_MATCH check the position, - * lower position is preferred. */ + // This state is already in the list, don't add it again, + // unless it is an MOPEN that is used for a backreference or + // when there is a PIM. For NFA_MATCH check the position, + // lower position is preferred. if (!rex.nfa_has_backref && pim == NULL && !l->has_pim && state->c != NFA_MATCH) { - - /* When called from addstate_here() do insert before - * existing states. */ + // 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) { @@ -4088,10 +4091,11 @@ skip_add: } } - /* Do not add the state again when it exists with the same - * positions. */ - if (has_state_with_pos(l, state, subs, pim)) + // Do not add the state again when it exists with the same + // positions. + if (has_state_with_pos(l, state, subs, pim)) { goto skip_add; + } } // When there are backreferences or PIMs the number of states may @@ -4101,7 +4105,7 @@ skip_add: const size_t newsize = newlen * sizeof(nfa_thread_T); if ((long)(newsize >> 10) >= p_mmp) { - EMSG(_(e_maxmempat)); + emsg(_(e_maxmempat)); depth--; return NULL; } @@ -4362,9 +4366,9 @@ static regsubs_T *addstate_here( int count; int listidx = *ip; - /* 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(). */ + // 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(). regsubs_T *r = addstate(l, state, subs, pim, -listidx - ADDSTATE_HERE_OFFSET); if (r == NULL) { return NULL; @@ -4385,13 +4389,13 @@ static regsubs_T *addstate_here( l->t[listidx] = l->t[l->n - 1]; } else if (count > 1) { if (l->n + count - 1 >= l->len) { - /* not enough space to move the new states, reallocate the list - * and move the states to the right position */ + // not enough space to move the new states, reallocate the list + // and move the states to the right position const int newlen = l->len * 3 / 2 + 50; const size_t newsize = newlen * sizeof(nfa_thread_T); if ((long)(newsize >> 10) >= p_mmp) { - EMSG(_(e_maxmempat)); + emsg(_(e_maxmempat)); return NULL; } nfa_thread_T *const newl = xmalloc(newsize); @@ -4408,8 +4412,8 @@ static regsubs_T *addstate_here( xfree(l->t); l->t = newl; } else { - /* make space for new states, then move them from the - * end to the current position */ + // make space for new states, then move them from the + // end to the current position memmove(&(l->t[listidx + count]), &(l->t[listidx + 1]), sizeof(nfa_thread_T) * (l->n - listidx - 1)); @@ -4520,7 +4524,7 @@ static int check_char_class(int class, int c) default: // should not be here :P - IEMSGN(_(e_ill_char_class), class); + siemsg(_(e_ill_char_class), (int64_t)class); return FAIL; } return FAIL; @@ -4797,7 +4801,7 @@ static int recursive_regmatch( fprintf(log_fd, "MATCH = %s\n", !result ? "false" : "OK"); fprintf(log_fd, "****************************\n"); } else { - EMSG(_(e_log_open_failed)); + emsg(_(e_log_open_failed)); log_fd = stderr; } #endif @@ -4994,9 +4998,9 @@ static long find_match_text(colnr_T startcol, int regstart, char_u *match_text) char_u *s2 = rex.line + col + regstart_len; // skip regstart while (*s1) { int c1_len = PTR2LEN(s1); - int c1 = PTR2CHAR(s1); + int c1 = utf_ptr2char(s1); int c2_len = PTR2LEN(s2); - int c2 = PTR2CHAR(s2); + int c2 = utf_ptr2char(s2); if ((c1 != c2 && (!rex.reg_ic || utf_fold(c1) != utf_fold(c2))) || c1_len != c2_len) { @@ -5008,7 +5012,7 @@ static long find_match_text(colnr_T startcol, int regstart, char_u *match_text) } if (match // check that no composing char follows - && !utf_iscomposing(PTR2CHAR(s2))) { + && !utf_iscomposing(utf_ptr2char(s2))) { cleanup_subexpr(); if (REG_MULTI) { rex.reg_startpos[0].lnum = rex.lnum; @@ -5079,7 +5083,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, FILE *debug = fopen(NFA_REGEXP_DEBUG_LOG, "a"); if (debug == NULL) { - EMSG2("(NFA) COULD NOT OPEN %s!", NFA_REGEXP_DEBUG_LOG); + semsg("(NFA) COULD NOT OPEN %s!", NFA_REGEXP_DEBUG_LOG); return false; } #endif @@ -5117,7 +5121,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, abs(start->id), code); fprintf(log_fd, "**********************************\n"); } else { - EMSG(_(e_log_open_failed)); + emsg(_(e_log_open_failed)); log_fd = stderr; } #endif @@ -5618,7 +5622,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, // Only match composing character(s), ignore base // character. Used for ".{composing}" and "{composing}" // (no preceding character). - len += mb_char2len(mc); + len += utf_char2len(mc); } if (rex.reg_icombine && len == 0) { // If \Z was present, then ignore composing characters. @@ -5634,7 +5638,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, } else if (len > 0 || mc == sta->c) { // Check base character matches first, unless ignored. if (len == 0) { - len += mb_char2len(mc); + len += utf_char2len(mc); sta = sta->out; } @@ -5643,9 +5647,10 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, while (len < clen) { mc = utf_ptr2char(rex.input + len); cchars[ccount++] = mc; - len += mb_char2len(mc); - if (ccount == MAX_MCO) + len += utf_char2len(mc); + if (ccount == MAX_MCO) { break; + } } // Check that each composing char in the pattern matches a @@ -5805,12 +5810,12 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, break; case NFA_PRINT: // \p - result = vim_isprintc(PTR2CHAR(rex.input)); + result = vim_isprintc(utf_ptr2char(rex.input)); ADD_STATE_IF_MATCH(t->state); break; case NFA_SPRINT: // \P - result = !ascii_isdigit(curc) && vim_isprintc(PTR2CHAR(rex.input)); + result = !ascii_isdigit(curc) && vim_isprintc(utf_ptr2char(rex.input)); ADD_STATE_IF_MATCH(t->state); break; @@ -6143,7 +6148,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, #ifdef REGEXP_DEBUG if (c < 0) { - IEMSGN("INTERNAL: Negative state char: %" PRId64, c); + siemsg("INTERNAL: Negative state char: %" PRId64, (int64_t)c); } #endif result = (c == curc); @@ -6303,7 +6308,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, } else { // Checking if the required start character matches is // cheaper than adding a state that won't match. - const int c = PTR2CHAR(rex.input + clen); + const int c = utf_ptr2char(rex.input + clen); if (c != prog->regstart && (!rex.reg_ic || utf_fold(c) != utf_fold(prog->regstart))) { @@ -6425,7 +6430,7 @@ static long nfa_regtry(nfa_regprog_T *prog, fprintf(f, "\n\n"); fclose(f); } else { - EMSG("Could not open temporary log file for writing"); + emsg("Could not open temporary log file for writing"); } #endif @@ -6540,7 +6545,7 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, /* Be paranoid... */ if (prog == NULL || line == NULL) { - IEMSG(_(e_null)); + iemsg(_(e_null)); goto theend; } @@ -6582,10 +6587,11 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, } if (prog->regstart != NUL) { - /* Skip ahead until a character we know the match must start with. - * When there is none there is no match. */ - if (skip_to_start(prog->regstart, &col) == FAIL) + // Skip ahead until a character we know the match must start with. + // When there is none there is no match. + 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. diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 5ade6244f9..674d807e96 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -146,7 +146,7 @@ int do_in_path(char_u *path, char *name, int flags, DoInRuntimepathCB callback, char *basepath = path == p_rtp ? "runtimepath" : "packpath"; if (flags & DIP_ERR) { - EMSG3(_(e_dirnotf), basepath, name); + semsg(_(e_dirnotf), basepath, name); } else if (p_verbose > 0) { verbose_enter(); smsg(_("not found in '%s': \"%s\""), basepath, name); @@ -268,7 +268,7 @@ int do_in_cached_path(char_u *name, int flags, DoInRuntimepathCB callback, void if (!did_one && name != NULL) { if (flags & DIP_ERR) { - EMSG3(_(e_dirnotf), "runtime path", name); + semsg(_(e_dirnotf), "runtime path", name); } else if (p_verbose > 0) { verbose_enter(); smsg(_("not found in runtime path: \"%s\""), name); @@ -439,16 +439,16 @@ static void expand_rtp_entry(RuntimeSearchPath *search_path, Map(String, handle_ } static void expand_pack_entry(RuntimeSearchPath *search_path, Map(String, handle_T) *rtp_used, - CharVec *after_path, char_u *pack_entry) + CharVec *after_path, char_u *pack_entry, size_t pack_entry_len) { static char buf[MAXPATHL]; char *(start_pat[]) = { "/pack/*/start/*", "/start/*" }; // NOLINT for (int i = 0; i < 2; i++) { - if (STRLEN(pack_entry) + STRLEN(start_pat[i]) + 1 > MAXPATHL) { + if (pack_entry_len + STRLEN(start_pat[i]) + 1 > sizeof buf) { continue; } - STRLCPY(buf, pack_entry, MAXPATHL); - xstrlcat(buf, start_pat[i], sizeof buf); + STRLCPY(buf, pack_entry, sizeof buf); + STRLCPY(buf + pack_entry_len, start_pat[i], sizeof buf - pack_entry_len); expand_rtp_entry(search_path, rtp_used, buf, false); size_t after_size = STRLEN(buf)+7; char *after = xmallocz(after_size); @@ -507,14 +507,15 @@ RuntimeSearchPath runtime_search_path_build(void) handle_T *h = map_ref(String, handle_T)(&pack_used, cstr_as_string((char *)buf), false); if (h) { (*h)++; - expand_pack_entry(&search_path, &rtp_used, &after_path, buf); + expand_pack_entry(&search_path, &rtp_used, &after_path, buf, buflen); } } for (size_t i = 0; i < kv_size(pack_entries); i++) { - handle_T h = map_get(String, handle_T)(&pack_used, kv_A(pack_entries, i)); + String item = kv_A(pack_entries, i); + handle_T h = map_get(String, handle_T)(&pack_used, item); if (h == 0) { - expand_pack_entry(&search_path, &rtp_used, &after_path, (char_u *)kv_A(pack_entries, i).data); + expand_pack_entry(&search_path, &rtp_used, &after_path, (char_u *)item.data, item.size); } } @@ -573,7 +574,6 @@ void runtime_search_path_validate(void) } - /// Just like do_in_path_and_pp(), using 'runtimepath' for "path". int do_in_runtimepath(char_u *name, int flags, DoInRuntimepathCB callback, void *cookie) { diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 32eb28e761..63e904079e 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -65,6 +65,7 @@ #include <stdbool.h> #include <string.h> +#include "nvim/api/extmark.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" #include "nvim/arabic.h" @@ -694,7 +695,7 @@ void conceal_check_cursor_line(void) if (curwin->w_p_cole > 0 && (conceal_cursor_used != should_conceal)) { redrawWinline(curwin, curwin->w_cursor.lnum); // Need to recompute cursor column, e.g., when starting Visual mode - // without concealing. */ + // without concealing. curs_columns(curwin, true); } } @@ -1951,7 +1952,7 @@ static size_t fill_foldcolumn(char_u *p, win_T *wp, foldinfo_T foldinfo, linenr_ first_level = 1; } - for (i = 0; i < MIN(fdc, level); i++) { + for (i = 0; i < MIN(fdc, level); i++) { if (foldinfo.fi_lnum == lnum && first_level + i >= foldinfo.fi_low_level) { symbol = wp->w_p_fcs_chars.foldopen; @@ -2372,11 +2373,12 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc filler_lines = 0; area_highlighting = true; } - int virtual_lines = decor_virtual_lines(wp, lnum); - filler_lines += virtual_lines; + VirtLines virt_lines = KV_INITIAL_VALUE; + int n_virt_lines = decor_virt_lines(wp, lnum, &virt_lines); + filler_lines += n_virt_lines; if (lnum == wp->w_topline) { filler_lines = wp->w_topfill; - virtual_lines = MIN(virtual_lines, filler_lines); + n_virt_lines = MIN(n_virt_lines, filler_lines); } filler_todo = filler_lines; @@ -2669,7 +2671,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc // Highlight one character for an empty match. if (shl->startcol == shl->endcol) { if (line[shl->endcol] != NUL) { - shl->endcol += (*mb_ptr2len)(line + shl->endcol); + shl->endcol += utfc_ptr2len(line + shl->endcol); } else { ++shl->endcol; } @@ -2904,7 +2906,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc if (draw_state == WL_SBR - 1 && n_extra == 0) { draw_state = WL_SBR; - if (filler_todo > filler_lines - virtual_lines) { + if (filler_todo > filler_lines - n_virt_lines) { // TODO(bfredl): check this doesn't inhibit TUI-style // clear-to-end-of-line. c_extra = ' '; @@ -2942,7 +2944,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc if (wp->w_skipcol == 0 || !wp->w_p_wrap) { need_showbreak = false; } - vcol_sbr = vcol + MB_CHARLEN(sbr); + vcol_sbr = vcol + mb_charlen(sbr); // Correct end of highlighted area for 'showbreak', // required when 'linebreak' is also set. if (tocol == vcol) { @@ -3143,7 +3145,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc if (shl->startcol == shl->endcol) { // highlight empty match, try again after it - shl->endcol += (*mb_ptr2len)(line + shl->endcol); + shl->endcol += utfc_ptr2len(line + shl->endcol); } // Loop to check if the match starts at the @@ -3242,7 +3244,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc // represent special characters (non-printable stuff) and other // things. When all characters are the same, c_extra is used. // If c_final is set, it will compulsorily be used at the end. - // "p_extra" must end in a NUL to avoid mb_ptr2len() reads past + // "p_extra" must end in a NUL to avoid utfc_ptr2len() reads past // "p_extra[n_extra]". // For the '$' of the 'list' option, n_extra == 1, p_extra == "". if (n_extra > 0) { @@ -3277,7 +3279,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc // If a double-width char doesn't fit display a '>' in the last column. if ((wp->w_p_rl ? (col <= 0) : (col >= grid->Columns - 1)) - && (*mb_char2cells)(mb_c) == 2) { + && utf_char2cells(mb_c) == 2) { c = '>'; mb_c = c; mb_l = 1; @@ -3391,7 +3393,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc // next line. if ((wp->w_p_rl ? (col <= 0) : (col >= grid->Columns - 1)) - && (*mb_char2cells)(mb_c) == 2) { + && utf_char2cells(mb_c) == 2) { c = '>'; mb_c = c; mb_utf8 = false; @@ -3580,7 +3582,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc // We have just drawn the showbreak value, no need to add // space for it again. if (vcol == vcol_sbr) { - n_extra -= MB_CHARLEN(get_showbreak_value(wp)); + n_extra -= mb_charlen(get_showbreak_value(wp)); if (n_extra < 0) { n_extra = 0; } @@ -3676,7 +3678,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc // Only adjust the tab_len, when at the first column after the // showbreak value was drawn. if (*sbr != NUL && vcol == vcol_sbr && wp->w_p_wrap) { - vcol_adjusted = vcol - MB_CHARLEN(sbr); + vcol_adjusted = vcol - mb_charlen(sbr); } // tab amount depends on current column tab_len = tabstop_padding(vcol_adjusted, @@ -3703,7 +3705,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc // if n_extra > 0, it gives the number of chars // to use for a tab, else we need to calculate the width // for a tab - int len = (tab_len * mb_char2len(wp->w_p_lcs_chars.tab2)); + int len = (tab_len * utf_char2len(wp->w_p_lcs_chars.tab2)); if (n_extra > 0) { len += n_extra - tab_len; } @@ -3726,8 +3728,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc lcs = wp->w_p_lcs_chars.tab3; } utf_char2bytes(lcs, p); - p += mb_char2len(lcs); - n_extra += mb_char2len(lcs) - (saved_nextra > 0 ? 1 : 0); + p += utf_char2len(lcs); + n_extra += utf_char2len(lcs) - (saved_nextra > 0 ? 1 : 0); } p_extra = p_extra_free; @@ -3962,7 +3964,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc && c != NUL) { c = wp->w_p_lcs_chars.prec; lcs_prec_todo = NUL; - if ((*mb_char2cells)(mb_c) > 1) { + if (utf_char2cells(mb_c) > 1) { // Double-width character being overwritten by the "precedes" // character, need to fill up half the character. c_extra = MB_FILLER_CHAR; @@ -4273,7 +4275,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc // // Store the character. // - if (wp->w_p_rl && (*mb_char2cells)(mb_c) > 1) { + if (wp->w_p_rl && utf_char2cells(mb_c) > 1) { // A double-wide character is: put first halve in left cell. off--; col--; @@ -4290,7 +4292,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc linebuf_attr[off] = char_attr; } - if ((*mb_char2cells)(mb_c) > 1) { + if (utf_char2cells(mb_c) > 1) { // Need to fill two screen columns. off++; col++; @@ -4351,7 +4353,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc } - if ((*mb_char2cells)(mb_c) > 1) { + if (utf_char2cells(mb_c) > 1) { // Need to fill two screen columns. if (wp->w_p_rl) { --boguscols; @@ -4423,12 +4425,12 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc int draw_col = col - boguscols; if (filler_todo > 0) { - int index = filler_todo - (filler_lines - virtual_lines); + int index = filler_todo - (filler_lines - n_virt_lines); if (index > 0) { - int fpos = kv_size(buf->b_virt_lines) - index; - assert(fpos >= 0); - int offset = buf->b_virt_line_leftcol ? 0 : win_col_offset; - draw_virt_text_item(buf, offset, kv_A(buf->b_virt_lines, fpos), + int i = kv_size(virt_lines) - index; + assert(i >= 0); + int offset = kv_A(virt_lines, i).left_col ? 0 : win_col_offset; + draw_virt_text_item(buf, offset, kv_A(virt_lines, i).line, kHlModeReplace, grid->Columns, offset); } } else { @@ -4506,6 +4508,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc cap_col = 0; } + kv_destroy(virt_lines); xfree(p_extra_free); return row; } @@ -4827,8 +4830,8 @@ static void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, } if (clear_next) { - /* Clear the second half of a double-wide character of which the left - * half was overwritten with a single-wide character. */ + // Clear the second half of a double-wide character of which the left + // half was overwritten with a single-wide character. schar_from_ascii(grid->chars[off_to], ' '); end_dirty++; } @@ -5131,7 +5134,7 @@ void win_redr_status_matches(expand_T *xp, int num_matches, char_u **matches, in for (; *s != NUL; ++s) { s += skip_status_match_char(xp, s); clen += ptr2cells(s); - if ((l = (*mb_ptr2len)(s)) > 1) { + if ((l = utfc_ptr2len(s)) > 1) { STRNCPY(buf + len, s, l); // NOLINT(runtime/printf) s += l - 1; len += l; @@ -5175,9 +5178,9 @@ void win_redr_status_matches(expand_T *xp, int num_matches, char_u **matches, in } wild_menu_showing = WM_SCROLLED; } else { - /* Create status line if needed by setting 'laststatus' to 2. - * Set 'winminheight' to zero to avoid that the window is - * resized. */ + // Create status line if needed by setting 'laststatus' to 2. + // Set 'winminheight' to zero to avoid that the window is + // resized. if (lastwin->w_status_height == 0) { save_p_ls = p_ls; save_p_wmh = p_wmh; @@ -5652,7 +5655,9 @@ static void win_redr_border(win_T *wp) int ic = (i == 0 && !adj[3] && chars[6][0]) ? 6 : 5; grid_put_schar(grid, irow+adj[0], i+adj[3], chars[ic], attrs[ic]); } - grid_put_schar(grid, irow+adj[0], icol+adj[3], chars[4], attrs[4]); + if (adj[1]) { + grid_put_schar(grid, irow+adj[0], icol+adj[3], chars[4], attrs[4]); + } grid_puts_line_flush(false); } } @@ -6078,7 +6083,7 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum) || (cur != NULL && pos_inprogress))) { next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n, shl == &search_hl ? NULL : cur); - pos_inprogress = !(cur == NULL || cur->pos.cur == 0); + pos_inprogress = !(cur == NULL || cur->pos.cur == 0); if (shl->lnum != 0) { shl->first_lnum = shl->lnum + shl->rm.endpos[0].lnum @@ -6164,7 +6169,7 @@ static void next_search_hl(win_T *win, match_T *shl, linenr_T lnum, colnr_T minc shl->lnum = 0; break; } - matchcol += mb_ptr2len(ml); + matchcol += utfc_ptr2len(ml); } else { matchcol = shl->rm.endpos[0].col; } @@ -6722,7 +6727,6 @@ bool grid_invalid_row(ScreenGrid *grid, int row) } - /// Copy part of a grid line for vertically split window. static void linecopy(ScreenGrid *grid, int to, int from, int col, int width) { @@ -6959,7 +6963,7 @@ int showmode(void) lines_left = 0; if (do_mode) { - MSG_PUTS_ATTR("--", attr); + msg_puts_attr("--", attr); // CTRL-X in Insert mode if (edit_submode != NULL && !shortmess(SHM_COMPLETIONMENU)) { // These messages can get long, avoid a wrap in a narrow window. @@ -6984,7 +6988,7 @@ int showmode(void) msg_puts_attr((const char *)edit_submode, attr); } if (edit_submode_extra != NULL) { - MSG_PUTS_ATTR(" ", attr); // Add a space in between. + msg_puts_attr(" ", attr); // Add a space in between. if ((int)edit_submode_highl < HLF_COUNT) { sub_attr = win_hl_attr(curwin, edit_submode_highl); } else { @@ -6995,37 +6999,37 @@ int showmode(void) } } else { if (State & TERM_FOCUS) { - MSG_PUTS_ATTR(_(" TERMINAL"), attr); + msg_puts_attr(_(" TERMINAL"), attr); } else if (State & VREPLACE_FLAG) { - MSG_PUTS_ATTR(_(" VREPLACE"), attr); + msg_puts_attr(_(" VREPLACE"), attr); } else if (State & REPLACE_FLAG) { - MSG_PUTS_ATTR(_(" REPLACE"), attr); + msg_puts_attr(_(" REPLACE"), attr); } else if (State & INSERT) { if (p_ri) { - MSG_PUTS_ATTR(_(" REVERSE"), attr); + msg_puts_attr(_(" REVERSE"), attr); } - MSG_PUTS_ATTR(_(" INSERT"), attr); + msg_puts_attr(_(" INSERT"), attr); } else if (restart_edit == 'I' || restart_edit == 'i' || restart_edit == 'a') { - MSG_PUTS_ATTR(_(" (insert)"), attr); + msg_puts_attr(_(" (insert)"), attr); } else if (restart_edit == 'R') { - MSG_PUTS_ATTR(_(" (replace)"), attr); + msg_puts_attr(_(" (replace)"), attr); } else if (restart_edit == 'V') { - MSG_PUTS_ATTR(_(" (vreplace)"), attr); + msg_puts_attr(_(" (vreplace)"), attr); } if (p_hkmap) { - MSG_PUTS_ATTR(_(" Hebrew"), attr); + msg_puts_attr(_(" Hebrew"), attr); } if (State & LANGMAP) { if (curwin->w_p_arab) { - MSG_PUTS_ATTR(_(" Arabic"), attr); + msg_puts_attr(_(" Arabic"), attr); } else if (get_keymap_str(curwin, (char_u *)" (%s)", NameBuff, MAXPATHL)) { - MSG_PUTS_ATTR(NameBuff, attr); + msg_puts_attr((char *)NameBuff, attr); } } if ((State & INSERT) && p_paste) { - MSG_PUTS_ATTR(_(" (paste)"), attr); + msg_puts_attr(_(" (paste)"), attr); } if (VIsual_active) { @@ -7049,9 +7053,9 @@ int showmode(void) default: p = N_(" SELECT BLOCK"); break; } - MSG_PUTS_ATTR(_(p), attr); + msg_puts_attr(_(p), attr); } - MSG_PUTS_ATTR(" --", attr); + msg_puts_attr(" --", attr); } need_clear = TRUE; @@ -7140,11 +7144,11 @@ void clearmode(void) static void recording_mode(int attr) { - MSG_PUTS_ATTR(_("recording"), attr); + msg_puts_attr(_("recording"), attr); if (!shortmess(SHM_RECORDING)) { - char_u s[4]; - snprintf((char *)s, ARRAY_SIZE(s), " @%c", reg_recording); - MSG_PUTS_ATTR(s, attr); + char s[4]; + snprintf(s, ARRAY_SIZE(s), " @%c", reg_recording); + msg_puts_attr(s, attr); } } @@ -7324,8 +7328,8 @@ void draw_tabline(void) } } - /* Reset the flag here again, in case evaluating 'tabline' causes it to be - * set. */ + // Reset the flag here again, in case evaluating 'tabline' causes it to be + // set. redraw_tabline = false; } @@ -7390,9 +7394,9 @@ int fillchar_status(int *attr, win_T *wp) *attr = win_hl_attr(wp, HLF_SNC); fill = wp->w_p_fcs_chars.stlnc; } - /* Use fill when there is highlighting, and highlighting of current - * window differs, or the fillchars differ, or this is not the - * current window */ + // 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 && ((win_hl_attr(wp, HLF_S) != win_hl_attr(wp, HLF_SNC) || !is_curwin || ONE_WINDOW) || (wp->w_p_fcs_chars.stl != wp->w_p_fcs_chars.stlnc))) { diff --git a/src/nvim/search.c b/src/nvim/search.c index 1b54d12042..0756fbf37d 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -144,9 +144,9 @@ int search_regcomp(char_u *pat, int pat_save, int pat_use, int options, regmmatc } if (spats[i].pat == NULL) { // pattern was never defined if (pat_use == RE_SUBST) { - EMSG(_(e_nopresub)); + emsg(_(e_nopresub)); } else { - EMSG(_(e_noprevre)); + emsg(_(e_noprevre)); } rc_did_emsg = true; return FAIL; @@ -386,7 +386,7 @@ bool pat_has_uppercase(char_u *pat) char_u *p = pat; while (*p != NUL) { - const int l = mb_ptr2len(p); + const int l = utfc_ptr2len(p); if (l > 1) { if (mb_isupper(utf_ptr2char(p))) { @@ -577,7 +577,7 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, if (search_regcomp(pat, RE_SEARCH, pat_use, (options & (SEARCH_HIS + SEARCH_KEEP)), ®match) == FAIL) { if ((options & SEARCH_MSG) && !rc_did_emsg) { - EMSG2(_("E383: Invalid search string: %s"), mr_pattern); + semsg(_("E383: Invalid search string: %s"), mr_pattern); } return FAIL; } @@ -699,8 +699,8 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, */ if (vim_strchr(p_cpo, CPO_SEARCH) != NULL) { if (nmatched > 1) { - /* end is in next line, thus no match in - * this line */ + // end is in next line, thus no match in + // this line match_ok = false; break; } @@ -758,10 +758,10 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, */ match_ok = false; for (;; ) { - /* Remember a position that is before the start - * position, we use it if it's the last match in - * the line. Always accept a position after - * wrapping around. */ + // Remember a position that is before the start + // position, we use it if it's the last match in + // the line. Always accept a position after + // wrapping around. if (loop || ((options & SEARCH_END) ? (lnum + regmatch.endpos[0].lnum @@ -797,7 +797,7 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, // for empty match: advance one char if (matchcol == matchpos.col && ptr[matchcol] != NUL) { - matchcol += mb_ptr2len(ptr + matchcol); + matchcol += utfc_ptr2len(ptr + matchcol); } } else { // Stop when the match is in a next line. @@ -806,7 +806,7 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, } matchcol = matchpos.col; if (ptr[matchcol] != NUL) { - matchcol += mb_ptr2len(ptr + matchcol); + matchcol += utfc_ptr2len(ptr + matchcol); } } if (ptr[matchcol] == NUL @@ -890,9 +890,9 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, break; } - /* Cancel searching if a character was typed. Used for - * 'incsearch'. Don't check too often, that would slowdown - * searching too much. */ + // Cancel searching if a character was typed. Used for + // 'incsearch'. Don't check too often, that would slowdown + // searching too much. if ((options & SEARCH_PEEK) && ((lnum - pos->lnum) & 0x3f) == 0 && char_avail()) { @@ -953,15 +953,15 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, if (!found) { // did not find it if (got_int) { - EMSG(_(e_interr)); + emsg(_(e_interr)); } else if ((options & SEARCH_MSG) == SEARCH_MSG) { if (p_ws) { - EMSG2(_(e_patnotf2), mr_pattern); + semsg(_(e_patnotf2), mr_pattern); } else if (lnum == 0) { - EMSG2(_("E384: search hit TOP without match for: %s"), + semsg(_("E384: search hit TOP without match for: %s"), mr_pattern); } else { - EMSG2(_("E385: search hit BOTTOM without match for: %s"), + semsg(_("E385: search hit BOTTOM without match for: %s"), mr_pattern); } } @@ -1082,8 +1082,8 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count, } } - /* If the cursor is in a closed fold, don't find another match in the same - * fold. */ + // If the cursor is in a closed fold, don't find another match in the same + // fold. if (dirc == '/') { if (hasFolding(pos.lnum, NULL, &pos.lnum)) { pos.col = MAXCOL - 2; // avoid overflow when adding 1 @@ -1115,7 +1115,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count, if (spats[RE_SEARCH].pat == NULL) { // no previous pattern searchstr = spats[RE_SUBST].pat; if (searchstr == NULL) { - EMSG(_(e_noprevre)); + emsg(_(e_noprevre)); retval = 0; goto end_do_search; } @@ -1426,7 +1426,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count, search_delim = dirc; if (dirc != '?' && dirc != '/') { retval = 0; - EMSG(_("E386: Expected '?' or '/' after ';'")); + emsg(_("E386: Expected '?' or '/' after ';'")); goto end_do_search; } ++pat; @@ -1871,7 +1871,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) --pos.col; } for (;; ) { - initc = PTR2CHAR(linep + pos.col); + initc = utf_ptr2char(linep + pos.col); if (initc == NUL) { break; } @@ -1892,8 +1892,8 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) } else if (!cpo_bsl) { int col, bslcnt = 0; - /* Set "match_escaped" if there are an odd number of - * backslashes. */ + // Set "match_escaped" if there are an odd number of + // backslashes. for (col = pos.col; check_prevcol(linep, col, '\\', &col); ) { bslcnt++; } @@ -2033,8 +2033,8 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) || (lisp && comment_col != MAXCOL && pos.col == (colnr_T)comment_col)) { if (pos.lnum == curbuf->b_ml.ml_line_count // end of file - /* line is exhausted and comment with it, - * don't search for match in code */ + // line is exhausted and comment with it, + // don't search for match in code || lispcomm) { break; } @@ -2197,7 +2197,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) * inquote if the number of quotes in a line is even, unless this * line or the previous one ends in a '\'. Complicated, isn't it? */ - const int c = PTR2CHAR(linep + pos.col); + const int c = utf_ptr2char(linep + pos.col); switch (c) { case NUL: // at end of line without trailing backslash, reset inquote @@ -2271,8 +2271,8 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) break; } - /* Check for match outside of quotes, and inside of - * quotes when the start is also inside of quotes. */ + // Check for match outside of quotes, and inside of + // quotes when the start is also inside of quotes. if ((!inquote || start_in_quotes == kTrue) && (c == initc || c == findc)) { int col, bslcnt = 0; @@ -2340,8 +2340,8 @@ static int check_linecomment(const char_u *line) } } else { while ((p = vim_strchr(p, '/')) != NULL) { - /* accept a double /, unless it's preceded with * and followed by *, - * because * / / * is an end and start of a C comment */ + // accept a double /, unless it's preceded with * and followed by *, + // because * / / * is an end and start of a C comment if (p[1] == '/' && (p == line || p[-1] != '*' || p[2] != '*')) { break; } @@ -2378,12 +2378,12 @@ void showmatch(int c) * Only show match for chars in the 'matchpairs' option. */ // 'matchpairs' is "x:y,x:y" - for (p = curbuf->b_p_mps; *p != NUL; ++p) { - if (PTR2CHAR(p) == c && (curwin->w_p_rl ^ p_ri)) { + for (p = curbuf->b_p_mps; *p != NUL; p++) { + if (utf_ptr2char(p) == c && (curwin->w_p_rl ^ p_ri)) { break; } p += utfc_ptr2len(p) + 1; - if (PTR2CHAR(p) == c && !(curwin->w_p_rl ^ p_ri)) { + if (utf_ptr2char(p) == c && !(curwin->w_p_rl ^ p_ri)) { break; } p += utfc_ptr2len(p); @@ -2427,9 +2427,9 @@ void showmatch(int c) showruler(false); setcursor(); ui_flush(); - /* Restore dollar_vcol(), because setcursor() may call curs_rows() - * which resets it if the matching position is in a previous line - * and has a higher column number. */ + // Restore dollar_vcol(), because setcursor() may call curs_rows() + // which resets it if the matching position is in a previous line + // and has a higher column number. dollar_vcol = save_dollar_vcol; /* @@ -2530,13 +2530,14 @@ int findsent(Direction dir, long count) } if (c == '.' || c == '!' || c == '?') { tpos = pos; - do + do{ if ((c = inc(&tpos)) == -1) { break; } + } while (vim_strchr((char_u *)")]\"'", c = gchar_pos(&tpos)) != NULL); - if (c == -1 || (!cpo_J && (c == ' ' || c == '\t')) || c == NUL + if (c == -1 || (!cpo_J && (c == ' ' || c == '\t')) || c == NUL || (cpo_J && (c == ' ' && inc(&tpos) >= 0 && gchar_pos(&tpos) == ' '))) { pos = tpos; @@ -2595,8 +2596,8 @@ bool findpar(bool *pincl, int dir, long count, int what, int both) bool first; // true on first line linenr_T fold_first; // first line of a closed fold linenr_T fold_last; // last line of a closed fold - bool fold_skipped; /* true if a closed fold was skipped this - iteration */ + bool fold_skipped; // true if a closed fold was skipped this + // iteration curr = curwin->w_cursor.lnum; @@ -2658,16 +2659,16 @@ static int inmacro(char_u *opt, char_u *s) { char_u *macro; - for (macro = opt; macro[0]; ++macro) { - /* Accept two characters in the option being equal to two characters - * in the line. A space in the option matches with a space in the - * line or the line having ended. */ - if ( (macro[0] == s[0] - || (macro[0] == ' ' - && (s[0] == NUL || s[0] == ' '))) - && (macro[1] == s[1] - || ((macro[1] == NUL || macro[1] == ' ') - && (s[0] == NUL || s[1] == NUL || s[1] == ' ')))) { + for (macro = opt; macro[0]; macro++) { + // Accept two characters in the option being equal to two characters + // in the line. A space in the option matches with a space in the + // line or the line having ended. + if ((macro[0] == s[0] + || (macro[0] == ' ' + && (s[0] == NUL || s[0] == ' '))) + && (macro[1] == s[1] + || ((macro[1] == NUL || macro[1] == ' ') + && (s[0] == NUL || s[1] == NUL || s[1] == ' ')))) { break; } ++macro; @@ -2756,8 +2757,8 @@ int fwd_word(long count, int bigword, int eol) curwin->w_cursor.coladd = 0; cls_bigword = bigword; while (--count >= 0) { - /* When inside a range of folded lines, move to the last char of the - * last line. */ + // When inside a range of folded lines, move to the last char of the + // last line. if (hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum)) { coladvance(MAXCOL); } @@ -3675,9 +3676,9 @@ again: xfree(epat); if (r < 1 || lt(curwin->w_cursor, old_end)) { - /* Can't find other end or it's before the previous end. Could be a - * HTML tag that doesn't have a matching end. Search backwards for - * another starting tag. */ + // Can't find other end or it's before the previous end. Could be a + // HTML tag that doesn't have a matching end. Search backwards for + // another starting tag. count = 1; curwin->w_cursor = start_pos; goto again; @@ -3729,8 +3730,8 @@ again: } if (VIsual_active) { - /* If the end is before the start there is no text between tags, select - * the char under the cursor. */ + // If the end is before the start there is no text between tags, select + // the char under the cursor. if (lt(end_pos, start_pos)) { curwin->w_cursor = start_pos; } else if (*p_sel == 'e') { @@ -3744,8 +3745,8 @@ again: oap->start = start_pos; oap->motion_type = kMTCharWise; if (lt(end_pos, start_pos)) { - /* End is before the start: there is no text between tags; operate - * on an empty area. */ + // End is before the start: there is no text between tags; operate + // on an empty area. curwin->w_cursor = start_pos; oap->inclusive = false; } else { @@ -3954,7 +3955,7 @@ static int find_next_quote(char_u *line, int col, int quotechar, char_u *escape) } else if (c == quotechar) { break; } - col += mb_ptr2len(line + col); + col += utfc_ptr2len(line + col); } return col; } @@ -4112,10 +4113,10 @@ bool current_quote(oparg_T *oap, long count, bool include, int quotechar) first_col = find_prev_quote(line, col_start, quotechar, NULL); } } - /* The cursor is on a quote, we don't know if it's the opening or - * closing quote. Search from the start of the line to find out. - * Also do this when there is a Visual area, a' may leave the cursor - * in between two strings. */ + // The cursor is on a quote, we don't know if it's the opening or + // closing quote. Search from the start of the line to find out. + // Also do this when there is a Visual area, a' may leave the cursor + // in between two strings. col_start = 0; for (;; ) { // Find open quote character. @@ -4169,18 +4170,17 @@ bool current_quote(oparg_T *oap, long count, bool include, int quotechar) } } - /* Set start position. After vi" another i" must include the ". - * For v2i" include the quotes. */ + // Set start position. After vi" another i" must include the ". + // For v2i" include the quotes. if (!include && count < 2 && (vis_empty || !inside_quotes)) { ++col_start; } curwin->w_cursor.col = col_start; if (VIsual_active) { - /* Set the start of the Visual area when the Visual area was empty, we - * were just inside quotes or the Visual area didn't start at a quote - * and didn't include a quote. - */ + // Set the start of the Visual area when the Visual area was empty, we + // were just inside quotes or the Visual area didn't start at a quote + // and didn't include a quote. if (vis_empty || (vis_bef_curs && !selected_quote @@ -4211,9 +4211,9 @@ bool current_quote(oparg_T *oap, long count, bool include, int quotechar) dec_cursor(); } } else { - /* Cursor is at start of Visual area. Set the end of the Visual - * area when it was just inside quotes or it didn't end at a - * quote. */ + // Cursor is at start of Visual area. Set the end of the Visual + // area when it was just inside quotes or it didn't end at a + // quote. if (inside_quotes || (!selected_quote && line[VIsual.col] != quotechar @@ -4251,7 +4251,6 @@ abort_search: } - /// Find next search match under cursor, cursor at end. /// Used while an operator is pending, and in Visual mode. /// @@ -4656,7 +4655,7 @@ void f_searchcount(typval_T *argvars, typval_T *rettv, FunPtr fptr) bool error = false; if (argvars[0].v_type != VAR_DICT || argvars[0].vval.v_dict == NULL) { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); return; } dict = argvars[0].vval.v_dict; @@ -4691,11 +4690,11 @@ void f_searchcount(typval_T *argvars, typval_T *rettv, FunPtr fptr) di = tv_dict_find(dict, (const char *)"pos", -1); if (di != NULL) { if (di->di_tv.v_type != VAR_LIST) { - EMSG2(_(e_invarg2), "pos"); + semsg(_(e_invarg2), "pos"); return; } if (tv_list_len(di->di_tv.vval.v_list) != 3) { - EMSG2(_(e_invarg2), "List format should be [lnum, col, off]"); + semsg(_(e_invarg2), "List format should be [lnum, col, off]"); return; } li = tv_list_find(di->di_tv.vval.v_list, 0L); @@ -4879,7 +4878,7 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo if (!got_int) { // don't display if 'q' typed at "--more--" // message msg_home_replace_hl(new_fname); - MSG_PUTS(_(" (includes previously listed match)")); + msg_puts(_(" (includes previously listed match)")); prev_fname = NULL; } } @@ -4896,29 +4895,29 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo msg_putchar('\n'); // cursor below last one } else { gotocmdline(true); // cursor at status line - MSG_PUTS_TITLE(_("--- Included files ")); + msg_puts_title(_("--- Included files ")); if (action != ACTION_SHOW_ALL) { - MSG_PUTS_TITLE(_("not found ")); + msg_puts_title(_("not found ")); } - MSG_PUTS_TITLE(_("in path ---\n")); + msg_puts_title(_("in path ---\n")); } did_show = true; while (depth_displayed < depth && !got_int) { ++depth_displayed; for (i = 0; i < depth_displayed; i++) { - MSG_PUTS(" "); + msg_puts(" "); } msg_home_replace(files[depth_displayed].name); - MSG_PUTS(" -->\n"); + msg_puts(" -->\n"); } - if (!got_int) { /* don't display if 'q' typed - for "--more--" message */ + if (!got_int) { // don't display if 'q' typed + // for "--more--" message for (i = 0; i <= depth_displayed; i++) { - MSG_PUTS(" "); + msg_puts(" "); } if (new_fname != NULL) { - /* using "new_fname" is more reliable, e.g., when - * 'includeexpr' is set. */ + // using "new_fname" is more reliable, e.g., when + // 'includeexpr' is set. msg_outtrans_attr(new_fname, HL_ATTR(HLF_D)); } else { /* @@ -4935,10 +4934,8 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo // find the file name after the end of the match for (p = incl_regmatch.endp[0]; *p && !vim_isfilec(*p); p++) { - ; } for (i = 0; vim_isfilec(p[i]); i++) { - ; } } @@ -4965,9 +4962,9 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo if (new_fname == NULL && action == ACTION_SHOW_ALL) { if (already_searched) { - MSG_PUTS(_(" (Already listed)")); + msg_puts(_(" (Already listed)")); } else { - MSG_PUTS(_(" NOT FOUND")); + msg_puts(_(" NOT FOUND")); } } } @@ -5012,7 +5009,7 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo vim_snprintf((char *)IObuff, IOSIZE, _("Scanning included file: %s"), (char *)new_fname); - msg_trunc_attr(IObuff, true, HL_ATTR(HLF_R)); + msg_trunc_attr((char *)IObuff, true, HL_ATTR(HLF_R)); } else if (p_verbose >= 5) { verbose_enter(); smsg(_("Searching included file %s"), @@ -5217,7 +5214,7 @@ search_line: found = true; if (depth == -1 && lnum == curwin->w_cursor.lnum && l_g_do_tagpreview == 0) { - EMSG(_("E387: Match is on current line")); + emsg(_("E387: Match is on current line")); } else if (action == ACTION_SHOW) { show_pat_in_path(line, type, did_show, action, (depth == -1) ? NULL : files[depth].fp, @@ -5342,19 +5339,19 @@ exit_matched: if (type == CHECK_PATH) { if (!did_show) { if (action != ACTION_SHOW_ALL) { - MSG(_("All included files were found")); + msg(_("All included files were found")); } else { - MSG(_("No included files")); + msg(_("No included files")); } } } else if (!found && action != ACTION_EXPAND) { if (got_int || compl_interrupted) { - EMSG(_(e_interr)); + emsg(_(e_interr)); } else if (type == FIND_DEFINE) { - EMSG(_("E388: Couldn't find definition")); + emsg(_("E388: Couldn't find definition")); } else { - EMSG(_("E389: Couldn't find pattern")); + emsg(_("E389: Couldn't find pattern")); } } if (action == ACTION_SHOW || action == ACTION_SHOW_ALL) { diff --git a/src/nvim/search.h b/src/nvim/search.h index 85bcda84a4..15b8d41f39 100644 --- a/src/nvim/search.h +++ b/src/nvim/search.h @@ -84,8 +84,7 @@ typedef struct { int sa_wrapped; ///< search wrapped around } searchit_arg_T; -typedef struct searchstat -{ +typedef struct searchstat { int cur; // current position of found words int cnt; // total count of found words bool exact_match; // true if matched exactly on specified position diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 10f93913ad..89f9d3a719 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -713,11 +713,11 @@ static ShaDaReadResult sd_reader_skip(ShaDaReadDef *const sd_reader, const size_ { if (sd_reader->skip(sd_reader, offset) != OK) { if (sd_reader->error != NULL) { - emsgf(_(SERR "System error while skipping in ShaDa file: %s"), + semsg(_(SERR "System error while skipping in ShaDa file: %s"), sd_reader->error); return kSDReadStatusReadError; } else if (sd_reader->eof) { - emsgf(_(RCERR "Error while reading ShaDa file: " + semsg(_(RCERR "Error while reading ShaDa file: " "last entry specified that it occupies %" PRIu64 " bytes, " "but file ended earlier"), (uint64_t)offset); @@ -762,7 +762,7 @@ static void close_file(void *cookie) { const int error = file_free(cookie, !!p_fs); if (error != 0) { - emsgf(_(SERR "System error while closing ShaDa file: %s"), + semsg(_(SERR "System error while closing ShaDa file: %s"), os_strerror(error)); } } @@ -797,7 +797,7 @@ static int msgpack_sd_writer_write(void *data, const char *buf, size_t len) ShaDaWriteDef *const sd_writer = (ShaDaWriteDef *)data; ptrdiff_t written_bytes = sd_writer->write(sd_writer, buf, len); if (written_bytes == -1) { - emsgf(_(SERR "System error while writing ShaDa file: %s"), + semsg(_(SERR "System error while writing ShaDa file: %s"), sd_writer->error); return -1; } @@ -844,7 +844,7 @@ static int shada_read_file(const char *const file, const int flags) if (of_ret != 0) { if (of_ret != UV_ENOENT || (flags & kShaDaMissingError)) { - emsgf(_(SERR "System error while opening ShaDa file %s for reading: %s"), + semsg(_(SERR "System error while opening ShaDa file %s for reading: %s"), fname, os_strerror(of_ret)); } xfree(fname); @@ -1598,7 +1598,7 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, ShadaEntr if (encode_vim_to_msgpack(spacker, &entry.data.global_var.value, vardesc) == FAIL) { ret = kSDWriteIgnError; - EMSG2(_(WERR "Failed to write variable %s"), + semsg(_(WERR "Failed to write variable %s"), entry.data.global_var.name); goto shada_pack_entry_error; } @@ -1899,7 +1899,7 @@ shada_parse_msgpack_read_next: {} } break; case MSGPACK_UNPACK_PARSE_ERROR: - emsgf(_(RCERR "Failed to parse ShaDa file due to a msgpack parser error " + semsg(_(RCERR "Failed to parse ShaDa file due to a msgpack parser error " "at position %" PRIu64), (uint64_t)initial_fpos); ret = kSDReadStatusNotShaDa; @@ -1910,18 +1910,18 @@ shada_parse_msgpack_read_next: {} try_to_free_memory(); goto shada_parse_msgpack_read_next; } - EMSG(_(e_outofmem)); + emsg(_(e_outofmem)); ret = kSDReadStatusReadError; break; case MSGPACK_UNPACK_CONTINUE: - emsgf(_(RCERR "Failed to parse ShaDa file: incomplete msgpack string " + semsg(_(RCERR "Failed to parse ShaDa file: incomplete msgpack string " "at position %" PRIu64), (uint64_t)initial_fpos); ret = kSDReadStatusNotShaDa; break; case MSGPACK_UNPACK_EXTRA_BYTES: shada_parse_msgpack_extra_bytes: - emsgf(_(RCERR "Failed to parse ShaDa file: extra bytes in msgpack string " + semsg(_(RCERR "Failed to parse ShaDa file: extra bytes in msgpack string " "at position %" PRIu64), (uint64_t)initial_fpos); ret = kSDReadStatusNotShaDa; @@ -2949,7 +2949,7 @@ int shada_write_file(const char *const file, bool nomerge) int error; if ((error = open_shada_file_for_reading(fname, &sd_reader)) != 0) { if (error != UV_ENOENT) { - emsgf(_(SERR "System error while opening ShaDa file %s for reading " + semsg(_(SERR "System error while opening ShaDa file %s for reading " "to merge before writing it: %s"), fname, os_strerror(error)); // Try writing the file even if opening it emerged any issues besides @@ -2981,7 +2981,7 @@ shada_write_file_open: {} if (*wp == 'z') { // Tried names from .tmp.a to .tmp.z, all failed. Something must be // wrong then. - EMSG2(_("E138: All %s.tmp.X files exist, cannot write ShaDa file!"), + semsg(_("E138: All %s.tmp.X files exist, cannot write ShaDa file!"), fname); xfree(fname); xfree(tempname); @@ -2993,7 +2993,7 @@ shada_write_file_open: {} goto shada_write_file_open; } } else { - emsgf(_(SERR "System error while opening temporary ShaDa file %s " + semsg(_(SERR "System error while opening temporary ShaDa file %s " "for writing: %s"), tempname, os_strerror(error)); } } @@ -3008,7 +3008,7 @@ shada_write_file_nomerge: {} int ret; char *failed_dir; if ((ret = os_mkdir_recurse(fname, 0700, &failed_dir)) != 0) { - EMSG3(_(SERR "Failed to create directory %s " + semsg(_(SERR "Failed to create directory %s " "for writing ShaDa file: %s"), failed_dir, os_strerror(ret)); xfree(fname); @@ -3022,7 +3022,7 @@ shada_write_file_nomerge: {} sd_writer.cookie = file_open_new(&error, fname, kFileCreate|kFileTruncate, 0600); if (sd_writer.cookie == NULL) { - emsgf(_(SERR "System error while opening ShaDa file %s for writing: %s"), + semsg(_(SERR "System error while opening ShaDa file %s for writing: %s"), fname, os_strerror(error)); } } @@ -3064,7 +3064,7 @@ shada_write_file_nomerge: {} const int fchown_ret = os_fchown(file_fd(sd_writer.cookie), old_uid, old_gid); if (fchown_ret != 0) { - EMSG3(_(RNERR "Failed setting uid and gid for file %s: %s"), + semsg(_(RNERR "Failed setting uid and gid for file %s: %s"), tempname, os_strerror(fchown_ret)); goto shada_write_file_did_not_remove; } @@ -3074,13 +3074,13 @@ shada_write_file_nomerge: {} : (old_info.stat.st_gid == getgid() ? (old_info.stat.st_mode & 0020) : (old_info.stat.st_mode & 0002)))) { - EMSG2(_("E137: ShaDa file is not writable: %s"), fname); + semsg(_("E137: ShaDa file is not writable: %s"), fname); goto shada_write_file_did_not_remove; } } #endif if (vim_rename((char_u *)tempname, (char_u *)fname) == -1) { - EMSG3(_(RNERR "Can't rename ShaDa file from %s to %s!"), + semsg(_(RNERR "Can't rename ShaDa file from %s to %s!"), tempname, fname); } else { did_remove = true; @@ -3088,10 +3088,10 @@ shada_write_file_nomerge: {} } } else { if (sw_ret == kSDWriteReadNotShada) { - EMSG3(_(RNERR "Did not rename %s because %s " + semsg(_(RNERR "Did not rename %s because %s " "does not look like a ShaDa file"), tempname, fname); } else { - EMSG3(_(RNERR "Did not rename %s to %s because there were errors " + semsg(_(RNERR "Did not rename %s to %s because there were errors " "during writing it"), tempname, fname); } } @@ -3099,7 +3099,7 @@ shada_write_file_nomerge: {} #ifdef UNIX shada_write_file_did_not_remove: #endif - EMSG3(_(RNERR "Do not forget to remove %s or rename it manually to %s."), + semsg(_(RNERR "Do not forget to remove %s or rename it manually to %s."), tempname, fname); } xfree(tempname); @@ -3225,11 +3225,11 @@ static ShaDaReadResult fread_len(ShaDaReadDef *const sd_reader, char *const buff if (read_bytes != (ptrdiff_t)length) { if (sd_reader->error != NULL) { - emsgf(_(SERR "System error while reading ShaDa file: %s"), + semsg(_(SERR "System error while reading ShaDa file: %s"), sd_reader->error); return kSDReadStatusReadError; } else { - emsgf(_(RCERR "Error while reading ShaDa file: " + semsg(_(RCERR "Error while reading ShaDa file: " "last entry specified that it occupies %" PRIu64 " bytes, " "but file ended earlier"), (uint64_t)length); @@ -3263,11 +3263,11 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, const if (first_char == EOF) { if (sd_reader->error) { - emsgf(_(SERR "System error while reading integer from ShaDa file: %s"), + semsg(_(SERR "System error while reading integer from ShaDa file: %s"), sd_reader->error); return kSDReadStatusReadError; } else if (sd_reader->eof) { - emsgf(_(RCERR "Error while reading ShaDa file: " + semsg(_(RCERR "Error while reading ShaDa file: " "expected positive integer at position %" PRIu64 ", but got nothing"), (uint64_t)fpos); @@ -3294,7 +3294,7 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, const length = 8; break; default: - emsgf(_(RCERR "Error while reading ShaDa file: " + semsg(_(RCERR "Error while reading ShaDa file: " "expected positive integer at position %" PRIu64), (uint64_t)fpos); return kSDReadStatusNotShaDa; @@ -3334,18 +3334,18 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, const proc) \ do { \ if (!(condition)) { \ - emsgf(_(READERR(entry_name, error_desc)), initial_fpos); \ + semsg(_(READERR(entry_name, error_desc)), initial_fpos); \ CLEAR_GA_AND_ERROR_OUT(ad_ga); \ } \ tgt = proc(obj.via.attr); \ } while (0) #define CHECK_KEY_IS_STR(un, entry_name) \ if (un.data.via.map.ptr[i].key.type != MSGPACK_OBJECT_STR) { \ - emsgf(_(READERR(entry_name, "has key which is not a string")), \ + semsg(_(READERR(entry_name, "has key which is not a string")), \ initial_fpos); \ CLEAR_GA_AND_ERROR_OUT(ad_ga); \ } else if (un.data.via.map.ptr[i].key.via.str.size == 0) { \ - emsgf(_(READERR(entry_name, "has empty key")), initial_fpos); \ + semsg(_(READERR(entry_name, "has empty key")), initial_fpos); \ CLEAR_GA_AND_ERROR_OUT(ad_ga); \ } #define CHECKED_KEY(un, entry_name, name, error_desc, tgt, condition, attr, \ @@ -3403,7 +3403,7 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, const typval_T adtv; \ if (msgpack_to_vim(obj, &adtv) == FAIL \ || adtv.v_type != VAR_DICT) { \ - emsgf(_(READERR(name, \ + semsg(_(READERR(name, \ "cannot be converted to a VimL dictionary")), \ initial_fpos); \ ga_clear(&ad_ga); \ @@ -3428,7 +3428,7 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, const }; \ typval_T aetv; \ if (msgpack_to_vim(obj, &aetv) == FAIL) { \ - emsgf(_(READERR(name, "cannot be converted to a VimL list")), \ + semsg(_(READERR(name, "cannot be converted to a VimL list")), \ initial_fpos); \ tv_clear(&aetv); \ goto shada_read_next_item_error; \ @@ -3488,7 +3488,7 @@ shada_read_next_item_start: } if (length_u64 > PTRDIFF_MAX) { - emsgf(_(RCERR "Error while reading ShaDa file: " + semsg(_(RCERR "Error while reading ShaDa file: " "there is an item at position %" PRIu64 " " "that is stated to be too long"), initial_fpos); @@ -3502,7 +3502,7 @@ shada_read_next_item_start: // 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. - emsgf(_(RCERR "Error while reading ShaDa file: " + semsg(_(RCERR "Error while reading ShaDa file: " "there is an item at position %" PRIu64 " " "that must not be there: Missing items are " "for internal uses only"), @@ -3572,13 +3572,13 @@ shada_read_next_item_start: switch ((ShadaEntryType)type_u64) { case kSDItemHeader: if (!msgpack_rpc_to_dictionary(&(unpacked.data), &(entry->data.header))) { - emsgf(_(READERR("header", "is not a dictionary")), initial_fpos); + semsg(_(READERR("header", "is not a dictionary")), initial_fpos); goto shada_read_next_item_error; } break; case kSDItemSearchPattern: { if (unpacked.data.type != MSGPACK_OBJECT_MAP) { - emsgf(_(READERR("search pattern", "is not a dictionary")), + semsg(_(READERR("search pattern", "is not a dictionary")), initial_fpos); goto shada_read_next_item_error; } @@ -3610,7 +3610,7 @@ shada_read_next_item_start: ADDITIONAL_KEY(unpacked) } if (entry->data.search_pattern.pat == NULL) { - emsgf(_(READERR("search pattern", "has no pattern")), initial_fpos); + semsg(_(READERR("search pattern", "has no pattern")), initial_fpos); CLEAR_GA_AND_ERROR_OUT(ad_ga); } SET_ADDITIONAL_DATA(entry->data.search_pattern.additional_data, @@ -3622,7 +3622,7 @@ shada_read_next_item_start: case kSDItemGlobalMark: case kSDItemLocalMark: { if (unpacked.data.type != MSGPACK_OBJECT_MAP) { - emsgf(_(READERR("mark", "is not a dictionary")), initial_fpos); + semsg(_(READERR("mark", "is not a dictionary")), initial_fpos); goto shada_read_next_item_error; } garray_T ad_ga; @@ -3631,7 +3631,7 @@ shada_read_next_item_start: CHECK_KEY_IS_STR(unpacked, "mark") if (CHECK_KEY(unpacked.data.via.map.ptr[i].key, KEY_NAME_CHAR)) { if (type_u64 == kSDItemJump || type_u64 == kSDItemChange) { - emsgf(_(READERR("mark", "has n key which is only valid for " + semsg(_(READERR("mark", "has n key which is only valid for " "local and global mark entries")), initial_fpos); CLEAR_GA_AND_ERROR_OUT(ad_ga); } @@ -3647,15 +3647,15 @@ shada_read_next_item_start: ADDITIONAL_KEY(unpacked) } if (entry->data.filemark.fname == NULL) { - emsgf(_(READERR("mark", "is missing file name")), initial_fpos); + semsg(_(READERR("mark", "is missing file name")), initial_fpos); CLEAR_GA_AND_ERROR_OUT(ad_ga); } if (entry->data.filemark.mark.lnum <= 0) { - emsgf(_(READERR("mark", "has invalid line number")), initial_fpos); + semsg(_(READERR("mark", "has invalid line number")), initial_fpos); CLEAR_GA_AND_ERROR_OUT(ad_ga); } if (entry->data.filemark.mark.col < 0) { - emsgf(_(READERR("mark", "has invalid column number")), initial_fpos); + semsg(_(READERR("mark", "has invalid column number")), initial_fpos); CLEAR_GA_AND_ERROR_OUT(ad_ga); } SET_ADDITIONAL_DATA(entry->data.filemark.additional_data, "mark"); @@ -3663,7 +3663,7 @@ shada_read_next_item_start: } case kSDItemRegister: { if (unpacked.data.type != MSGPACK_OBJECT_MAP) { - emsgf(_(READERR("register", "is not a dictionary")), initial_fpos); + semsg(_(READERR("register", "is not a dictionary")), initial_fpos); goto shada_read_next_item_error; } garray_T ad_ga; @@ -3673,14 +3673,14 @@ shada_read_next_item_start: if (CHECK_KEY(unpacked.data.via.map.ptr[i].key, REG_KEY_CONTENTS)) { if (unpacked.data.via.map.ptr[i].val.type != MSGPACK_OBJECT_ARRAY) { - emsgf(_(READERR("register", + semsg(_(READERR("register", "has " REG_KEY_CONTENTS " key with non-array value")), initial_fpos); CLEAR_GA_AND_ERROR_OUT(ad_ga); } if (unpacked.data.via.map.ptr[i].val.via.array.size == 0) { - emsgf(_(READERR("register", + semsg(_(READERR("register", "has " REG_KEY_CONTENTS " key with empty array")), initial_fpos); CLEAR_GA_AND_ERROR_OUT(ad_ga); @@ -3689,7 +3689,7 @@ shada_read_next_item_start: unpacked.data.via.map.ptr[i].val.via.array; for (size_t j = 0; j < arr.size; j++) { if (arr.ptr[j].type != MSGPACK_OBJECT_BIN) { - emsgf(_(READERR("register", "has " REG_KEY_CONTENTS " array " + semsg(_(READERR("register", "has " REG_KEY_CONTENTS " array " "with non-binary value")), initial_fpos); CLEAR_GA_AND_ERROR_OUT(ad_ga); } @@ -3711,7 +3711,7 @@ shada_read_next_item_start: ADDITIONAL_KEY(unpacked) } if (entry->data.reg.contents == NULL) { - emsgf(_(READERR("register", "has missing " REG_KEY_CONTENTS " array")), + semsg(_(READERR("register", "has missing " REG_KEY_CONTENTS " array")), initial_fpos); CLEAR_GA_AND_ERROR_OUT(ad_ga); } @@ -3720,29 +3720,29 @@ shada_read_next_item_start: } case kSDItemHistoryEntry: { if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) { - emsgf(_(READERR("history", "is not an array")), initial_fpos); + semsg(_(READERR("history", "is not an array")), initial_fpos); goto shada_read_next_item_error; } if (unpacked.data.via.array.size < 2) { - emsgf(_(READERR("history", "does not have enough elements")), + semsg(_(READERR("history", "does not have enough elements")), initial_fpos); goto shada_read_next_item_error; } if (unpacked.data.via.array.ptr[0].type != MSGPACK_OBJECT_POSITIVE_INTEGER) { - emsgf(_(READERR("history", "has wrong history type type")), + semsg(_(READERR("history", "has wrong history type type")), initial_fpos); goto shada_read_next_item_error; } if (unpacked.data.via.array.ptr[1].type != MSGPACK_OBJECT_BIN) { - emsgf(_(READERR("history", "has wrong history string type")), + semsg(_(READERR("history", "has wrong history string type")), initial_fpos); goto shada_read_next_item_error; } if (memchr(unpacked.data.via.array.ptr[1].via.bin.ptr, 0, unpacked.data.via.array.ptr[1].via.bin.size) != NULL) { - emsgf(_(READERR("history", "contains string with zero byte inside")), + semsg(_(READERR("history", "contains string with zero byte inside")), initial_fpos); goto shada_read_next_item_error; } @@ -3752,13 +3752,13 @@ shada_read_next_item_start: entry->data.history_item.histtype == HIST_SEARCH; if (is_hist_search) { if (unpacked.data.via.array.size < 3) { - emsgf(_(READERR("search history", + semsg(_(READERR("search history", "does not have separator character")), initial_fpos); goto shada_read_next_item_error; } if (unpacked.data.via.array.ptr[2].type != MSGPACK_OBJECT_POSITIVE_INTEGER) { - emsgf(_(READERR("search history", + semsg(_(READERR("search history", "has wrong history separator type")), initial_fpos); goto shada_read_next_item_error; } @@ -3784,16 +3784,16 @@ shada_read_next_item_start: } case kSDItemVariable: { if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) { - emsgf(_(READERR("variable", "is not an array")), initial_fpos); + semsg(_(READERR("variable", "is not an array")), initial_fpos); goto shada_read_next_item_error; } if (unpacked.data.via.array.size < 2) { - emsgf(_(READERR("variable", "does not have enough elements")), + semsg(_(READERR("variable", "does not have enough elements")), initial_fpos); goto shada_read_next_item_error; } if (unpacked.data.via.array.ptr[0].type != MSGPACK_OBJECT_BIN) { - emsgf(_(READERR("variable", "has wrong variable name type")), + semsg(_(READERR("variable", "has wrong variable name type")), initial_fpos); goto shada_read_next_item_error; } @@ -3813,7 +3813,7 @@ shada_read_next_item_start: const typval_T *type_tv = TV_LIST_ITEM_TV(type_item); if (type_tv->v_type != VAR_NUMBER || type_tv->vval.v_number != VAR_TYPE_BLOB) { - emsgf(_(READERR("variable", "has wrong variable type")), + semsg(_(READERR("variable", "has wrong variable type")), initial_fpos); goto shada_read_next_item_error; } @@ -3828,7 +3828,7 @@ shada_read_next_item_start: tv_blob_set_ret(&entry->data.global_var.value, blob); } else if (msgpack_to_vim(unpacked.data.via.array.ptr[1], &(entry->data.global_var.value)) == FAIL) { - emsgf(_(READERR("variable", "has value that cannot " + semsg(_(READERR("variable", "has value that cannot " "be converted to the VimL value")), initial_fpos); goto shada_read_next_item_error; } @@ -3836,16 +3836,16 @@ shada_read_next_item_start: } case kSDItemSubString: if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) { - emsgf(_(READERR("sub string", "is not an array")), initial_fpos); + semsg(_(READERR("sub string", "is not an array")), initial_fpos); goto shada_read_next_item_error; } if (unpacked.data.via.array.size < 1) { - emsgf(_(READERR("sub string", "does not have enough elements")), + semsg(_(READERR("sub string", "does not have enough elements")), initial_fpos); goto shada_read_next_item_error; } if (unpacked.data.via.array.ptr[0].type != MSGPACK_OBJECT_BIN) { - emsgf(_(READERR("sub string", "has wrong sub string type")), + semsg(_(READERR("sub string", "has wrong sub string type")), initial_fpos); goto shada_read_next_item_error; } @@ -3857,7 +3857,7 @@ shada_read_next_item_start: break; case kSDItemBufferList: if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) { - emsgf(_(READERR("buffer list", "is not an array")), initial_fpos); + semsg(_(READERR("buffer list", "is not an array")), initial_fpos); goto shada_read_next_item_error; } if (unpacked.data.via.array.size == 0) { @@ -3873,7 +3873,7 @@ shada_read_next_item_start: }; { if (unpacked_2.data.type != MSGPACK_OBJECT_MAP) { - emsgf(_(RERR "Error while reading ShaDa file: " + semsg(_(RERR "Error while reading ShaDa file: " "buffer list at position %" PRIu64 " " "contains entry that is not a dictionary"), initial_fpos); @@ -3900,21 +3900,21 @@ shada_read_next_item_start: i = j; // XXX: Restore `i`. } if (entry->data.buffer_list.buffers[i].pos.lnum <= 0) { - emsgf(_(RERR "Error while reading ShaDa file: " + semsg(_(RERR "Error while reading ShaDa file: " "buffer list at position %" PRIu64 " " "contains entry with invalid line number"), initial_fpos); CLEAR_GA_AND_ERROR_OUT(ad_ga); } if (entry->data.buffer_list.buffers[i].pos.col < 0) { - emsgf(_(RERR "Error while reading ShaDa file: " + semsg(_(RERR "Error while reading ShaDa file: " "buffer list at position %" PRIu64 " " "contains entry with invalid column number"), initial_fpos); CLEAR_GA_AND_ERROR_OUT(ad_ga); } if (entry->data.buffer_list.buffers[i].fname == NULL) { - emsgf(_(RERR "Error while reading ShaDa file: " + semsg(_(RERR "Error while reading ShaDa file: " "buffer list at position %" PRIu64 " " "contains entry that does not have a file name"), initial_fpos); @@ -4014,7 +4014,7 @@ static inline size_t shada_init_jumps(PossiblyFreedShadaEntry *jumps, jump_iter = mark_jumplist_iter(jump_iter, curwin, &fm); if (fm.fmark.mark.lnum == 0) { - iemsgf("ShaDa: mark lnum zero (ji:%p, js:%p, len:%i)", + siemsg("ShaDa: mark lnum zero (ji:%p, js:%p, len:%i)", (void *)jump_iter, (void *)&curwin->w_jumplist[0], curwin->w_jumplistlen); continue; diff --git a/src/nvim/sign.c b/src/nvim/sign.c index 1b100161bf..dfa863d0ff 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -23,8 +23,7 @@ /// Struct to hold the sign properties. typedef struct sign sign_T; -struct sign -{ +struct sign { sign_T *sn_next; // next sign in list int sn_typenr; // type number of sign char_u *sn_name; // name of sign @@ -434,9 +433,9 @@ sign_attrs_T *sign_get_attr(SignType type, sign_attrs_T sattrs[], int idx, int m int nr_matches = 0; for (int i = 0; i < SIGN_SHOW_MAX; i++) { - if ( (type == SIGN_TEXT && sattrs[i].sat_text != NULL) - || (type == SIGN_LINEHL && sattrs[i].sat_linehl != 0) - || (type == SIGN_NUMHL && sattrs[i].sat_numhl != 0)) { + if ((type == SIGN_TEXT && sattrs[i].sat_text != NULL) + || (type == SIGN_LINEHL && sattrs[i].sat_linehl != 0) + || (type == SIGN_NUMHL && sattrs[i].sat_numhl != 0)) { matches[nr_matches] = &sattrs[i]; nr_matches++; // attr list is sorted with most important (priority, id), thus we @@ -681,7 +680,7 @@ void sign_list_placed(buf_T *rbuf, char_u *sign_group) char lbuf[MSG_BUF_LEN]; char group[MSG_BUF_LEN]; - MSG_PUTS_TITLE(_("\n--- Signs ---")); + msg_puts_title(_("\n--- Signs ---")); msg_putchar('\n'); if (rbuf == NULL) { buf = firstbuf; @@ -691,7 +690,7 @@ void sign_list_placed(buf_T *rbuf, char_u *sign_group) while (buf != NULL && !got_int) { if (buf->b_signlist != NULL) { vim_snprintf(lbuf, MSG_BUF_LEN, _("Signs for %s:"), buf->b_fname); - MSG_PUTS_ATTR(lbuf, HL_ATTR(HLF_D)); + msg_puts_attr(lbuf, HL_ATTR(HLF_D)); msg_putchar('\n'); } FOR_ALL_SIGNS_IN_BUF(buf, sign) { @@ -711,7 +710,7 @@ void sign_list_placed(buf_T *rbuf, char_u *sign_group) _(" line=%ld id=%d%s name=%s priority=%d"), (long)sign->se_lnum, sign->se_id, group, sign_typenr2name(sign->se_typenr), sign->se_priority); - MSG_PUTS(lbuf); + msg_puts(lbuf); msg_putchar('\n'); } if (rbuf != NULL) { @@ -825,7 +824,7 @@ static sign_T *alloc_new_sign(char_u *name) } if (next_sign_typenr == start) { xfree(sp); - EMSG(_("E612: Too many signs defined")); + emsg(_("E612: Too many signs defined")); return NULL; } lp = first_sign; // start all over @@ -871,7 +870,7 @@ static int sign_define_init_text(sign_T *sp, char_u *text) } // Count cells and check for non-printable chars cells = 0; - for (s = text; s < endp; s += (*mb_ptr2len)(s)) { + for (s = text; s < endp; s += utfc_ptr2len(s)) { if (!vim_isprintc(utf_ptr2char(s))) { break; } @@ -879,7 +878,7 @@ static int sign_define_init_text(sign_T *sp, char_u *text) } // Currently must be empty, one or two display cells if (s != endp || cells > 2) { - EMSG2(_("E239: Invalid sign text: %s"), text); + semsg(_("E239: Invalid sign text: %s"), text); return FAIL; } if (cells < 1) { @@ -962,7 +961,7 @@ int sign_undefine_by_name(const char_u *name) sp = sign_find(name, &sp_prev); if (sp == NULL) { - EMSG2(_("E155: Unknown sign: %s"), name); + semsg(_("E155: Unknown sign: %s"), name); return FAIL; } sign_undefine(sp, sp_prev); @@ -990,7 +989,7 @@ static void sign_list_by_name(char_u *name) if (sp != NULL) { sign_list_defined(sp); } else { - EMSG2(_("E155: Unknown sign: %s"), name); + semsg(_("E155: Unknown sign: %s"), name); } } @@ -1012,7 +1011,7 @@ int sign_place(int *sign_id, const char_u *sign_group, const char_u *sign_name, } } if (sp == NULL) { - EMSG2(_("E155: Unknown sign: %s"), sign_name); + semsg(_("E155: Unknown sign: %s"), sign_name); return FAIL; } if (*sign_id == 0) { @@ -1041,7 +1040,7 @@ int sign_place(int *sign_id, const char_u *sign_group, const char_u *sign_name, // number column is less than 2, then force recomputing the width. may_force_numberwidth_recompute(buf, false); } else { - EMSG2(_("E885: Not possible to change sign %s"), sign_name); + semsg(_("E885: Not possible to change sign %s"), sign_name); return FAIL; } @@ -1088,7 +1087,7 @@ static void sign_unplace_at_cursor(char_u *groupname) if (id > 0) { sign_unplace(id, groupname, curwin->w_buffer, curwin->w_cursor.lnum); } else { - EMSG(_("E159: Missing sign number")); + emsg(_("E159: Missing sign number")); } } @@ -1098,7 +1097,7 @@ linenr_T sign_jump(int sign_id, char_u *sign_group, buf_T *buf) linenr_T lnum; if ((lnum = buf_findsign(buf, sign_id, sign_group)) <= 0) { - EMSGN(_("E157: Invalid sign ID: %" PRId64), sign_id); + semsg(_("E157: Invalid sign ID: %" PRId64), (int64_t)sign_id); return -1; } @@ -1109,7 +1108,7 @@ linenr_T sign_jump(int sign_id, char_u *sign_group, buf_T *buf) beginline(BL_WHITE); } else { // ... not currently in a window if (buf->b_fname == NULL) { - EMSG(_("E934: Cannot jump to a buffer that does not have a name")); + emsg(_("E934: Cannot jump to a buffer that does not have a name")); return -1; } size_t cmdlen = STRLEN(buf->b_fname) + 24; @@ -1160,7 +1159,7 @@ static void sign_define_cmd(char_u *sign_name, char_u *cmdline) arg += 6; numhl = vim_strnsave(arg, (size_t)(p - arg)); } else { - EMSG2(_(e_invarg2), arg); + semsg(_(e_invarg2), arg); failed = true; break; } @@ -1194,7 +1193,7 @@ static void sign_place_cmd(buf_T *buf, linenr_T lnum, char_u *sign_name, int id, // :sign place group=* if (lnum >= 0 || sign_name != NULL || (group != NULL && *group == '\0')) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); } else { sign_list_placed(buf, group); } @@ -1202,7 +1201,7 @@ static void sign_place_cmd(buf_T *buf, linenr_T lnum, char_u *sign_name, int id, // Place a new sign if (sign_name == NULL || buf == NULL || (group != NULL && *group == '\0')) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -1214,7 +1213,7 @@ static void sign_place_cmd(buf_T *buf, linenr_T lnum, char_u *sign_name, int id, static void sign_unplace_cmd(buf_T *buf, linenr_T lnum, char_u *sign_name, int id, char_u *group) { if (lnum >= 0 || sign_name != NULL || (group != NULL && *group == '\0')) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -1271,7 +1270,7 @@ static void sign_unplace_cmd(buf_T *buf, linenr_T lnum, char_u *sign_name, int i static void sign_jump_cmd(buf_T *buf, linenr_T lnum, char_u *sign_name, int id, char_u *group) { if (sign_name == NULL && group == NULL && id == -1) { - EMSG(_(e_argreq)); + emsg(_(e_argreq)); return; } @@ -1279,7 +1278,7 @@ static void sign_jump_cmd(buf_T *buf, linenr_T lnum, char_u *sign_name, int id, || lnum >= 0 || sign_name != NULL) { // File or buffer is not specified or an empty group is used // or a line number or a sign name is specified. - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return; } @@ -1318,7 +1317,7 @@ static int parse_sign_cmd_args(int cmd, char_u *arg, char_u **sign_name, int *si lnum_arg = true; } else if (STRNCMP(arg, "*", 1) == 0 && cmd == SIGNCMD_UNPLACE) { if (*signid != -1) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return FAIL; } *signid = -2; @@ -1355,18 +1354,18 @@ static int parse_sign_cmd_args(int cmd, char_u *arg, char_u **sign_name, int *si filename = arg; *buf = buflist_findnr(getdigits_int(&arg, true, 0)); if (*skipwhite(arg) != NUL) { - EMSG(_(e_trailing)); + emsg(_(e_trailing)); } break; } else { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return FAIL; } arg = skipwhite(arg); } if (filename != NULL && *buf == NULL) { - EMSG2(_("E158: Invalid buffer name: %s"), filename); + semsg(_("E158: Invalid buffer name: %s"), filename); return FAIL; } @@ -1391,7 +1390,7 @@ void ex_sign(exarg_T *eap) p = skiptowhite(arg); idx = sign_cmd_idx(arg, p); if (idx == SIGNCMD_LAST) { - EMSG2(_("E160: Unknown sign command: %s"), arg); + semsg(_("E160: Unknown sign command: %s"), arg); return; } arg = skipwhite(p); @@ -1404,7 +1403,7 @@ void ex_sign(exarg_T *eap) sign_list_defined(sp); } } else if (*arg == NUL) { - EMSG(_("E156: Missing sign name")); + emsg(_("E156: Missing sign name")); } else { char_u *name; @@ -1898,7 +1897,7 @@ void sign_define_multiple(list_T *l, list_T *retlist) if (TV_LIST_ITEM_TV(li)->v_type == VAR_DICT) { retval = sign_define_from_dict(NULL, TV_LIST_ITEM_TV(li)->vval.v_dict); } else { - EMSG(_(e_dictreq)); + emsg(_(e_dictreq)); } tv_list_append_number(retlist, retval); }); @@ -1934,7 +1933,7 @@ int sign_place_from_dict(typval_T *id_tv, typval_T *group_tv, typval_T *name_tv, return -1; } if (sign_id < 0) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); return -1; } } @@ -1995,7 +1994,7 @@ int sign_place_from_dict(typval_T *id_tv, typval_T *group_tv, typval_T *name_tv, if (di != NULL) { lnum = tv_get_lnum(&di->di_tv); if (lnum <= 0) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); goto cleanup; } } @@ -2069,7 +2068,7 @@ int sign_unplace_from_dict(typval_T *group_tv, dict_T *dict) if (tv_dict_find(dict, "id", -1) != NULL) { sign_id = (int)tv_dict_get_number(dict, "id"); if (sign_id <= 0) { - EMSG(_(e_invarg)); + emsg(_(e_invarg)); goto cleanup; } } diff --git a/src/nvim/sign_defs.h b/src/nvim/sign_defs.h index f3ec2c45f6..46436b2c8e 100644 --- a/src/nvim/sign_defs.h +++ b/src/nvim/sign_defs.h @@ -9,8 +9,7 @@ // signs: line annotations // Sign group -typedef struct signgroup_S -{ +typedef struct signgroup_S { uint16_t sg_refcount; // number of signs in this group int sg_next_sign_id; // next sign id for this group char_u sg_name[1]; // sign group name @@ -55,5 +54,4 @@ typedef enum { } SignType; - #endif // NVIM_SIGN_DEFS_H diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 9ed421c8a0..20081bce4f 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -397,7 +397,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou bool this_upper = false; // init for gcc if (use_camel_case) { - c = PTR2CHAR(mi.mi_fend); + c = utf_ptr2char(mi.mi_fend); this_upper = SPELL_ISUPPER(c); } @@ -405,7 +405,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou MB_PTR_ADV(mi.mi_fend); if (use_camel_case) { const bool prev_upper = this_upper; - c = PTR2CHAR(mi.mi_fend); + c = utf_ptr2char(mi.mi_fend); this_upper = SPELL_ISUPPER(c); camel_case = !prev_upper && this_upper; } @@ -414,7 +414,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou if (capcol != NULL && *capcol == 0 && wp->w_s->b_cap_prog != NULL) { // Check word starting with capital letter. - c = PTR2CHAR(ptr); + c = utf_ptr2char(ptr); if (!SPELL_ISUPPER(c)) { wrongcaplen = (size_t)(mi.mi_fend - ptr); } @@ -634,7 +634,7 @@ static void find_word(matchinf_T *mip, int mode) if (byts[arridx] == 0) { if (endidxcnt == MAXWLEN) { // Must be a corrupted spell file. - EMSG(_(e_format)); + emsg(_(e_format)); return; } endlen[endidxcnt] = wlen; @@ -1386,7 +1386,7 @@ static bool no_spell_checking(win_T *wp) { if (!wp->w_p_spell || *wp->w_s->b_p_spl == NUL || GA_EMPTY(&wp->w_s->b_langp)) { - EMSG(_(e_no_spell)); + emsg(_(e_no_spell)); return true; } return false; @@ -1758,7 +1758,8 @@ void slang_free(slang_T *lp) } /// Frees a salitem_T -static void free_salitem(salitem_T *smp) { +static void free_salitem(salitem_T *smp) +{ xfree(smp->sm_lead); // Don't free sm_oneof and sm_rules, they point into sm_lead. xfree(smp->sm_to); @@ -1768,7 +1769,8 @@ static void free_salitem(salitem_T *smp) { } /// Frees a fromto_T -static void free_fromto(fromto_T *ftp) { +static void free_fromto(fromto_T *ftp) +{ xfree(ftp->ft_from); xfree(ftp->ft_to); } @@ -2022,7 +2024,7 @@ static int count_syllables(slang_T *slang, const char_u *word) } else { // No recognized syllable item, at least a syllable char then? c = utf_ptr2char(p); - len = (*mb_ptr2len)(p); + len = utfc_ptr2len(p); if (vim_strchr(slang->sl_syllable, c) == NULL) { skip = false; // No, search for next syllable } else if (!skip) { @@ -2036,7 +2038,7 @@ static int count_syllables(slang_T *slang, const char_u *word) // 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) +char *did_set_spelllang(win_T *wp) { garray_T ga; char_u *splp; @@ -2057,7 +2059,7 @@ char_u *did_set_spelllang(win_T *wp) bool nobreak = false; langp_T *lp, *lp2; static bool recursive = false; - char_u *ret_msg = NULL; + char *ret_msg = NULL; char_u *spl_copy; bufref_T bufref; @@ -2155,8 +2157,7 @@ char_u *did_set_spelllang(win_T *wp) // SpellFileMissing autocommands may do anything, including // destroying the buffer we are using... if (!bufref_valid(&bufref)) { - ret_msg = - (char_u *)N_("E797: SpellFileMissing autocommand deleted buffer"); + ret_msg = N_("E797: SpellFileMissing autocommand deleted buffer"); goto theend; } } @@ -2422,7 +2423,7 @@ int captype(char_u *word, char_u *end) // But a word with an upper char only at start is a ONECAP. for (; end == NULL ? *p != NUL : p < end; MB_PTR_ADV(p)) { if (spell_iswordp_nmw(p, curwin)) { - c = PTR2CHAR(p); + c = utf_ptr2char(p); if (!SPELL_ISUPPER(c)) { // UUl -> KEEPCAP if (past_second && allcap) { @@ -2463,7 +2464,7 @@ static int badword_captype(char_u *word, char_u *end) l = u = 0; first = false; for (p = word; p < end; MB_PTR_ADV(p)) { - c = PTR2CHAR(p); + c = utf_ptr2char(p); if (SPELL_ISUPPER(c)) { ++u; if (p == word) { @@ -2870,7 +2871,7 @@ void spell_suggest(int count) } if (*curwin->w_s->b_p_spl == NUL) { - EMSG(_(e_no_spell)); + emsg(_(e_no_spell)); return; } @@ -2933,7 +2934,7 @@ void spell_suggest(int count) true, need_cap, true); if (GA_EMPTY(&sug.su_ga)) { - MSG(_("Sorry, no suggestions")); + msg(_("Sorry, no suggestions")); } else if (count > 0) { if (count > sug.su_ga.ga_len) { smsg(_("Sorry, only %" PRId64 " suggestions"), @@ -3149,7 +3150,7 @@ void ex_spellrepall(exarg_T *eap) linenr_T prev_lnum = 0; if (repl_from == NULL || repl_to == NULL) { - EMSG(_("E752: No previous spell replacement")); + emsg(_("E752: No previous spell replacement")); return; } addlen = (int)(STRLEN(repl_to) - STRLEN(repl_from)); @@ -3193,7 +3194,7 @@ void ex_spellrepall(exarg_T *eap) xfree(frompat); if (sub_nsubs == 0) { - EMSG2(_("E753: Not found: %s"), repl_from); + semsg(_("E753: Not found: %s"), repl_from); } else { do_sub_msg(false); } @@ -3313,7 +3314,7 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma // If the word is not capitalised and spell_check() doesn't consider the // word to be bad then it might need to be capitalised. Add a suggestion // for that. - c = PTR2CHAR(su->su_badptr); + c = utf_ptr2char(su->su_badptr); if (!SPELL_ISUPPER(c) && attr == HLF_COUNT) { make_case_word(su->su_badword, buf, WF_ONECAP); add_suggestion(su, &su->su_ga, buf, su->su_badlen, SCORE_ICASE, @@ -3404,7 +3405,7 @@ static void spell_suggest_file(suginfo_T *su, char_u *fname) // Open the file. fd = os_fopen((char *)fname, "r"); if (fd == NULL) { - EMSG2(_(e_notopen), fname); + semsg(_(e_notopen), fname); return; } @@ -3420,7 +3421,6 @@ static void spell_suggest_file(suginfo_T *su, char_u *fname) if (STRICMP(su->su_badword, line) == 0) { // Match! Isolate the good word, until CR or NL. for (len = 0; p[len] >= ' '; ++len) { - ; } p[len] = NUL; @@ -3813,7 +3813,6 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so if (sp->ts_prefixdepth == PFD_PREFIXTREE) { // Skip over the NUL bytes, we use them later. for (n = 0; n < len && byts[arridx + n] == 0; ++n) { - ; } sp->ts_curi += n; @@ -3888,7 +3887,6 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so n = stack[sp->ts_prefixdepth].ts_arridx; len = pbyts[n++]; for (c = 0; c < len && pbyts[n + c] == 0; ++c) { - ; } if (c > 0) { c = valid_word_prefix(c, n, flags, @@ -4010,7 +4008,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so c = su->su_badflags; if ((c & WF_ALLCAP) && su->su_badlen == - (*mb_ptr2len)(su->su_badptr)) { + utfc_ptr2len(su->su_badptr)) { c = WF_ONECAP; } c |= flags; @@ -4611,7 +4609,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so break; } - n = MB_CPTR2LEN(p); + n = utf_ptr2len(p); c = utf_ptr2char(p); if (p[n] == NUL) { c2 = NUL; @@ -4646,7 +4644,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so PROF_STORE(sp->ts_state) sp->ts_state = STATE_UNSWAP; depth++; - fl = mb_char2len(c2); + fl = utf_char2len(c2); memmove(p, p + n, fl); utf_char2bytes(c, p + fl); stack[depth].ts_fidxtry = sp->ts_fidx + n + fl; @@ -4671,9 +4669,9 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // Swap two bytes, skipping one: "123" -> "321". We change // "fword" here, it's changed back afterwards at STATE_UNSWAP3. p = fword + sp->ts_fidx; - n = MB_CPTR2LEN(p); + n = utf_ptr2len(p); c = utf_ptr2char(p); - fl = MB_CPTR2LEN(p + n); + fl = utf_ptr2len(p + n); c2 = utf_ptr2char(p + n); if (!soundfold && !spell_iswordp(p + n + fl, curwin)) { c3 = c; // don't swap non-word char @@ -4702,7 +4700,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so PROF_STORE(sp->ts_state) sp->ts_state = STATE_UNSWAP3; depth++; - tl = mb_char2len(c3); + tl = utf_char2len(c3); memmove(p, p + n + fl, tl); utf_char2bytes(c2, p + tl); utf_char2bytes(c, p + fl + tl); @@ -4748,10 +4746,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so sp->ts_state = STATE_UNROT3L; ++depth; p = fword + sp->ts_fidx; - n = MB_CPTR2LEN(p); + n = utf_ptr2len(p); c = utf_ptr2char(p); - fl = MB_CPTR2LEN(p + n); - fl += MB_CPTR2LEN(p + n + fl); + fl = utf_ptr2len(p + n); + fl += utf_ptr2len(p + n + fl); memmove(p, p + n, fl); utf_char2bytes(c, p + fl); stack[depth].ts_fidxtry = sp->ts_fidx + n + fl; @@ -4785,10 +4783,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so sp->ts_state = STATE_UNROT3R; ++depth; p = fword + sp->ts_fidx; - n = MB_CPTR2LEN(p); - n += MB_CPTR2LEN(p + n); + n = utf_ptr2len(p); + n += utf_ptr2len(p + n); c = utf_ptr2char(p + n); - tl = MB_CPTR2LEN(p + n); + tl = utf_ptr2len(p + n); memmove(p + tl, p, n); utf_char2bytes(c, p); stack[depth].ts_fidxtry = sp->ts_fidx + n + tl; @@ -5023,8 +5021,8 @@ static void find_keepcap_word(slang_T *slang, char_u *fword, char_u *kword) } else { // round[depth] == 1: Try using the folded-case character. // round[depth] == 2: Try using the upper-case character. - flen = MB_CPTR2LEN(fword + fwordidx[depth]); - ulen = MB_CPTR2LEN(uword + uwordidx[depth]); + flen = utf_ptr2len(fword + fwordidx[depth]); + ulen = utf_ptr2len(uword + uwordidx[depth]); if (round[depth] == 1) { p = fword + fwordidx[depth]; l = flen; @@ -5514,9 +5512,9 @@ badword: // lower to upper case. Helps for "tath" -> "Kath", which is // less common than "tath" -> "path". Don't do it when the // letter is the same, that has already been counted. - gc = PTR2CHAR(p); + gc = utf_ptr2char(p); if (SPELL_ISUPPER(gc)) { - bc = PTR2CHAR(su->su_badword); + bc = utf_ptr2char(su->su_badword); if (!SPELL_ISUPPER(bc) && SPELL_TOFOLD(bc) != SPELL_TOFOLD(gc)) { goodscore += SCORE_ICASE / 2; @@ -6938,7 +6936,7 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg) if (n == WF_ONECAP) { dumpflags |= DUMPFLAG_ONECAP; } else if (n == WF_ALLCAP - && (int)STRLEN(pat) > mb_ptr2len(pat)) { + && (int)STRLEN(pat) > utfc_ptr2len(pat)) { dumpflags |= DUMPFLAG_ALLCAP; } } @@ -7187,7 +7185,7 @@ static linenr_T dump_prefixes(slang_T *slang, char_u *word, char_u *pat, Directi // If the word starts with a lower-case letter make the word with an // upper-case letter in word_up[]. - c = PTR2CHAR(word); + c = utf_ptr2char(word); if (SPELL_TOUPPER(c) != c) { onecap_copy(word, word_up, true); has_word_up = true; diff --git a/src/nvim/spell_defs.h b/src/nvim/spell_defs.h index 78aa6bf199..220f51cd2f 100644 --- a/src/nvim/spell_defs.h +++ b/src/nvim/spell_defs.h @@ -230,7 +230,7 @@ typedef enum { 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_FINAL, // End of this node. } state_T; // Struct to keep the state at each level in suggest_try_change(). diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index e3a6236ae4..0fc9012f27 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -549,7 +549,7 @@ 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, ;); + SPELL_READ_BYTES(buf, VIMSPELLMAGICL, fd, ; ); if (memcmp(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0) { return SP_FORMERROR; } @@ -584,7 +584,7 @@ slang_T *spell_load_file(char_u *fname, char_u *lang, slang_T *old_lp, bool sile fd = os_fopen((char *)fname, "r"); if (fd == NULL) { if (!silent) { - EMSG2(_(e_notopen), fname); + semsg(_(e_notopen), fname); } else if (p_verbose > 2) { verbose_enter(); smsg((char *)e_notopen, fname); @@ -619,10 +619,10 @@ slang_T *spell_load_file(char_u *fname, char_u *lang, slang_T *old_lp, bool sile switch (scms_ret) { case SP_FORMERROR: case SP_TRUNCERROR: - emsgf("%s", _("E757: This does not look like a spell file")); + semsg("%s", _("E757: This does not look like a spell file")); goto endFAIL; case SP_OTHERERROR: - emsgf(_("E5042: Failed to read spell file %s: %s"), + semsg(_("E5042: Failed to read spell file %s: %s"), fname, strerror(ferror(fd))); goto endFAIL; case 0: @@ -630,10 +630,10 @@ slang_T *spell_load_file(char_u *fname, char_u *lang, slang_T *old_lp, bool sile } c = getc(fd); // <versionnr> if (c < VIMSPELLVERSION) { - EMSG(_("E771: Old spell file, needs to be updated")); + 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")); + emsg(_("E772: Spell file is for newer version of Vim")); goto endFAIL; } @@ -742,7 +742,7 @@ slang_T *spell_load_file(char_u *fname, char_u *lang, slang_T *old_lp, bool sile // 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")); + emsg(_("E770: Unsupported section in spell file")); goto endFAIL; } while (--len >= 0) { @@ -754,12 +754,12 @@ slang_T *spell_load_file(char_u *fname, char_u *lang, slang_T *old_lp, bool sile } someerror: if (res == SP_FORMERROR) { - EMSG(_(e_format)); + emsg(_(e_format)); goto endFAIL; } if (res == SP_TRUNCERROR) { truncerr: - EMSG(_(e_spell_trunc)); + emsg(_(e_spell_trunc)); goto endFAIL; } if (res == SP_OTHERERROR) { @@ -907,17 +907,17 @@ void suggest_load_files(void) buf[i] = getc(fd); // <fileID> } if (STRNCMP(buf, VIMSUGMAGIC, VIMSUGMAGICL) != 0) { - EMSG2(_("E778: This does not look like a .sug file: %s"), + semsg(_("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"), + semsg(_("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"), + semsg(_("E780: .sug file is for newer version of Vim: %s"), slang->sl_fname); goto nextone; } @@ -926,7 +926,7 @@ void suggest_load_files(void) // 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"), + semsg(_("E781: .sug file doesn't match .spl file: %s"), slang->sl_fname); goto nextone; } @@ -936,7 +936,7 @@ void suggest_load_files(void) if (spell_read_tree(fd, &slang->sl_sbyts, NULL, &slang->sl_sidxs, false, 0) != 0) { someerror: - EMSG2(_("E782: error while reading .sug file: %s"), + semsg(_("E782: error while reading .sug file: %s"), slang->sl_fname); slang_clear_sug(slang); goto nextone; @@ -1030,7 +1030,7 @@ static int read_region_section(FILE *fd, slang_T *lp, int len) if (len > MAXREGIONS * 2) { return SP_FORMERROR; } - SPELL_READ_NONNUL_BYTES((char *)lp->sl_regions, (size_t)len, fd, ;); + SPELL_READ_NONNUL_BYTES((char *)lp->sl_regions, (size_t)len, fd, ; ); lp->sl_regions[len] = NUL; return 0; } @@ -1097,7 +1097,7 @@ static int read_prefcond_section(FILE *fd, slang_T *lp) 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, ;); + 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); } @@ -2042,7 +2042,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) // Open the file. fd = os_fopen((char *)fname, "r"); if (fd == NULL) { - EMSG2(_(e_notopen), fname); + semsg(_(e_notopen), fname); return NULL; } @@ -2504,19 +2504,19 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) // 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)] == + && aff_entry->ae_chop[utfc_ptr2len(aff_entry->ae_chop)] == NUL) { int c, c_up; - c = PTR2CHAR(aff_entry->ae_chop); + c = utf_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)) { + || utf_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) { + if (utf_ptr2char(p) == c_up) { upper = true; aff_entry->ae_chop = NULL; *p = NUL; @@ -2748,11 +2748,11 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) // 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")); + msg(_("Too many postponed prefixes")); } else if (spin->si_newprefID == 0 || spin->si_newprefID == 127) { - MSG(_("Too many compound flags")); + msg(_("Too many compound flags")); } else { - MSG(_("Too many postponed prefixes and/or compound flags")); + msg(_("Too many postponed prefixes and/or compound flags")); } } @@ -3126,7 +3126,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile) // Open the file. fd = os_fopen((char *)fname, "r"); if (fd == NULL) { - EMSG2(_(e_notopen), fname); + semsg(_(e_notopen), fname); return FAIL; } @@ -3142,7 +3142,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile) // Read and ignore the first line: word count. if (vim_fgets(line, MAXLINELEN, fd) || !ascii_isdigit(*skipwhite(line))) { - EMSG2(_("E760: No word count in %s"), fname); + semsg(_("E760: No word count in %s"), fname); } // Read all the lines in the file one by one. @@ -3209,7 +3209,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile) _("line %6d, word %6ld - %s"), lnum, spin->si_foldwcount + spin->si_keepwcount, w); msg_start(); - msg_puts_long_attr(message, 0); + msg_outtrans_long_attr(message, 0); msg_clr_eos(); msg_didout = false; msg_col = 0; @@ -3501,7 +3501,7 @@ static int store_aff_word(spellinfo_T *spin, char_u *word, char_u *afflist, afff if (ae->ae_chop != NULL) { // Remove chop string. p = newword + STRLEN(newword); - i = (int)MB_CHARLEN(ae->ae_chop); + i = mb_charlen(ae->ae_chop); for (; i > 0; i--) { MB_PTR_BACK(newword, p); } @@ -3684,7 +3684,7 @@ static int spell_read_wordfile(spellinfo_T *spin, char_u *fname) // Open the file. fd = os_fopen((char *)fname, "r"); if (fd == NULL) { - EMSG2(_(e_notopen), fname); + semsg(_(e_notopen), fname); return FAIL; } @@ -4352,7 +4352,7 @@ static int write_vim_spell(spellinfo_T *spin, char_u *fname) FILE *fd = os_fopen((char *)fname, "w"); if (fd == NULL) { - EMSG2(_(e_notopen), fname); + semsg(_(e_notopen), fname); return FAIL; } @@ -4723,7 +4723,7 @@ theend: retval = FAIL; } if (retval == FAIL) { - EMSG(_(e_write)); + emsg(_(e_write)); } return retval; @@ -4845,7 +4845,7 @@ static int put_node(FILE *fd, wordnode_T *node, int idx, int regionmask, bool pr if (fd != NULL) { if (putc(np->wn_byte, fd) == EOF) { // <byte> or <xbyte> - EMSG(_(e_write)); + emsg(_(e_write)); return 0; } } @@ -5164,13 +5164,13 @@ static int offset2bytes(int nr, char_u *buf) buf[3] = b1; return 4; } - if (b3 > 1 || b2 > 0x3f ) { // 3 bytes + 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 + if (b2 > 1 || b1 > 0x7f) { // 2 bytes buf[0] = 0x80 + b2; buf[1] = b1; return 2; @@ -5186,7 +5186,7 @@ static void sug_write(spellinfo_T *spin, char_u *fname) // Create the file. Note that an existing file is silently overwritten! FILE *fd = os_fopen((char *)fname, "w"); if (fd == NULL) { - EMSG2(_(e_notopen), fname); + semsg(_(e_notopen), fname); return; } @@ -5196,7 +5196,7 @@ static void sug_write(spellinfo_T *spin, char_u *fname) // <SUGHEADER>: <fileID> <versionnr> <timestamp> if (fwrite(VIMSUGMAGIC, VIMSUGMAGICL, (size_t)1, fd) != 1) { // <fileID> - EMSG(_(e_write)); + emsg(_(e_write)); goto theend; } putc(VIMSUGVERSION, fd); // <versionnr> @@ -5234,7 +5234,7 @@ static void sug_write(spellinfo_T *spin, char_u *fname) 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)); + emsg(_(e_write)); goto theend; } assert((size_t)spin->si_memtot + len <= INT_MAX); @@ -5243,7 +5243,7 @@ static void sug_write(spellinfo_T *spin, char_u *fname) // Write another byte to check for errors. if (putc(0, fd) == EOF) { - EMSG(_(e_write)); + emsg(_(e_write)); } vim_snprintf((char *)IObuff, IOSIZE, @@ -5331,20 +5331,20 @@ static void mkspell(int fcount, char_u **fnames, bool ascii, bool over_write, bo } if (incount <= 0) { - EMSG(_(e_invarg)); // need at least output and input names + 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")); + emsg(_("E751: Output file name must not have region name")); } else if (incount > MAXREGIONS) { - emsgf(_("E754: Only up to %d regions supported"), MAXREGIONS); + semsg(_("E754: Only up to %d regions supported"), MAXREGIONS); } else { // Check for overwriting before doing things that may take a lot of // time. if (!over_write && os_path_exists(wfname)) { - EMSG(_(e_exists)); + emsg(_(e_exists)); goto theend; } if (os_isdir(wfname)) { - EMSG2(_(e_isadir2), wfname); + semsg(_(e_isadir2), wfname); goto theend; } @@ -5359,7 +5359,7 @@ static void mkspell(int fcount, char_u **fnames, bool ascii, bool over_write, bo len = (int)STRLEN(innames[i]); if (STRLEN(path_tail(innames[i])) < 5 || innames[i][len - 3] != '_') { - EMSG2(_("E755: Invalid region in %s"), innames[i]); + semsg(_("E755: Invalid region in %s"), innames[i]); goto theend; } spin.si_region_name[i * 2] = TOLOWER_ASC(innames[i][len - 2]); @@ -5417,7 +5417,7 @@ static void mkspell(int fcount, char_u **fnames, bool ascii, bool over_write, bo } if (spin.si_compflags != NULL && spin.si_nobreak) { - MSG(_("Warning: both compounding and NOBREAK specified")); + msg(_("Warning: both compounding and NOBREAK specified")); } if (!error && !got_int) { @@ -5487,7 +5487,7 @@ static void spell_message(const spellinfo_T *spin, char_u *str) if (!spin->si_verbose) { verbose_enter(); } - MSG(str); + msg((char *)str); ui_flush(); if (!spin->si_verbose) { verbose_leave(); @@ -5541,7 +5541,7 @@ void spell_add_word(char_u *word, int len, SpellAddType what, int idx, bool undo } if (*curwin->w_s->b_p_spf == NUL) { - EMSG2(_(e_notset), "spellfile"); + semsg(_(e_notset), "spellfile"); return; } fnamebuf = xmalloc(MAXPATHL); @@ -5552,7 +5552,7 @@ void spell_add_word(char_u *word, int len, SpellAddType what, int idx, bool undo break; } if (*spf == NUL) { - EMSGN(_("E765: 'spellfile' does not have %" PRId64 " entries"), idx); + semsg(_("E765: 'spellfile' does not have %" PRId64 " entries"), (int64_t)idx); xfree(fnamebuf); return; } @@ -5564,7 +5564,7 @@ void spell_add_word(char_u *word, int len, SpellAddType what, int idx, bool undo buf = NULL; } if (buf != NULL && bufIsChanged(buf)) { - EMSG(_(e_bufloaded)); + emsg(_(e_bufloaded)); xfree(fnamebuf); return; } @@ -5632,7 +5632,7 @@ void spell_add_word(char_u *word, int len, SpellAddType what, int idx, bool undo } if (fd == NULL) { - EMSG2(_(e_notopen), fname); + semsg(_(e_notopen), fname); } else { if (what == SPELL_ADD_BAD) { fprintf(fd, "%.*s/!\n", len, word); @@ -5778,7 +5778,7 @@ static int set_spell_finish(spelltab_T *new_st) || 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")); + emsg(_("E763: Word characters differ between spell files")); return FAIL; } } @@ -5858,8 +5858,8 @@ static void set_map_str(slang_T *lp, char_u *map) // 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); + int cl = utf_char2len(c); + int headcl = utf_char2len(headc); char_u *b; hash_T hash; hashitem_T *hi; @@ -5876,7 +5876,7 @@ static void set_map_str(slang_T *lp, char_u *map) } else { // This should have been checked when generating the .spl // file. - EMSG(_("E783: duplicate char in MAP entry")); + emsg(_("E783: duplicate char in MAP entry")); xfree(b); } } else { diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 11c1aa1760..47cbf01996 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -283,7 +283,7 @@ char_u *vim_strsave_shellescape(const char_u *string, bool do_special, bool do_n continue; } - MB_COPY_CHAR(p, d); + mb_copy_char(&p, &d); } // add terminating quote and finish with a NUL @@ -557,7 +557,7 @@ static varnumber_T tv_nr(typval_T *tvs, int *idxp) varnumber_T n = 0; if (tvs[idx].v_type == VAR_UNKNOWN) { - EMSG(_(e_printf)); + emsg(_(e_printf)); } else { (*idxp)++; bool err = false; @@ -590,7 +590,7 @@ static const char *tv_str(typval_T *tvs, int *idxp, char **const tofree) const char *s = NULL; if (tvs[idx].v_type == VAR_UNKNOWN) { - EMSG(_(e_printf)); + emsg(_(e_printf)); } else { (*idxp)++; if (tvs[idx].v_type == VAR_STRING || tvs[idx].v_type == VAR_NUMBER) { @@ -627,7 +627,7 @@ static const void *tv_ptr(const typval_T *const tvs, int *const idxp) #undef OFF const int idx = *idxp - 1; if (tvs[idx].v_type == VAR_UNKNOWN) { - EMSG(_(e_printf)); + emsg(_(e_printf)); return NULL; } else { (*idxp)++; @@ -652,7 +652,7 @@ static float_T tv_float(typval_T *const tvs, int *const idxp) float_T f = 0; if (tvs[idx].v_type == VAR_UNKNOWN) { - EMSG(_(e_printf)); + emsg(_(e_printf)); } else { (*idxp)++; if (tvs[idx].v_type == VAR_FLOAT) { @@ -660,7 +660,7 @@ static float_T tv_float(typval_T *const tvs, int *const idxp) } else if (tvs[idx].v_type == VAR_NUMBER) { f = (float_T)tvs[idx].vval.v_number; } else { - EMSG(_("E807: Expected Float argument for printf()")); + emsg(_("E807: Expected Float argument for printf()")); } } return f; @@ -706,7 +706,7 @@ static float_T tv_float(typval_T *const tvs, int *const idxp) /// Append a formatted value to the string /// /// @see vim_vsnprintf_typval(). -int vim_snprintf_add(char *str, size_t str_m, char *fmt, ...) +int vim_snprintf_add(char *str, size_t str_m, const char *fmt, ...) FUNC_ATTR_PRINTF(3, 4) { const size_t len = strlen(str); @@ -999,7 +999,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap, t size_t i = 0; for (p1 = (char_u *)str_arg; *p1; - p1 += mb_ptr2len(p1)) { + p1 += utfc_ptr2len(p1)) { i += (size_t)utf_ptr2cells(p1); if (i > precision) { break; @@ -1184,7 +1184,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap, t zero_padding_insertion_ind++; } if (zero_padding_insertion_ind + 1 < str_arg_l - && tmp[zero_padding_insertion_ind] == '0' + && 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' @@ -1456,7 +1456,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap, t } if (tvs && tvs[arg_idx - 1].v_type != VAR_UNKNOWN) { - EMSG(_("E767: Too many arguments to printf()")); + emsg(_("E767: Too many arguments to printf()")); } // return the number of characters formatted (excluding trailing nul diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 1e14f988f1..504d1cd16e 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -929,9 +929,9 @@ static void syn_update_ends(bool startofline) stateitem_T *cur_si; if (startofline) { - /* Check for a match carried over from a previous line with a - * contained region. The match ends as soon as the region ends. */ - for (int i = 0; i < current_state.ga_len; ++i) { + // Check for a match carried over from a previous line with a + // contained region. The match ends as soon as the region ends. + for (int i = 0; i < current_state.ga_len; i++) { cur_si = &CUR_STATE(i); if (cur_si->si_idx >= 0 && (SYN_ITEMS(syn_block)[cur_si->si_idx]).sp_type @@ -1082,7 +1082,6 @@ static void syn_stack_alloc(void) // Make sure that all valid entries fit in the new array. while (syn_block->b_sst_len - syn_block->b_sst_freecount + 2 > len && syn_stack_cleanup()) { - ; } if (len < syn_block->b_sst_len - syn_block->b_sst_freecount + 2) { len = syn_block->b_sst_len - syn_block->b_sst_freecount + 2; @@ -1335,8 +1334,8 @@ static synstate_T *store_current_state(void) if (syn_block->b_sst_freecount == 0) { sp = NULL; } else { - /* Take the first item from the free list and put it in the used - * list, after *sp */ + // Take the first item from the free list and put it in the used + // list, after *sp p = syn_block->b_sst_firstfree; syn_block->b_sst_firstfree = p->sst_next; --syn_block->b_sst_freecount; @@ -1359,8 +1358,8 @@ static synstate_T *store_current_state(void) clear_syn_state(sp); sp->sst_stacksize = current_state.ga_len; if (current_state.ga_len > SST_FIX_STATES) { - /* Need to clear it, might be something remaining from when the - * length was less than SST_FIX_STATES. */ + // Need to clear it, might be something remaining from when the + // length was less than SST_FIX_STATES. ga_init(&sp->sst_union.sst_ga, (int)sizeof(bufstate_T), 1); ga_grow(&sp->sst_union.sst_ga, current_state.ga_len); sp->sst_union.sst_ga.ga_len = current_state.ga_len; @@ -1458,24 +1457,24 @@ static bool syn_stack_equal(synstate_T *sp) if (bp[i].bs_extmatch == CUR_STATE(i).si_extmatch) { continue; } - /* When the extmatch pointers are different, the strings in - * them can still be the same. Check if the extmatch - * references are equal. */ + // When the extmatch pointers are different, the strings in + // them can still be the same. Check if the extmatch + // references are equal. bsx = bp[i].bs_extmatch; six = CUR_STATE(i).si_extmatch; - /* If one of the extmatch pointers is NULL the states are - * different. */ + // If one of the extmatch pointers is NULL the states are + // different. if (bsx == NULL || six == NULL) { break; } int j; - for (j = 0; j < NSUBEXP; ++j) { - /* Check each referenced match string. They must all be - * equal. */ + for (j = 0; j < NSUBEXP; j++) { + // Check each referenced match string. They must all be + // equal. if (bsx->matches[j] != six->matches[j]) { - /* 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 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) { break; } @@ -1749,8 +1748,8 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con && (syn_block->b_keywtab.ht_used > 0 || syn_block->b_keywtab_ic.ht_used > 0); - /* Init the list of zero-width matches with a nextlist. This is used to - * avoid matching the same item in the same position twice. */ + // Init the list of zero-width matches with a nextlist. This is used to + // avoid matching the same item in the same position twice. ga_init(&zero_width_next_ga, (int)sizeof(int), 10); // use syntax iskeyword option @@ -1867,9 +1866,9 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con : in_id_list(cur_si, cur_si->si_cont_list, &spp->sp_syn, spp->sp_flags & HL_CONTAINED)))) { - /* If we already tried matching in this line, and - * there isn't a match before next_match_col, skip - * this item. */ + // If we already tried matching in this line, and + // there isn't a match before next_match_col, skip + // this item. if (spp->sp_line_id == current_line_id && spp->sp_startcol >= next_match_col) { continue; @@ -2037,9 +2036,9 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con keep_next_list = true; zero_width_next_list = true; - /* Add the index to a list, so that we can check - * later that we don't match it again (and cause an - * endless loop). */ + // Add the index to a list, so that we can check + // later that we don't match it again (and cause an + // endless loop). GA_APPEND(int, &zero_width_next_ga, next_match_idx); next_match_idx = -1; } else { @@ -2136,10 +2135,10 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con *can_spell = !in_id_list(sip, sip->si_cont_list, &sps, 0); } } else { - /* The @Spell cluster is defined: Do spelling in items with - * the @Spell cluster. But not when @NoSpell is also there. - * At the toplevel only spell check when ":syn spell toplevel" - * was used. */ + // The @Spell cluster is defined: Do spelling in items with + // the @Spell cluster. But not when @NoSpell is also there. + // At the toplevel only spell check when ":syn spell toplevel" + // was used. if (current_trans_id == 0) { *can_spell = (syn_block->b_syn_spell == SYNSPL_TOP); } else { @@ -2216,8 +2215,8 @@ static bool did_match_already(int idx, garray_T *gap) } } - /* Zero-width matches with a nextgroup argument are not put on the syntax - * stack, and can only be matched once anyway. */ + // Zero-width matches with a nextgroup argument are not put on the syntax + // stack, and can only be matched once anyway. for (int i = gap->ga_len; --i >= 0; ) { if (((int *)(gap->ga_data))[i] == idx) { return true; @@ -2353,8 +2352,8 @@ static void check_state_ends(void) next_match_col = MAXCOL; break; } else { - /* handle next_list, unless at end of line and no "skipnl" or - * "skipempty" */ + // handle next_list, unless at end of line and no "skipnl" or + // "skipempty" current_next_list = cur_si->si_next_list; current_next_flags = cur_si->si_flags; if (!(current_next_flags & (HL_SKIPNL | HL_SKIPEMPTY)) @@ -3006,7 +3005,7 @@ static int syn_regexec(regmmatch_T *rmp, linenr_T lnum, colnr_T col, syn_time_T } if (timed_out && !syn_win->w_s->b_syn_slow) { syn_win->w_s->b_syn_slow = true; - MSG(_("'redrawtime' exceeded, syntax highlighting disabled")); + msg(_("'redrawtime' exceeded, syntax highlighting disabled")); } if (r > 0) { @@ -3111,16 +3110,16 @@ static void syn_cmd_conceal(exarg_T *eap, int syncing) next = skiptowhite(arg); if (*arg == NUL) { if (curwin->w_s->b_syn_conceal) { - MSG(_("syntax conceal on")); + msg(_("syntax conceal on")); } else { - MSG(_("syntax conceal off")); + msg(_("syntax conceal off")); } } else if (STRNICMP(arg, "on", 2) == 0 && next - arg == 2) { curwin->w_s->b_syn_conceal = true; } else if (STRNICMP(arg, "off", 3) == 0 && next - arg == 3) { curwin->w_s->b_syn_conceal = false; } else { - EMSG2(_(e_illegal_arg), arg); + semsg(_(e_illegal_arg), arg); } } @@ -3140,16 +3139,16 @@ static void syn_cmd_case(exarg_T *eap, int syncing) next = skiptowhite(arg); if (*arg == NUL) { if (curwin->w_s->b_syn_ic) { - MSG(_("syntax case ignore")); + msg(_("syntax case ignore")); } else { - MSG(_("syntax case match")); + msg(_("syntax case match")); } } else if (STRNICMP(arg, "match", 5) == 0 && next - arg == 5) { curwin->w_s->b_syn_ic = false; } else if (STRNICMP(arg, "ignore", 6) == 0 && next - arg == 6) { curwin->w_s->b_syn_ic = true; } else { - EMSG2(_(e_illegal_arg), arg); + semsg(_(e_illegal_arg), arg); } } @@ -3167,9 +3166,9 @@ static void syn_cmd_foldlevel(exarg_T *eap, int syncing) if (*arg == NUL) { switch (curwin->w_s->b_syn_foldlevel) { case SYNFLD_START: - MSG(_("syntax foldlevel start")); break; + msg(_("syntax foldlevel start")); break; case SYNFLD_MINIMUM: - MSG(_("syntax foldlevel minimum")); break; + msg(_("syntax foldlevel minimum")); break; default: break; } @@ -3182,13 +3181,13 @@ static void syn_cmd_foldlevel(exarg_T *eap, int syncing) } else if (STRNICMP(arg, "minimum", 7) == 0 && arg_end - arg == 7) { curwin->w_s->b_syn_foldlevel = SYNFLD_MINIMUM; } else { - EMSG2(_(e_illegal_arg), arg); + semsg(_(e_illegal_arg), arg); return; } arg = skipwhite(arg_end); if (*arg != NUL) { - EMSG2(_(e_illegal_arg), arg); + semsg(_(e_illegal_arg), arg); } } @@ -3208,11 +3207,11 @@ static void syn_cmd_spell(exarg_T *eap, int syncing) next = skiptowhite(arg); if (*arg == NUL) { if (curwin->w_s->b_syn_spell == SYNSPL_TOP) { - MSG(_("syntax spell toplevel")); + msg(_("syntax spell toplevel")); } else if (curwin->w_s->b_syn_spell == SYNSPL_NOTOP) { - MSG(_("syntax spell notoplevel")); + msg(_("syntax spell notoplevel")); } else { - MSG(_("syntax spell default")); + msg(_("syntax spell default")); } } else if (STRNICMP(arg, "toplevel", 8) == 0 && next - arg == 8) { curwin->w_s->b_syn_spell = SYNSPL_TOP; @@ -3221,7 +3220,7 @@ static void syn_cmd_spell(exarg_T *eap, int syncing) } else if (STRNICMP(arg, "default", 7) == 0 && next - arg == 7) { curwin->w_s->b_syn_spell = SYNSPL_DEFAULT; } else { - EMSG2(_(e_illegal_arg), arg); + semsg(_(e_illegal_arg), arg); return; } @@ -3242,9 +3241,9 @@ static void syn_cmd_iskeyword(exarg_T *eap, int syncing) arg = skipwhite(arg); if (*arg == NUL) { - MSG_PUTS("\n"); + msg_puts("\n"); if (curwin->w_s->b_syn_isk != empty_option) { - MSG_PUTS(_("syntax iskeyword ")); + msg_puts(_("syntax iskeyword ")); msg_outtrans(curwin->w_s->b_syn_isk); } else { msg_outtrans((char_u *)_("syntax iskeyword not set")); @@ -3445,7 +3444,7 @@ static void syn_cmd_clear(exarg_T *eap, int syncing) if (*arg == '@') { id = syn_scl_namen2id(arg + 1, (int)(arg_end - arg - 1)); if (id == 0) { - EMSG2(_("E391: No such syntax cluster: %s"), arg); + semsg(_("E391: No such syntax cluster: %s"), arg); break; } else { // We can't physically delete a cluster without changing @@ -3458,7 +3457,7 @@ static void syn_cmd_clear(exarg_T *eap, int syncing) } else { id = syn_name2id_len(arg, (int)(arg_end - arg)); if (id == 0) { - EMSG2(_(e_nogroup), arg); + semsg(_(e_nogroup), arg); break; } else { syn_clear_one(id, syncing); @@ -3567,41 +3566,41 @@ static void syn_cmd_list(exarg_T *eap, int syncing) } if (!syntax_present(curwin)) { - MSG(_(msg_no_items)); + msg(_(msg_no_items)); return; } if (syncing) { if (curwin->w_s->b_syn_sync_flags & SF_CCOMMENT) { - MSG_PUTS(_("syncing on C-style comments")); + msg_puts(_("syncing on C-style comments")); syn_lines_msg(); syn_match_msg(); return; } else if (!(curwin->w_s->b_syn_sync_flags & SF_MATCH)) { if (curwin->w_s->b_syn_sync_minlines == 0) { - MSG_PUTS(_("no syncing")); + msg_puts(_("no syncing")); } else { if (curwin->w_s->b_syn_sync_minlines == MAXLNUM) { - MSG_PUTS(_("syncing starts at the first line")); + msg_puts(_("syncing starts at the first line")); } else { - MSG_PUTS(_("syncing starts ")); + msg_puts(_("syncing starts ")); msg_outnum(curwin->w_s->b_syn_sync_minlines); - MSG_PUTS(_(" lines before top line")); + msg_puts(_(" lines before top line")); } syn_match_msg(); } return; } - MSG_PUTS_TITLE(_("\n--- Syntax sync items ---")); + msg_puts_title(_("\n--- Syntax sync items ---")); if (curwin->w_s->b_syn_sync_minlines > 0 || curwin->w_s->b_syn_sync_maxlines > 0 || curwin->w_s->b_syn_sync_linebreaks > 0) { - MSG_PUTS(_("\nsyncing on items")); + msg_puts(_("\nsyncing on items")); syn_lines_msg(); syn_match_msg(); } } else { - MSG_PUTS_TITLE(_("\n--- Syntax items ---")); + msg_puts_title(_("\n--- Syntax items ---")); } if (ends_excmd(*arg)) { /* @@ -3622,14 +3621,14 @@ static void syn_cmd_list(exarg_T *eap, int syncing) if (*arg == '@') { int id = syn_scl_namen2id(arg + 1, (int)(arg_end - arg - 1)); if (id == 0) { - EMSG2(_("E392: No such syntax cluster: %s"), arg); + semsg(_("E392: No such syntax cluster: %s"), arg); } else { syn_list_cluster(id - SYNID_CLUSTER); } } else { int id = syn_name2id_len(arg, (int)(arg_end - arg)); if (id == 0) { - EMSG2(_(e_nogroup), arg); + semsg(_(e_nogroup), arg); } else { syn_list_one(id, syncing, true); } @@ -3644,22 +3643,22 @@ static void syn_lines_msg(void) { if (curwin->w_s->b_syn_sync_maxlines > 0 || curwin->w_s->b_syn_sync_minlines > 0) { - MSG_PUTS("; "); + msg_puts("; "); if (curwin->w_s->b_syn_sync_minlines == MAXLNUM) { - MSG_PUTS(_("from the first line")); + msg_puts(_("from the first line")); } else { if (curwin->w_s->b_syn_sync_minlines > 0) { - MSG_PUTS(_("minimal ")); + msg_puts(_("minimal ")); msg_outnum(curwin->w_s->b_syn_sync_minlines); if (curwin->w_s->b_syn_sync_maxlines) { - MSG_PUTS(", "); + msg_puts(", "); } } if (curwin->w_s->b_syn_sync_maxlines > 0) { - MSG_PUTS(_("maximal ")); + msg_puts(_("maximal ")); msg_outnum(curwin->w_s->b_syn_sync_maxlines); } - MSG_PUTS(_(" lines before top line")); + msg_puts(_(" lines before top line")); } } } @@ -3667,9 +3666,9 @@ static void syn_lines_msg(void) static void syn_match_msg(void) { if (curwin->w_s->b_syn_sync_linebreaks > 0) { - MSG_PUTS(_("; match ")); + msg_puts(_("; match ")); msg_outnum(curwin->w_s->b_syn_sync_linebreaks); - MSG_PUTS(_(" line breaks")); + msg_puts(_(" line breaks")); } } @@ -3768,7 +3767,7 @@ static void syn_list_one(const int id, const bool syncing, const bool link_only) msg_outtrans(HL_TABLE()[SYN_ITEMS(curwin->w_s) [spp->sp_sync_idx].sp_syn.id - 1].sg_name); } else { - MSG_PUTS("NONE"); + msg_puts("NONE"); } msg_putchar(' '); } @@ -4230,7 +4229,7 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha if (flagtab[fidx].argtype == 1) { if (!opt->has_cont_list) { - EMSG(_("E395: contains argument not accepted here")); + emsg(_("E395: contains argument not accepted here")); return NULL; } if (get_id_list(&arg, 8, &opt->cont_list, skip) == FAIL) { @@ -4247,9 +4246,9 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha } else if (flagtab[fidx].argtype == 11 && arg[5] == '=') { // cchar=? *conceal_char = utf_ptr2char(arg + 6); - arg += mb_ptr2len(arg + 6) - 1; + arg += utfc_ptr2len(arg + 6) - 1; if (!vim_isprintc_strict(*conceal_char)) { - EMSG(_("E844: invalid cchar value")); + emsg(_("E844: invalid cchar value")); return NULL; } arg = skipwhite(arg + 7); @@ -4260,7 +4259,7 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha if (flagtab[fidx].flags == HL_SYNC_HERE || flagtab[fidx].flags == HL_SYNC_THERE) { if (opt->sync_idx == NULL) { - EMSG(_("E393: group[t]here not accepted here")); + emsg(_("E393: group[t]here not accepted here")); return NULL; } gname_start = arg; @@ -4282,7 +4281,7 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha } } if (i < 0) { - EMSG2(_("E394: Didn't find region item for %s"), gname); + semsg(_("E394: Didn't find region item for %s"), gname); xfree(gname); return NULL; } @@ -4333,7 +4332,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing) int sgl_id = 1; char_u *group_name_end; char_u *rest; - char_u *errormsg = NULL; + char *errormsg = NULL; int prev_toplvl_grp; int prev_syn_inc_tag; bool source = false; @@ -4347,7 +4346,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing) ++arg; rest = get_group_name(arg, &group_name_end); if (rest == NULL) { - EMSG((char_u *)_("E397: Filename required")); + emsg(_("E397: Filename required")); return; } sgl_id = syn_check_cluster(arg, (int)(group_name_end - arg)); @@ -4371,7 +4370,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing) source = true; if (expand_filename(eap, syn_cmdlinep, &errormsg) == FAIL) { if (errormsg != NULL) { - EMSG(errormsg); + emsg(errormsg); } return; } @@ -4382,7 +4381,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing) * include" tag around the actual inclusion. */ if (running_syn_inc_tag >= MAX_SYN_INC_TAG) { - EMSG((char_u *)_("E847: Too many syntax includes")); + emsg(_("E847: Too many syntax includes")); return; } prev_syn_inc_tag = current_syn_inc_tag; @@ -4392,7 +4391,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing) if (source ? do_source((char *)eap->arg, false, DOSO_NONE) == FAIL : source_runtime((char *)eap->arg, DIP_ALL) == FAIL) { - EMSG2(_(e_notopen), eap->arg); + semsg(_(e_notopen), eap->arg); } curwin->w_s->b_syn_topgrp = prev_toplvl_grp; current_syn_inc_tag = prev_syn_inc_tag; @@ -4472,19 +4471,19 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing) break; } if (p[1] == NUL) { - emsgf(_("E789: Missing ']': %s"), kw); + semsg(_("E789: Missing ']': %s"), kw); goto error; } if (p[1] == ']') { if (p[2] != NUL) { - emsgf(_("E890: trailing char after ']': %s]%s"), + semsg(_("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); + const int l = utfc_ptr2len(p + 1); memmove(p, p + 1, l); p += l; @@ -4502,7 +4501,7 @@ error: if (rest != NULL) { eap->nextcmd = check_nextcmd(rest); } else { - EMSG2(_(e_invarg2), arg); + semsg(_(e_invarg2), arg); } redraw_curbuf_later(SOME_VALID); @@ -4604,7 +4603,7 @@ static void syn_cmd_match(exarg_T *eap, int syncing) xfree(syn_opt_arg.next_list); if (rest == NULL) { - EMSG2(_(e_invarg2), arg); + semsg(_(e_invarg2), arg); } } @@ -4692,7 +4691,7 @@ static void syn_cmd_region(exarg_T *eap, int syncing) rest = skipwhite(key_end); if (*rest != '=') { rest = NULL; - EMSG2(_("E398: Missing '=': %s"), arg); + semsg(_("E398: Missing '=': %s"), arg); break; } rest = skipwhite(rest + 1); @@ -4831,9 +4830,9 @@ static void syn_cmd_region(exarg_T *eap, int syncing) xfree(syn_opt_arg.cont_in_list); xfree(syn_opt_arg.next_list); if (not_enough) { - EMSG2(_("E399: Not enough arguments: syntax region %s"), arg); + semsg(_("E399: Not enough arguments: syntax region %s"), arg); } else if (illegal || rest == NULL) { - EMSG2(_(e_invarg2), arg); + semsg(_(e_invarg2), arg); } } } @@ -5030,7 +5029,7 @@ static int syn_add_cluster(char_u *name) int len = curwin->w_s->b_syn_clusters.ga_len; if (len >= MAX_CLUSTER_ID) { - EMSG((char_u *)_("E848: Too many syntax clusters")); + emsg(_("E848: Too many syntax clusters")); xfree(name); return 0; } @@ -5098,7 +5097,7 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing) int16_t *clstr_list = NULL; if (get_id_list(&rest, opt_len, &clstr_list, eap->skip) == FAIL) { - EMSG2(_(e_invarg2), rest); + semsg(_(e_invarg2), rest); break; } if (scl_id >= 0) { @@ -5117,10 +5116,10 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing) } if (!got_clstr) { - EMSG(_("E400: No cluster specified")); + emsg(_("E400: No cluster specified")); } if (rest == NULL || !ends_excmd(*rest)) { - EMSG2(_(e_invarg2), arg); + semsg(_(e_invarg2), arg); } } @@ -5152,7 +5151,7 @@ static char_u *get_syn_pattern(char_u *arg, synpat_T *ci) end = skip_regexp(arg + 1, *arg, TRUE, NULL); if (*end != *arg) { // end delimiter not found - EMSG2(_("E401: Pattern delimiter not found: %s"), arg); + semsg(_("E401: Pattern delimiter not found: %s"), arg); return NULL; } // store the pattern and compiled regexp program @@ -5224,7 +5223,7 @@ static char_u *get_syn_pattern(char_u *arg, synpat_T *ci) } while (idx >= 0); if (!ends_excmd(*end) && !ascii_iswhite(*end)) { - EMSG2(_("E402: Garbage after pattern: %s"), arg); + semsg(_("E402: Garbage after pattern: %s"), arg); return NULL; } return skipwhite(end); @@ -5303,7 +5302,7 @@ static void syn_cmd_sync(exarg_T *eap, int syncing) break; } if (curwin->w_s->b_syn_linecont_pat != NULL) { - EMSG(_("E403: syntax sync: line continuations pattern specified twice")); + emsg(_("E403: syntax sync: line continuations pattern specified twice")); finished = TRUE; break; } @@ -5352,7 +5351,7 @@ static void syn_cmd_sync(exarg_T *eap, int syncing) } xfree(key); if (illegal) { - EMSG2(_("E404: Illegal arguments: %s"), arg_start); + semsg(_("E404: Illegal arguments: %s"), arg_start); } else if (!finished) { eap->nextcmd = check_nextcmd(arg_start); redraw_curbuf_later(SOME_VALID); @@ -5388,12 +5387,12 @@ static int get_id_list(char_u **const arg, const int keylen, int16_t **const lis // skip "contains" p = skipwhite(*arg + keylen); if (*p != '=') { - EMSG2(_("E405: Missing equal sign: %s"), *arg); + semsg(_("E405: Missing equal sign: %s"), *arg); break; } p = skipwhite(p + 1); if (ends_excmd(*p)) { - EMSG2(_("E406: Empty argument: %s"), *arg); + semsg(_("E406: Empty argument: %s"), *arg); break; } @@ -5409,13 +5408,13 @@ static int get_id_list(char_u **const arg, const int keylen, int16_t **const lis || STRCMP(name + 1, "TOP") == 0 || STRCMP(name + 1, "CONTAINED") == 0) { if (TOUPPER_ASC(**arg) != 'C') { - EMSG2(_("E407: %s not allowed here"), name + 1); + semsg(_("E407: %s not allowed here"), name + 1); failed = true; xfree(name); break; } if (count != 0) { - EMSG2(_("E408: %s must be first in contains list"), + semsg(_("E408: %s must be first in contains list"), name + 1); failed = true; xfree(name); @@ -5480,7 +5479,7 @@ static int get_id_list(char_u **const arg, const int keylen, int16_t **const lis } xfree(name); if (id == 0) { - EMSG2(_("E409: Unknown group name: %s"), p); + semsg(_("E409: Unknown group name: %s"), p); failed = true; break; } @@ -5698,7 +5697,7 @@ void ex_syntax(exarg_T *eap) } for (int i = 0;; i++) { if (subcommands[i].name == NULL) { - EMSG2(_("E410: Invalid :syntax subcommand: %s"), subcmd_name); + semsg(_("E410: Invalid :syntax subcommand: %s"), subcmd_name); break; } if (STRCMP(subcmd_name, (char_u *)subcommands[i].name) == 0) { @@ -5770,7 +5769,7 @@ static enum { EXP_SUBCMD, // expand ":syn" sub-commands EXP_CASE, // expand ":syn case" arguments EXP_SPELL, // expand ":syn spell" arguments - EXP_SYNC // expand ":syn sync" arguments + EXP_SYNC, // expand ":syn sync" arguments } expand_what; /* @@ -6003,7 +6002,7 @@ void ex_syntime(exarg_T *eap) } else if (STRCMP(eap->arg, "report") == 0) { syntime_report(); } else { - EMSG2(_(e_invarg2), eap->arg); + semsg(_(e_invarg2), eap->arg); } } @@ -6023,7 +6022,7 @@ static void syntime_clear(void) synpat_T *spp; if (!syntax_present(curwin)) { - MSG(_(msg_no_items)); + msg(_(msg_no_items)); return; } for (int idx = 0; idx < curwin->w_s->b_syn_patterns.ga_len; ++idx) { @@ -6065,7 +6064,7 @@ static int syn_compare_syntime(const void *v1, const void *v2) static void syntime_report(void) { if (!syntax_present(curwin)) { - MSG(_(msg_no_items)); + msg(_(msg_no_items)); return; } @@ -6099,28 +6098,28 @@ static void syntime_report(void) syn_compare_syntime); } - MSG_PUTS_TITLE(_(" TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN")); - MSG_PUTS("\n"); + msg_puts_title(_(" TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN")); + msg_puts("\n"); for (int idx = 0; idx < ga.ga_len && !got_int; ++idx) { p = ((time_entry_T *)ga.ga_data) + idx; - MSG_PUTS(profile_msg(p->total)); - MSG_PUTS(" "); // make sure there is always a separating space + msg_puts(profile_msg(p->total)); + msg_puts(" "); // make sure there is always a separating space msg_advance(13); msg_outnum(p->count); - MSG_PUTS(" "); + msg_puts(" "); msg_advance(20); msg_outnum(p->match); - MSG_PUTS(" "); + msg_puts(" "); msg_advance(26); - MSG_PUTS(profile_msg(p->slowest)); - MSG_PUTS(" "); + msg_puts(profile_msg(p->slowest)); + msg_puts(" "); msg_advance(38); - MSG_PUTS(profile_msg(p->average)); - MSG_PUTS(" "); + msg_puts(profile_msg(p->average)); + msg_puts(" "); msg_advance(50); msg_outtrans(HL_TABLE()[p->id - 1].sg_name); - MSG_PUTS(" "); + msg_puts(" "); msg_advance(69); int len; @@ -6133,15 +6132,15 @@ static void syntime_report(void) len = (int)STRLEN(p->pattern); } msg_outtrans_len(p->pattern, len); - MSG_PUTS("\n"); + msg_puts("\n"); } ga_clear(&ga); if (!got_int) { - MSG_PUTS("\n"); - MSG_PUTS(profile_msg(total_total)); + msg_puts("\n"); + msg_puts(profile_msg(total_total)); msg_advance(13); msg_outnum(total_count); - MSG_PUTS("\n"); + msg_puts("\n"); } } @@ -6776,7 +6775,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) if (!doclear && !dolink && ends_excmd((uint8_t)(*linep))) { id = syn_name2id_len((const char_u *)line, (int)(name_end - line)); if (id == 0) { - emsgf(_("E411: highlight group not found: %s"), line); + semsg(_("E411: highlight group not found: %s"), line); } else { highlight_list_one(id); } @@ -6799,13 +6798,13 @@ void do_highlight(const char *line, const bool forceit, const bool init) if (ends_excmd((uint8_t)(*from_start)) || ends_excmd((uint8_t)(*to_start))) { - emsgf(_("E412: Not enough arguments: \":highlight link %s\""), + semsg(_("E412: Not enough arguments: \":highlight link %s\""), from_start); return; } if (!ends_excmd(*skipwhite((const char_u *)to_end))) { - emsgf(_("E413: Too many arguments: \":highlight link %s\""), from_start); + semsg(_("E413: Too many arguments: \":highlight link %s\""), from_start); return; } @@ -6831,7 +6830,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) if (to_id > 0 && !forceit && !init && hl_has_settings(from_id - 1, dodefault)) { if (sourcing_name == NULL && !dodefault) { - EMSG(_("E414: group has settings, highlight link ignored")); + emsg(_("E414: group has settings, highlight link ignored")); } } else if (hlgroup->sg_link != to_id || hlgroup->sg_script_ctx.sc_sid != current_sctx.sc_sid @@ -6903,7 +6902,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) while (!ends_excmd((uint8_t)(*linep))) { key_start = linep; if (*linep == '=') { - emsgf(_("E415: unexpected equal sign: %s"), key_start); + semsg(_("E415: unexpected equal sign: %s"), key_start); error = true; break; } @@ -6930,7 +6929,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) // Check for the equal sign. if (*linep != '=') { - emsgf(_("E416: missing equal sign: %s"), key_start); + semsg(_("E416: missing equal sign: %s"), key_start); error = true; break; } @@ -6942,7 +6941,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) arg_start = ++linep; linep = strchr(linep, '\''); if (linep == NULL) { - emsgf(_(e_invarg2), key_start); + semsg(_(e_invarg2), key_start); error = true; break; } @@ -6951,7 +6950,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) linep = (const char *)skiptowhite((const char_u *)linep); } if (linep == arg_start) { - emsgf(_("E417: missing argument: %s"), key_start); + semsg(_("E417: missing argument: %s"), key_start); error = true; break; } @@ -6978,7 +6977,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) } } if (i < 0) { - emsgf(_("E418: Illegal value: %s"), arg); + semsg(_("E418: Illegal value: %s"), arg); error = true; break; } @@ -7026,7 +7025,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) if (cterm_normal_fg_color) { color = cterm_normal_fg_color - 1; } else { - EMSG(_("E419: FG color unknown")); + emsg(_("E419: FG color unknown")); error = true; break; } @@ -7034,7 +7033,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) if (cterm_normal_bg_color > 0) { color = cterm_normal_bg_color - 1; } else { - EMSG(_("E420: BG color unknown")); + emsg(_("E420: BG color unknown")); error = true; break; } @@ -7048,7 +7047,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) } } if (i < 0) { - emsgf(_("E421: Color name or number not recognized: %s"), + semsg(_("E421: Color name or number not recognized: %s"), key_start); error = true; break; @@ -7181,7 +7180,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) HL_TABLE()[idx].sg_blend = -1; } } else { - emsgf(_("E423: Illegal argument: %s"), key_start); + semsg(_("E423: Illegal argument: %s"), key_start); error = true; break; } @@ -7417,8 +7416,8 @@ static bool highlight_list_arg(const int id, bool didh, const int type, int iarg didh = true; if (!got_int) { if (*name != NUL) { - MSG_PUTS_ATTR(name, HL_ATTR(HLF_D)); - MSG_PUTS_ATTR("=", HL_ATTR(HLF_D)); + msg_puts_attr(name, HL_ATTR(HLF_D)); + msg_puts_attr("=", HL_ATTR(HLF_D)); } msg_outtrans((char_u *)ts); } @@ -7699,14 +7698,14 @@ static int syn_add_group(char_u *name) // Check that the name is ASCII letters, digits and underscore. for (p = name; *p != NUL; ++p) { if (!vim_isprintc(*p)) { - EMSG(_("E669: Unprintable character in group name")); + emsg(_("E669: Unprintable character in group name")); xfree(name); return 0; } else if (!ASCII_ISALNUM(*p) && *p != '_') { /* This is an error, but since there previously was no check only * give a warning. */ msg_source(HL_ATTR(HLF_W)); - MSG(_("W18: Invalid character in group name")); + msg(_("W18: Invalid character in group name")); break; } } @@ -7720,7 +7719,7 @@ static int syn_add_group(char_u *name) } if (highlight_ga.ga_len >= MAX_HL_ID) { - EMSG(_("E849: Too many highlight and syntax groups")); + emsg(_("E849: Too many highlight and syntax groups")); xfree(name); return 0; } @@ -7771,8 +7770,6 @@ int syn_id2attr(int hl_id) } - - /* * Translate a group ID to the final group ID (following links). */ diff --git a/src/nvim/tag.c b/src/nvim/tag.c index c22d344878..673ebc2668 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -178,7 +178,7 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose) static int flags; if (tfu_in_use) { - EMSG(_(recurmsg)); + emsg(_(recurmsg)); return false; } @@ -271,30 +271,29 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose) g_do_tagpreview != 0 ? ptag_entry.tagname == NULL : tagstacklen == 0) { // empty stack - EMSG(_(e_tagstack)); + emsg(_(e_tagstack)); goto end_do_tag; } if (type == DT_POP) { // go to older position const bool old_KeyTyped = KeyTyped; if ((tagstackidx -= count) < 0) { - EMSG(_(bottommsg)); + emsg(_(bottommsg)); if (tagstackidx + count == 0) { // We did [num]^T from the bottom of the stack tagstackidx = 0; goto end_do_tag; } - /* We weren't at the bottom of the stack, so jump all the - * way to the bottom now. - */ + // We weren't at the bottom of the stack, so jump all the + // way to the bottom now. tagstackidx = 0; } else if (tagstackidx >= tagstacklen) { // count == 0? - EMSG(_(topmsg)); + emsg(_(topmsg)); goto end_do_tag; } - /* Make a copy of the fmark, autocommands may invalidate the - * tagstack before it's used. */ + // Make a copy of the fmark, autocommands may invalidate the + // tagstack before it's used. saved_fmark = tagstack[tagstackidx].fmark; if (saved_fmark.fnum != curbuf->b_fnum) { /* @@ -306,8 +305,8 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose) tagstackidx = oldtagstackidx; // back to old posn goto end_do_tag; } - /* A BufReadPost autocommand may jump to the '" mark, but - * we don't what that here. */ + // A BufReadPost autocommand may jump to the '" mark, but + // we don't what that here. curwin->w_cursor.lnum = saved_fmark.mark.lnum; } else { setpcmark(); @@ -343,10 +342,10 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose) * position. */ tagstackidx = tagstacklen - 1; - EMSG(_(topmsg)); + emsg(_(topmsg)); save_pos = false; } else if (tagstackidx < 0) { // must have been count == 0 - EMSG(_(bottommsg)); + emsg(_(bottommsg)); tagstackidx = 0; goto end_do_tag; } @@ -384,7 +383,7 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose) if (cur_match >= MAXCOL) { cur_match = MAXCOL - 1; } else if (cur_match < 0) { - EMSG(_("E425: Cannot go before first matching tag")); + emsg(_("E425: Cannot go before first matching tag")); skip_msg = true; cur_match = 0; cur_fnum = curbuf->b_fnum; @@ -488,9 +487,9 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose) // found: all matches found. } - /* If there already were some matches for the same name, move them - * to the start. Avoids that the order changes when using - * ":tnext" and jumping to another file. */ + // If there already were some matches for the same name, move them + // to the start. Avoids that the order changes when using + // ":tnext" and jumping to another file. if (!new_tag && !other_name) { int j, k; int idx = 0; @@ -520,7 +519,7 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose) if (num_matches <= 0) { if (verbose) { - EMSG2(_("E426: tag not found: %s"), name); + semsg(_("E426: tag not found: %s"), name); } g_do_tagpreview = 0; } else { @@ -561,15 +560,15 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose) } if (cur_match >= num_matches) { - /* Avoid giving this error when a file wasn't found and we're - * looking for a match in another file, which wasn't found. - * There will be an EMSG("file doesn't exist") below then. */ + // Avoid giving this error when a file wasn't found and we're + // looking for a match in another file, which wasn't found. + // There will be an emsg("file doesn't exist") below then. if ((type == DT_NEXT || type == DT_FIRST) && nofile_fname == NULL) { if (num_matches == 1) { - EMSG(_("E427: There is only one matching tag")); + emsg(_("E427: There is only one matching tag")); } else { - EMSG(_("E428: Cannot go beyond last matching tag")); + emsg(_("E428: Cannot go beyond last matching tag")); } skip_msg = true; } @@ -597,7 +596,7 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose) /* * Only when going to try the next match, report that the previous - * file didn't exist. Otherwise an EMSG() is given below. + * file didn't exist. Otherwise an emsg() is given below. */ if (nofile_fname != NULL && error_cur_match != cur_match) { smsg(_("File \"%s\" does not exist"), nofile_fname); @@ -622,7 +621,7 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose) if (ic) { msg_attr((const char *)IObuff, HL_ATTR(HLF_W)); } else { - msg(IObuff); + msg((char *)IObuff); } msg_scroll = true; // Don't overwrite this message. } else { @@ -664,10 +663,10 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose) } continue; } - EMSG2(_("E429: File \"%s\" does not exist"), nofile_fname); + semsg(_("E429: File \"%s\" does not exist"), nofile_fname); } else { - /* We may have jumped to another window, check that - * tagstackidx is still valid. */ + // We may have jumped to another window, check that + // tagstackidx is still valid. if (use_tagstack && tagstackidx > curwin->w_tagstacklen) { tagstackidx = curwin->w_tagstackidx; } @@ -1039,7 +1038,7 @@ void do_tags(exarg_T *eap) int tagstacklen = curwin->w_tagstacklen; // Highlight title - MSG_PUTS_TITLE(_("\n # TO tag FROM line in file/text")); + msg_puts_title(_("\n # TO tag FROM line in file/text")); for (i = 0; i < tagstacklen; ++i) { if (tagstack[i].tagname != NULL) { name = fm_getname(&(tagstack[i].fmark), 30); @@ -1062,12 +1061,11 @@ void do_tags(exarg_T *eap) ui_flush(); // show one line at a time } if (tagstackidx == tagstacklen) { // idx at top of stack - MSG_PUTS("\n>"); + msg_puts("\n>"); } } - /* * Compare two strings, for length "len", ignoring case the ASCII way. * return 0 for match, < 0 for smaller, > 0 for bigger @@ -1198,7 +1196,7 @@ static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int fl } if (rettv.v_type != VAR_LIST || !rettv.vval.v_list) { tv_clear(&rettv); - EMSG(_(tfu_inv_ret_msg)); + emsg(_(tfu_inv_ret_msg)); return FAIL; } taglist = rettv.vval.v_list; @@ -1212,7 +1210,7 @@ static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int fl int name_only = flags & TAG_NAMES; if (TV_LIST_ITEM_TV(li)->v_type != VAR_DICT) { - EMSG(_(tfu_inv_ret_msg)); + emsg(_(tfu_inv_ret_msg)); break; } @@ -1258,7 +1256,7 @@ static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int fl } if (!res_name || !res_fname || !res_cmd) { - EMSG(_(tfu_inv_ret_msg)); + emsg(_(tfu_inv_ret_msg)); break; } @@ -1405,7 +1403,7 @@ int find_tags(char_u *pat, int *num_matches, char_u ***matchesp, int flags, int TS_LINEAR, // linear searching forward, till EOF TS_BINARY, // binary searching TS_SKIP_BACK, // skipping backwards - TS_STEP_FORWARD // stepping forwards + TS_STEP_FORWARD, // stepping forwards } state; // Current search state int cmplen; @@ -1584,15 +1582,15 @@ int find_tags(char_u *pat, int *num_matches, char_u ***matchesp, int flags, int } } - /* When searching for a specific language skip tags files - * for other languages. */ + // When searching for a specific language skip tags files + // for other languages. if (help_lang_find != NULL && STRICMP(help_lang, help_lang_find) != 0) { continue; } - /* For CTRL-] in a help file prefer a match with the same - * language. */ + // For CTRL-] in a help file prefer a match with the same + // language. if ((flags & TAG_KEEP_LANG) && help_lang_find == NULL && curbuf->b_fname != NULL @@ -1758,7 +1756,6 @@ line_read_in: } - /* * When still at the start of the file, check for Emacs tags file * format, and for "not sorted" flag. @@ -2196,9 +2193,9 @@ parse_line: } // forever if (line_error) { - EMSG2(_("E431: Format error in tags file \"%s\""), tag_fname); + semsg(_("E431: Format error in tags file \"%s\""), tag_fname); if (!use_cscope) { - EMSGN(_("Before byte %" PRId64), vim_ftell(fp)); + semsg(_("Before byte %" PRId64), (int64_t)vim_ftell(fp)); } stop_searching = true; line_error = false; @@ -2213,7 +2210,7 @@ parse_line: tag_file_sorted = NUL; if (sort_error) { - EMSG2(_("E432: Tags file not sorted: %s"), tag_fname); + semsg(_("E432: Tags file not sorted: %s"), tag_fname); sort_error = false; } @@ -2234,8 +2231,8 @@ parse_line: tagname_free(&tn); } - /* stop searching when already did a linear search, or when TAG_NOIC - * used, and 'ignorecase' not set or already did case-ignore search */ + // stop searching when already did a linear search, or when TAG_NOIC + // used, and 'ignorecase' not set or already did case-ignore search if (stop_searching || linear || (!p_ic && noic) || orgpat.regmatch.rm_ic) { break; } @@ -2247,7 +2244,7 @@ parse_line: if (!stop_searching) { if (!did_open && verbose) { // never opened any tags file - EMSG(_("E433: No tags file")); + emsg(_("E433: No tags file")); } retval = OK; // It's OK even when no tag found } @@ -2367,8 +2364,8 @@ int get_tagfname(tagname_T *tnp, int first, char_u *buf) } if (tnp->tn_hf_idx >= tag_fnames.ga_len) { - /* Not found in 'runtimepath', use 'helpfile', if it exists and - * wasn't used yet, replacing "help.txt" with "tags". */ + // Not found in 'runtimepath', use 'helpfile', if it exists and + // wasn't used yet, replacing "help.txt" with "tags". if (tnp->tn_hf_idx > tag_fnames.ga_len || *p_hf == NUL) { return FAIL; } @@ -2393,8 +2390,8 @@ int get_tagfname(tagname_T *tnp, int first, char_u *buf) } if (first) { - /* Init. We make a copy of 'tags', because autocommands may change - * the value without notifying us. */ + // Init. We make a copy of 'tags', because autocommands may change + // the value without notifying us. tnp->tn_tags = vim_strsave((*curbuf->b_p_tags != NUL) ? curbuf->b_p_tags : p_tags); tnp->tn_np = tnp->tn_tags; @@ -2431,8 +2428,8 @@ int get_tagfname(tagname_T *tnp, int first, char_u *buf) (void)copy_option_part(&tnp->tn_np, buf, MAXPATHL - 1, " ,"); r_ptr = vim_findfile_stopdir(buf); - /* move the filename one char forward and truncate the - * filepath with a NUL */ + // move the filename one char forward and truncate the + // filepath with a NUL filename = path_tail(buf); STRMOVE(filename + 1, filename); *filename++ = NUL; @@ -2790,8 +2787,8 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help) } if (keep_help) { - /* A :ta from a help file will keep the b_help flag set. For ":ptag" - * we need to use the flag from the window where we came from. */ + // A :ta from a help file will keep the b_help flag set. For ":ptag" + // we need to use the flag from the window where we came from. if (l_g_do_tagpreview != 0) { keep_help_flag = curwin_save->w_buffer->b_help; } else { @@ -2884,7 +2881,7 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help) *tagp.tagname_end = cc; } if (found == 0) { - EMSG(_("E434: Can't find tag pattern")); + emsg(_("E434: Can't find tag pattern")); curwin->w_cursor.lnum = save_lnum; } else { /* @@ -2892,7 +2889,7 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help) * is set and match found while ignoring case. */ if (found == 2 || !save_p_ic) { - MSG(_("E435: Couldn't find tag, just guessing!")); + msg(_("E435: Couldn't find tag, just guessing!")); if (!msg_scrolled && msg_silent == 0) { ui_flush(); os_delay(1010L, true); @@ -2905,8 +2902,8 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help) p_ic = save_p_ic; // -V519 p_scs = save_p_scs; - /* A search command may have positioned the cursor beyond the end - * of the line. May need to correct that here. */ + // A search command may have positioned the cursor beyond the end + // of the line. May need to correct that here. check_cursor(); } else { const int save_secure = secure; @@ -3128,9 +3125,8 @@ int expand_tags(int tagnames, char_u *pat, int *num_file, char_u ***file) TAG_MANY, curbuf->b_ffname); } if (ret == OK && !tagnames) { - /* Reorganize the tags for display and matching as strings of: - * "<tagname>\0<kind>\0<filename>\0" - */ + // Reorganize the tags for display and matching as strings of: + // "<tagname>\0<kind>\0<filename>\0" for (i = 0; i < *num_file; i++) { size_t len; @@ -3260,8 +3256,8 @@ int get_tags(list_T *list, char_u *pat, char_u *buf_fname) char_u *s, *n; int len; - /* Add extra field as a dict entry. Fields are - * separated by Tabs. */ + // Add extra field as a dict entry. Fields are + // separated by Tabs. n = p; while (*p != NUL && *p >= ' ' && *p < 127 && *p != ':') { ++p; @@ -3458,13 +3454,13 @@ int set_tagstack(win_T *wp, const dict_T *d, int action) // not allowed to alter the tag stack entries from inside tagfunc if (tfu_in_use) { - EMSG(_(recurmsg)); + emsg(_(recurmsg)); return FAIL; } if ((di = tv_dict_find(d, "items", -1)) != NULL) { if (di->di_tv.v_type != VAR_LIST) { - EMSG(_(e_listreq)); + emsg(_(e_listreq)); return FAIL; } l = di->di_tv.vval.v_list; diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index fb025265f2..9002ac4967 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -124,7 +124,9 @@ struct terminal { // no way to know if the memory was reused. handle_T buf_handle; // program exited - bool closed, destroy; + bool closed; + // when true, the terminal's destruction is already enqueued. + bool destroy; // some vterm properties bool forward_mouse; @@ -261,40 +263,66 @@ Terminal *terminal_open(buf_T *buf, TerminalOptions opts) void terminal_close(Terminal *term, int status) { - if (term->closed) { + if (term->destroy) { + return; + } + +#ifdef EXITFREE + if (entered_free_all_mem) { + // If called from close_buffer() inside free_all_mem(), the main loop has + // already been freed, so it is not safe to call the close callback here. + terminal_destroy(term); return; } +#endif - term->forward_mouse = false; + bool only_destroy = false; - // flush any pending changes to the buffer - if (!exiting) { - block_autocmds(); - refresh_terminal(term); - unblock_autocmds(); + if (term->closed) { + // If called from close_buffer() after the process has already exited, we + // only need to call the close callback to clean up the terminal object. + only_destroy = true; + } else { + term->forward_mouse = false; + // flush any pending changes to the buffer + if (!exiting) { + block_autocmds(); + refresh_terminal(term); + unblock_autocmds(); + } + term->closed = true; } buf_T *buf = handle_get_buffer(term->buf_handle); - term->closed = true; if (status == -1 || exiting) { - // If status is -1, this was called by close_buffer(buffer.c). Or if - // exiting, we must inform the buffer the terminal no longer exists so that - // close_buffer() doesn't call this again. + // If this was called by close_buffer() (status is -1), or if exiting, we + // must inform the buffer the terminal no longer exists so that + // close_buffer() won't call this again. + // If inside Terminal mode K_EVENT handling, setting buf_handle to 0 also + // informs terminal_enter() to call the close callback before returning. term->buf_handle = 0; if (buf) { buf->terminal = NULL; } if (!term->refcount) { + // Not inside Terminal mode K_EVENT handling. // We should not wait for the user to press a key. + term->destroy = true; term->opts.close_cb(term->opts.data); } - } else { + } else if (!only_destroy) { + // This was called by channel_process_exit_cb() not in process_teardown(). + // Do not call the close callback now. Wait for the user to press a key. char msg[sizeof("\r\n[Process exited ]") + NUMBUFLEN]; snprintf(msg, sizeof msg, "\r\n[Process exited %d]", status); terminal_receive(term, msg, strlen(msg)); } + if (only_destroy) { + return; + } + if (buf && !is_autocmd_blocked()) { dict_T *dict = get_vim_var_dict(VV_EVENT); tv_dict_add_nr(dict, S_LEN("status"), status); @@ -417,6 +445,7 @@ void terminal_enter(void) ui_busy_stop(); if (s->close) { bool wipe = s->term->buf_handle != 0; + s->term->destroy = true; s->term->opts.close_cb(s->term->opts.data); if (wipe) { do_cmdline_cmd("bwipeout!"); @@ -725,7 +754,7 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, int *te int attr_id = 0; - if (hl_attrs ||!fg_default || !bg_default) { + if (hl_attrs || !fg_default || !bg_default) { attr_id = hl_get_term_attr(&(HlAttrs) { .cterm_ae_attr = (int16_t)hl_attrs, .cterm_fg_color = vt_fg_idx, diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index ffca415282..98340d0ac6 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -309,6 +309,11 @@ func Test_getcompletion() let l = getcompletion('NoMatch', 'dir') call assert_equal([], l) + if glob('~/*') !=# '' + let l = getcompletion('~/', 'dir') + call assert_true(l[0][0] ==# '~') + endif + let l = getcompletion('exe', 'expression') call assert_true(index(l, 'executable(') >= 0) let l = getcompletion('kill', 'expression') @@ -422,6 +427,16 @@ func Test_getcompletion() let l = getcompletion('call paint', 'cmdline') call assert_equal([], l) + func T(a, c, p) + return "oneA\noneB\noneC" + endfunc + command -nargs=1 -complete=custom,T MyCmd + let l = getcompletion('MyCmd ', 'cmdline') + call assert_equal(['oneA', 'oneB', 'oneC'], l) + + delcommand MyCmd + delfunc T + " For others test if the name is recognized. let names = ['buffer', 'environment', 'file_in_path', 'mapping', 'tag', 'tag_listfiles', 'user'] if has('cmdline_hist') diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim index 32cee7ca56..61da3cbcaa 100644 --- a/src/nvim/testdir/test_diffmode.vim +++ b/src/nvim/testdir/test_diffmode.vim @@ -984,6 +984,9 @@ func Test_diff_with_scroll_and_change() call term_sendkeys(buf, "ax\<Esc>") call VerifyScreenDump(buf, 'Test_diff_scroll_change_02', {}) + call term_sendkeys(buf, "\<C-W>lay\<Esc>") + call VerifyScreenDump(buf, 'Test_diff_scroll_change_03', {}) + " clean up call StopVimInTerminal(buf) call delete('Xtest_scroll_change') diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 18587b9b2c..8c6ce63ade 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -705,6 +705,23 @@ func Test_vimgreptitle() augroup! QfBufWinEnter endfunc +func Test_bufwinenter_once() + augroup QfBufWinEnter + au! + au BufWinEnter * let g:got_afile ..= 'got ' .. expand('<afile>') + augroup END + let g:got_afile = '' + copen + call assert_equal('got quickfix', g:got_afile) + + cclose + unlet g:got_afile + augroup QfBufWinEnter + au! + augroup END + augroup! QfBufWinEnter +endfunc + func XqfTitleTests(cchar) call s:setup_commands(a:cchar) diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index ec277f7a4e..5bb6059fa7 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -151,7 +151,7 @@ static void tinput_paste_event(void **argv) Error err = ERROR_INIT; nvim_paste(keys, true, phase, &err); if (ERROR_SET(&err)) { - emsgf("paste: %s", err.msg); + semsg("paste: %s", err.msg); api_clear_error(&err); } diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index fcfe862044..bb75286369 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -1484,7 +1484,6 @@ static void unibi_goto(UI *ui, int row, int col) if (str) { \ unibi_var_t vars[26 + 26]; \ size_t orig_pos = data->bufpos; \ - \ memset(&vars, 0, sizeof(vars)); \ data->cork = true; \ retry: \ @@ -1664,6 +1663,14 @@ static void patch_terminfo_bugs(TUIData *data, const char *term, const char *col ILOG("Disabling smglr with TERM=xterm for non-xterm."); unibi_set_str(ut, unibi_set_lr_margin, NULL); } + if (unibi_get_str(ut, unibi_set_left_margin_parm)) { + ILOG("Disabling smglp with TERM=xterm for non-xterm."); + unibi_set_str(ut, unibi_set_left_margin_parm, NULL); + } + if (unibi_get_str(ut, unibi_set_right_margin_parm)) { + ILOG("Disabling smgrp with TERM=xterm for non-xterm."); + unibi_set_str(ut, unibi_set_right_margin_parm, NULL); + } } #ifdef WIN32 @@ -1688,6 +1695,14 @@ static void patch_terminfo_bugs(TUIData *data, const char *term, const char *col ILOG("Disabling smglr with TERM=screen.xterm for screen."); unibi_set_str(ut, unibi_set_lr_margin, NULL); } + if (unibi_get_str(ut, unibi_set_left_margin_parm)) { + ILOG("Disabling smglp with TERM=screen.xterm for screen."); + unibi_set_str(ut, unibi_set_left_margin_parm, NULL); + } + if (unibi_get_str(ut, unibi_set_right_margin_parm)) { + ILOG("Disabling smgrp with TERM=screen.xterm for screen."); + unibi_set_str(ut, unibi_set_right_margin_parm, NULL); + } } else if (tmux) { unibi_set_if_empty(ut, unibi_to_status_line, "\x1b_"); unibi_set_if_empty(ut, unibi_from_status_line, "\x1b\\"); diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 5261f9e2ec..7eb76abd2c 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -135,7 +135,8 @@ static int seen_b_u_curhead; static int seen_b_u_newhead; static int header_count; -static void u_check_tree(u_header_T *uhp, u_header_T *exp_uh_next, u_header_T *exp_uh_alt_prev) { +static void u_check_tree(u_header_T *uhp, u_header_T *exp_uh_next, u_header_T *exp_uh_alt_prev) +{ u_entry_T *uep; if (uhp == NULL) { @@ -143,25 +144,25 @@ static void u_check_tree(u_header_T *uhp, u_header_T *exp_uh_next, u_header_T *e } ++header_count; if (uhp == curbuf->b_u_curhead && ++seen_b_u_curhead > 1) { - EMSG("b_u_curhead found twice (looping?)"); + emsg("b_u_curhead found twice (looping?)"); return; } if (uhp == curbuf->b_u_newhead && ++seen_b_u_newhead > 1) { - EMSG("b_u_newhead found twice (looping?)"); + emsg("b_u_newhead found twice (looping?)"); return; } if (uhp->uh_magic != UH_MAGIC) { - EMSG("uh_magic wrong (may be using freed memory)"); + emsg("uh_magic wrong (may be using freed memory)"); } else { // Check pointers back are correct. if (uhp->uh_next.ptr != exp_uh_next) { - EMSG("uh_next wrong"); + emsg("uh_next wrong"); smsg("expected: 0x%x, actual: 0x%x", exp_uh_next, uhp->uh_next.ptr); } if (uhp->uh_alt_prev.ptr != exp_uh_alt_prev) { - EMSG("uh_alt_prev wrong"); + emsg("uh_alt_prev wrong"); smsg("expected: 0x%x, actual: 0x%x", exp_uh_alt_prev, uhp->uh_alt_prev.ptr); } @@ -169,7 +170,7 @@ static void u_check_tree(u_header_T *uhp, u_header_T *exp_uh_next, u_header_T *e // Check the undo tree at this header. for (uep = uhp->uh_entry; uep != NULL; uep = uep->ue_next) { if (uep->ue_magic != UE_MAGIC) { - EMSG("ue_magic wrong (may be using freed memory)"); + emsg("ue_magic wrong (may be using freed memory)"); break; } } @@ -182,7 +183,8 @@ static void u_check_tree(u_header_T *uhp, u_header_T *exp_uh_next, u_header_T *e } } -static void u_check(int newhead_may_be_NULL) { +static void u_check(int newhead_may_be_NULL) +{ seen_b_u_newhead = 0; seen_b_u_curhead = 0; header_count = 0; @@ -191,13 +193,13 @@ static void u_check(int newhead_may_be_NULL) { if (seen_b_u_newhead == 0 && curbuf->b_u_oldhead != NULL && !(newhead_may_be_NULL && curbuf->b_u_newhead == NULL)) { - EMSGN("b_u_newhead invalid: 0x%x", curbuf->b_u_newhead); + semsg("b_u_newhead invalid: 0x%x", curbuf->b_u_newhead); } if (curbuf->b_u_curhead != NULL && seen_b_u_curhead == 0) { - EMSGN("b_u_curhead invalid: 0x%x", curbuf->b_u_curhead); + semsg("b_u_curhead invalid: 0x%x", curbuf->b_u_curhead); } if (header_count != curbuf->b_u_numhead) { - EMSG("b_u_numhead invalid"); + emsg("b_u_numhead invalid"); smsg("expected: %" PRId64 ", actual: %" PRId64, (int64_t)header_count, (int64_t)curbuf->b_u_numhead); } @@ -281,20 +283,20 @@ bool undo_allowed(buf_T *buf) { // Don't allow changes when 'modifiable' is off. if (!MODIFIABLE(buf)) { - EMSG(_(e_modifiable)); + emsg(_(e_modifiable)); return false; } // In the sandbox it's not allowed to change the text. if (sandbox != 0) { - EMSG(_(e_sandbox)); + emsg(_(e_sandbox)); return false; } // Don't allow changes in the buffer while editing the cmdline. The // caller of getcmdline() may get confused. if (textlock != 0) { - EMSG(_(e_secure)); + emsg(_(e_secure)); return false; } @@ -355,7 +357,7 @@ int u_savecommon(buf_T *buf, linenr_T top, linenr_T bot, linenr_T newbot, int re if (bot > buf->b_ml.ml_line_count + 1) { // This happens when the FileChangedRO autocommand changes the // file in a way it becomes shorter. - EMSG(_("E881: Line count changed unexpectedly")); + emsg(_("E881: Line count changed unexpectedly")); return FAIL; } } @@ -503,8 +505,8 @@ int u_savecommon(buf_T *buf, linenr_T top, linenr_T bot, linenr_T newbot, int re break; } - /* If lines have been inserted/deleted we give up. - * Also when the line was included in a multi-line save. */ + // If lines have been inserted/deleted we give up. + // Also when the line was included in a multi-line save. if ((buf->b_u_newhead->uh_getbot_entry != uep ? (uep->ue_top + uep->ue_size + 1 != (uep->ue_bot == 0 @@ -520,18 +522,18 @@ int u_savecommon(buf_T *buf, linenr_T top, linenr_T bot, linenr_T newbot, int re // If it's the same line we can skip saving it again. if (uep->ue_size == 1 && uep->ue_top == top) { if (i > 0) { - /* It's not the last entry: get ue_bot for the last - * entry now. Following deleted/inserted lines go to - * the re-used entry. */ + // It's not the last entry: get ue_bot for the last + // entry now. Following deleted/inserted lines go to + // the re-used entry. u_getbot(buf); buf->b_u_synced = false; - /* Move the found entry to become the last entry. The - * order of undo/redo doesn't matter for the entries - * we move it over, since they don't change the line - * count and don't include this line. It does matter - * for the found entry if the line count is changed by - * the executed command. */ + // Move the found entry to become the last entry. The + // order of undo/redo doesn't matter for the entries + // we move it over, since they don't change the line + // count and don't include this line. It does matter + // for the found entry if the line count is changed by + // the executed command. prev_uep->ue_next = uep->ue_next; uep->ue_next = buf->b_u_newhead->uh_entry; buf->b_u_newhead->uh_entry = uep; @@ -719,7 +721,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading) int ret; char *failed_dir; if ((ret = os_mkdir_recurse(dir_name, 0755, &failed_dir)) != 0) { - EMSG3(_("E5003: Unable to create directory \"%s\" for undo file: %s"), + semsg(_("E5003: Unable to create directory \"%s\" for undo file: %s"), failed_dir, os_strerror(ret)); xfree(failed_dir); } else { @@ -758,7 +760,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading) static void corruption_error(const char *const mesg, const char *const file_name) FUNC_ATTR_NONNULL_ALL { - EMSG3(_("E825: Corrupted undo file (%s): %s"), mesg, file_name); + semsg(_("E825: Corrupted undo file (%s): %s"), mesg, file_name); } static void u_free_uhp(u_header_T *uhp) @@ -1213,8 +1215,8 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, // Strip any sticky and executable bits. perm = perm & 0666; - /* If the undo file already exists, verify that it actually is an undo - * file, and delete it. */ + // If the undo file already exists, verify that it actually is an undo + // file, and delete it. if (os_path_exists((char_u *)file_name)) { if (name == NULL || !forceit) { // Check we can read it and it's an undo file. @@ -1254,8 +1256,8 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, os_remove(file_name); } - /* If there is no undo information at all, quit here after deleting any - * existing undo file. */ + // If there is no undo information at all, quit here after deleting any + // existing undo file. if (buf->b_u_numhead == 0 && buf->b_u_line_ptr == NULL) { if (p_verbose > 0) { verb_msg(_("Skipping undo file write, nothing to undo")); @@ -1265,7 +1267,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, fd = os_open(file_name, O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm); if (fd < 0) { - EMSG2(_(e_not_open), file_name); + semsg(_(e_not_open), file_name); goto theend; } (void)os_setperm(file_name, perm); @@ -1299,7 +1301,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, fp = fdopen(fd, "w"); if (fp == NULL) { - EMSG2(_(e_not_open), file_name); + semsg(_(e_not_open), file_name); close(fd); os_remove(file_name); goto theend; @@ -1355,15 +1357,15 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, } #ifdef U_DEBUG if (headers_written != buf->b_u_numhead) { - EMSGN("Written %" PRId64 " headers, ...", headers_written); - EMSGN("... but numhead is %" PRId64, buf->b_u_numhead); + semsg("Written %" PRId64 " headers, ...", (int64_t)headers_written); + semsg("... but numhead is %" PRId64, (int64_t)buf->b_u_numhead); } #endif write_error: fclose(fp); if (!write_ok) { - EMSG2(_("E829: write error in undo file: %s"), file_name); + semsg(_("E829: write error in undo file: %s"), file_name); } #ifdef HAVE_ACL @@ -1432,7 +1434,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT FILE *fp = os_fopen(file_name, "r"); if (fp == NULL) { if (name != NULL || p_verbose > 0) { - EMSG2(_("E822: Cannot open undo file for reading: %s"), file_name); + semsg(_("E822: Cannot open undo file for reading: %s"), file_name); } goto error; } @@ -1445,12 +1447,12 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT char_u magic_buf[UF_START_MAGIC_LEN]; if (fread(magic_buf, UF_START_MAGIC_LEN, 1, fp) != 1 || memcmp(magic_buf, UF_START_MAGIC, UF_START_MAGIC_LEN) != 0) { - EMSG2(_("E823: Not an undo file: %s"), file_name); + semsg(_("E823: Not an undo file: %s"), file_name); goto error; } int version = get2c(fp); if (version != UF_VERSION) { - EMSG2(_("E824: Incompatible undo file: %s"), file_name); + semsg(_("E824: Incompatible undo file: %s"), file_name); goto error; } @@ -1653,7 +1655,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT #ifdef U_DEBUG for (int i = 0; i < num_head; i++) { if (uhp_table_used[i] == 0) { - EMSGN("uhp_table entry %" PRId64 " not used, leaking memory", i); + semsg("uhp_table entry %" PRId64 " not used, leaking memory", (int64_t)i); } } xfree(uhp_table_used); @@ -1883,10 +1885,10 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event) u_oldcount = -1; } while (count--) { - /* Do the change warning now, so that it triggers FileChangedRO when - * needed. This may cause the file to be reloaded, that must happen - * before we do anything, because it may change curbuf->b_u_curhead - * and more. */ + // Do the change warning now, so that it triggers FileChangedRO when + // needed. This may cause the file to be reloaded, that must happen + // before we do anything, because it may change curbuf->b_u_curhead + // and more. change_warning(curbuf, 0); if (undo_undoes) { @@ -1902,7 +1904,7 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event) curbuf->b_u_curhead = curbuf->b_u_oldhead; beep_flush(); if (count == startcount - 1) { - MSG(_("Already at oldest change")); + msg(_("Already at oldest change")); return; } break; @@ -1913,7 +1915,7 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event) if (curbuf->b_u_curhead == NULL || get_undolevel(curbuf) <= 0) { beep_flush(); // nothing to redo if (count == startcount - 1) { - MSG(_("Already at newest change")); + msg(_("Already at newest change")); return; } break; @@ -1987,16 +1989,16 @@ void undo_time(long step, bool sec, bool file, bool absolute) uhp = curbuf->b_u_newhead; } if (uhp != NULL && uhp->uh_save_nr != 0) { - /* "uh_save_nr" was set in the last block, that means - * there were no changes since the last write */ + // "uh_save_nr" was set in the last block, that means + // there were no changes since the last write target = curbuf->b_u_save_nr_cur + step; } else { // count the changes since the last write as one step target = curbuf->b_u_save_nr_cur + step + 1; } if (target <= 0) { - /* Go to before first write: before the oldest change. Use - * the sequence number for that. */ + // Go to before first write: before the oldest change. Use + // the sequence number for that. dofile = false; } } else { @@ -2047,11 +2049,11 @@ void undo_time(long step, bool sec, bool file, bool absolute) * When using the closest time we use the sequence number in the second * round, because there may be several entries with the same time. */ - for (round = 1; round <= 2; ++round) { - /* Find the path from the current state to where we want to go. The - * desired state can be anywhere in the undo tree, need to go all over - * it. We put "nomark" in uh_walk where we have been without success, - * "mark" where it could possibly be. */ + for (round = 1; round <= 2; round++) { + // Find the path from the current state to where we want to go. The + // desired state can be anywhere in the undo tree, need to go all over + // it. We put "nomark" in uh_walk where we have been without success, + // "mark" where it could possibly be. mark = ++lastmark; nomark = ++lastmark; @@ -2138,15 +2140,15 @@ void undo_time(long step, bool sec, bool file, bool absolute) } if (absolute) { - EMSGN(_("E830: Undo number %" PRId64 " not found"), step); + semsg(_("E830: Undo number %" PRId64 " not found"), (int64_t)step); return; } if (closest == closest_start) { if (step < 0) { - MSG(_("Already at oldest change")); + msg(_("Already at oldest change")); } else { - MSG(_("Already at newest change")); + msg(_("Already at newest change")); } return; } @@ -2329,7 +2331,7 @@ static void u_undoredo(int undo, bool do_buf_event) if (top > curbuf->b_ml.ml_line_count || top >= bot || bot > curbuf->b_ml.ml_line_count + 1) { unblock_autocmds(); - IEMSG(_("E438: u_undo: line numbers wrong")); + iemsg(_("E438: u_undo: line numbers wrong")); changed(); // don't want UNCHANGED now return; } @@ -2519,10 +2521,10 @@ static void u_undoredo(int undo, bool do_buf_event) beginline(BL_SOL | BL_FIX); } } else { - /* We get here with the current cursor line being past the end (eg - * after adding lines at the end of the file, and then undoing it). - * check_cursor() will move the cursor to the last line. Move it to - * the first column here. */ + // We get here with the current cursor line being past the end (eg + // after adding lines at the end of the file, and then undoing it). + // check_cursor() will move the cursor to the last line. Move it to + // the first column here. curwin->w_cursor.col = 0; curwin->w_cursor.coladd = 0; } @@ -2533,8 +2535,8 @@ static void u_undoredo(int undo, bool do_buf_event) // Remember where we are for "g-" and ":earlier 10s". curbuf->b_u_seq_cur = curhead->uh_seq; 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. */ + // 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 = curhead->uh_next.ptr ? curhead->uh_next.ptr->uh_seq : 0; } @@ -2728,7 +2730,7 @@ void ex_undolist(exarg_T *eap) } if (GA_EMPTY(&ga)) { - MSG(_("Nothing to undo")); + msg(_("Nothing to undo")); } else { sort_strings((char_u **)ga.ga_data, ga.ga_len); @@ -2757,7 +2759,7 @@ void ex_undojoin(exarg_T *eap) return; // nothing changed before } if (curbuf->b_u_curhead != NULL) { - EMSG(_("E790: undojoin is not allowed after undo")); + emsg(_("E790: undojoin is not allowed after undo")); return; } if (!curbuf->b_u_synced) { @@ -2854,7 +2856,7 @@ static void u_unch_branch(u_header_T *uhp) static u_entry_T *u_get_headentry(buf_T *buf) { if (buf->b_u_newhead == NULL || buf->b_u_newhead->uh_entry == NULL) { - IEMSG(_("E439: undo list corrupt")); + iemsg(_("E439: undo list corrupt")); return NULL; } return buf->b_u_newhead->uh_entry; @@ -2884,7 +2886,7 @@ static void u_getbot(buf_T *buf) extra = buf->b_ml.ml_line_count - uep->ue_lcount; uep->ue_bot = uep->ue_top + uep->ue_size + 1 + extra; if (uep->ue_bot < 1 || uep->ue_bot > buf->b_ml.ml_line_count) { - IEMSG(_("E440: undo line missing")); + iemsg(_("E440: undo line missing")); uep->ue_bot = uep->ue_top + 1; // assume all lines deleted, will // get all the old lines back // without deleting the current diff --git a/src/nvim/version.c b/src/nvim/version.c index 9e2358c9a3..1fcbae8be3 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -29,8 +29,8 @@ // for ":version", ":intro", and "nvim --version" #ifndef NVIM_VERSION_MEDIUM -# define NVIM_VERSION_MEDIUM "v" STR(NVIM_VERSION_MAJOR)\ - "." STR(NVIM_VERSION_MINOR) "." STR(NVIM_VERSION_PATCH)\ +# 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 @@ -1992,7 +1992,8 @@ bool has_vim_patch(int n) return false; } -Dictionary version_dict(void) { +Dictionary version_dict(void) +{ Dictionary d = ARRAY_DICT_INIT; PUT(d, "major", INTEGER_OBJ(NVIM_VERSION_MAJOR)); PUT(d, "minor", INTEGER_OBJ(NVIM_VERSION_MINOR)); @@ -2137,32 +2138,32 @@ void list_lua_version(void) Object ret = nlua_exec(cstr_as_string(code), (Array)ARRAY_DICT_INIT, &err); assert(!ERROR_SET(&err)); assert(ret.type == kObjectTypeString); - MSG(ret.data.string.data); + msg(ret.data.string.data); api_free_object(ret); } void list_version(void) { - MSG(longVersion); - MSG(version_buildtype); + msg(longVersion); + msg(version_buildtype); list_lua_version(); #ifndef NDEBUG - MSG(version_cflags); + msg(version_cflags); #endif #ifdef HAVE_PATHDEF if ((*compiled_user != NUL) || (*compiled_sys != NUL)) { - MSG_PUTS(_("\nCompiled ")); + msg_puts(_("\nCompiled ")); if (*compiled_user != NUL) { - MSG_PUTS(_("by ")); - MSG_PUTS(compiled_user); + msg_puts(_("by ")); + msg_puts((const char *)compiled_user); } if (*compiled_sys != NUL) { - MSG_PUTS("@"); - MSG_PUTS(compiled_sys); + msg_puts("@"); + msg_puts((const char *)compiled_sys); } } #endif // ifdef HAVE_PATHDEF diff --git a/src/nvim/vim.h b/src/nvim/vim.h index 7d49ca6ff1..726670f082 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -24,7 +24,7 @@ #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) -enum { NUMBUFLEN = 65 }; +enum { NUMBUFLEN = 65, }; #define MAX_TYPENR 65535 @@ -164,8 +164,6 @@ enum { }; - - // Minimal size for block 0 of a swap file. // NOTE: This depends on size of struct block0! It's not done with a sizeof(), // because struct block0 is defined in memline.c (Sorry). @@ -175,7 +173,6 @@ enum { #define MAX_SWAP_PAGE_SIZE 50000 - // Boolean constants #ifndef TRUE @@ -199,7 +196,7 @@ enum { #define DIALOG_MSG_SIZE 1000 // buffer size for dialog_msg() -enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext() +enum { FOLD_TEXT_LEN = 51, }; //!< buffer size for get_foldtext() // Maximum length of key sequence to be mapped. @@ -257,9 +254,9 @@ enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext() #include "nvim/message.h" -// Prefer using emsgf(), because perror() may send the output to the wrong +// Prefer using semsg(), because perror() may send the output to the wrong // destination and mess up the screen. -#define PERROR(msg) (void)emsgf("%s: %s", msg, strerror(errno)) +#define PERROR(msg) (void)semsg("%s: %s", msg, strerror(errno)) #define SHOWCMD_COLS 10 // columns needed by shown command diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c index 39687a8e8d..4f028fa87f 100644 --- a/src/nvim/viml/parser/expressions.c +++ b/src/nvim/viml/parser/expressions.c @@ -1525,7 +1525,6 @@ static inline void east_set_error(const ParserState *const pstate, ExprASTError assert(want_node == kENodeOperator); \ /* Operator: may only be curly braces name, but only under certain */ \ /* conditions. */ \ -\ /* First condition is that there is no space before a part of complex */ \ /* identifier. */ \ if (prev_token.type == kExprLexSpacing) { \ @@ -1534,7 +1533,6 @@ static inline void east_set_error(const ParserState *const pstate, ExprASTError switch ((*top_node_p)->type) { \ /* Second is that previous node is one of the identifiers: */ \ /* complex, plain, curly braces. */ \ -\ /* TODO(ZyX-I): Extend syntax to allow ${expr}. This is needed to */ \ /* handle environment variables like those bash uses for */ \ /* `export -f`: their names consist not only of alphanumeric */ \ diff --git a/src/nvim/viml/parser/expressions.h b/src/nvim/viml/parser/expressions.h index 325df643e7..fe9327b27d 100644 --- a/src/nvim/viml/parser/expressions.h +++ b/src/nvim/viml/parser/expressions.h @@ -361,7 +361,7 @@ typedef struct { typedef struct { /// When AST is not correct this message will be printed. /// - /// Uses `emsgf(msg, arg_len, arg);`, `msg` is assumed to contain only `%.*s`. + /// Uses `semsg(msg, arg_len, arg);`, `msg` is assumed to contain only `%.*s`. ExprASTError err; /// Root node of the AST. ExprASTNode *root; diff --git a/src/nvim/window.c b/src/nvim/window.c index dfe1ffdbd4..ff5b39eb84 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -59,8 +59,6 @@ #endif - - #define NOWIN (win_T *)-1 // non-existing window #define ROWS_AVAIL (Rows - p_ch - tabline_height()) @@ -94,7 +92,7 @@ void do_window(int nchar, long Prenum, int xchar) #define CHECK_CMDWIN \ do { \ if (cmdwin_type != 0) { \ - EMSG(_(e_cmdwin)); \ + emsg(_(e_cmdwin)); \ return; \ } \ } while (0) @@ -135,9 +133,9 @@ void do_window(int nchar, long Prenum, int xchar) if (buflist_findnr(Prenum == 0 ? curwin->w_alt_fnum : Prenum) == NULL) { if (Prenum == 0) { - EMSG(_(e_noalt)); + emsg(_(e_noalt)); } else { - EMSGN(_("E92: Buffer %" PRId64 " not found"), Prenum); + semsg(_("E92: Buffer %" PRId64 " not found"), (int64_t)Prenum); } break; } @@ -201,7 +199,7 @@ newwindow: } } if (wp == NULL) { - EMSG(_("E441: There is no preview window")); + emsg(_("E441: There is no preview window")); } else { win_goto(wp); } @@ -294,7 +292,7 @@ newwindow: // move window to new tab page case 'T': if (one_window()) { - MSG(_(m_onlyone)); + msg(_(m_onlyone)); } else { tabpage_T *oldtab = curtab; tabpage_T *newtab; @@ -464,9 +462,8 @@ wingotofile: } break; - /* Go to the first occurrence of the identifier under cursor along path in a - * new window -- webb - */ + // Go to the first occurrence of the identifier under cursor along path in a + // new window -- webb case 'i': // Go to any match case Ctrl_I: type = FIND_ANY; @@ -553,7 +550,7 @@ wingotofile: config.external = true; Error err = ERROR_INIT; if (!win_new_float(curwin, config, &err)) { - EMSG(err.msg); + emsg(err.msg); api_clear_error(&err); beep_flush(); } @@ -726,8 +723,11 @@ void win_config_float(win_T *wp, FloatConfig fconfig) bool has_border = wp->w_floating && wp->w_float_config.border; for (int i = 0; i < 4; i++) { - wp->w_border_adj[i] = - has_border && wp->w_float_config.border_chars[2 * i+1][0]; + int new_adj = has_border && wp->w_float_config.border_chars[2 * i + 1][0]; + if (new_adj != wp->w_border_adj[i]) { + change_border = true; + wp->w_border_adj[i] = new_adj; + } } if (!ui_has(kUIMultigrid)) { @@ -919,7 +919,7 @@ int win_split(int size, int flags) // Add flags from ":vertical", ":topleft" and ":botright". flags |= cmdmod.split; if ((flags & WSP_TOP) && (flags & WSP_BOT)) { - EMSG(_("E442: Can't split topleft and botright at the same time")); + emsg(_("E442: Can't split topleft and botright at the same time")); return FAIL; } @@ -972,7 +972,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) // add a status line when p_ls == 1 and splitting the first window if (one_nonfloat() && p_ls == 1 && oldwin->w_status_height == 0) { if (oldwin->w_height <= p_wmh && new_in_layout) { - EMSG(_(e_noroom)); + emsg(_(e_noroom)); return FAIL; } need_status = STATUS_HEIGHT; @@ -1021,7 +1021,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) needed += minwidth; } if (available < needed && new_in_layout) { - EMSG(_(e_noroom)); + emsg(_(e_noroom)); return FAIL; } if (new_size == 0) { @@ -1046,8 +1046,8 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) win_setwidth_win(oldwin->w_width + new_size + 1, oldwin); } - /* Only make all windows the same width if one of them (except oldwin) - * is wider than one of the split windows. */ + // Only make all windows the same width if one of them (except oldwin) + // is wider than one of the split windows. if (!do_equal && p_ea && size == 0 && *p_ead != 'v' && oldwin->w_frame->fr_parent != NULL) { frp = oldwin->w_frame->fr_parent->fr_child; @@ -1101,7 +1101,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) needed += minheight; } if (available < needed && new_in_layout) { - EMSG(_(e_noroom)); + emsg(_(e_noroom)); return FAIL; } oldwin_height = oldwin->w_height; @@ -1125,9 +1125,9 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) do_equal = true; } - /* We don't like to take lines for the new window from a - * 'winfixheight' window. Take them from a window above or below - * instead, if possible. */ + // We don't like to take lines for the new window from a + // 'winfixheight' window. Take them from a window above or below + // instead, if possible. if (oldwin->w_p_wfh) { // Set w_fraction now so that the cursor keeps the same relative // vertical position using the old height. @@ -1142,8 +1142,8 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) } } - /* Only make all windows the same height if one of them (except oldwin) - * is higher than one of the split windows. */ + // Only make all windows the same height if one of them (except oldwin) + // is higher than one of the split windows. if (!do_equal && p_ea && size == 0 && *p_ead != 'h' && oldwin->w_frame->fr_parent != NULL) { @@ -1657,7 +1657,7 @@ static void win_exchange(long Prenum) int temp; if (curwin->w_floating) { - EMSG(e_floatexchange); + emsg(e_floatexchange); return; } @@ -1744,7 +1744,7 @@ static void win_rotate(bool upwards, int count) int n; if (curwin->w_floating) { - EMSG(e_floatexchange); + emsg(e_floatexchange); return; } @@ -1757,7 +1757,7 @@ static void win_rotate(bool upwards, int count) // Check if all frames in this row/col have one window. FOR_ALL_FRAMES(frp, curwin->w_frame->fr_parent->fr_child) { if (frp->fr_win == NULL) { - EMSG(_("E443: Cannot rotate when another window is split")); + emsg(_("E443: Cannot rotate when another window is split")); return; } } @@ -1774,7 +1774,6 @@ static void win_rotate(bool upwards, int count) // find last frame and append removed window/frame after it for (; frp->fr_next != NULL; frp = frp->fr_next) { - ; } win_append(frp->fr_win, wp1); frame_append(frp, wp1->w_frame); @@ -1784,7 +1783,6 @@ static void win_rotate(bool upwards, int count) // find last window/frame in the list and remove it for (frp = curwin->w_frame; frp->fr_next != NULL; frp = frp->fr_next) { - ; } wp1 = frp->fr_win; wp2 = wp1->w_prev; // will become last window @@ -1874,15 +1872,14 @@ void win_move_after(win_T *win1, win_T *win2) // check if there is something to do if (win2->w_next != win1) { - /* may need move the status line/vertical separator of the last window - * */ + // may need move the status line/vertical separator of the last window if (win1 == lastwin) { height = win1->w_prev->w_status_height; win1->w_prev->w_status_height = win1->w_status_height; win1->w_status_height = height; if (win1->w_prev->w_vsep_width == 1) { - /* Remove the vertical separator from the last-but-one window, - * add it to the last window. Adjust the frame widths. */ + // Remove the vertical separator from the last-but-one window, + // add it to the last window. Adjust the frame widths. win1->w_prev->w_vsep_width = 0; win1->w_prev->w_frame->fr_width -= 1; win1->w_vsep_width = 1; @@ -1974,8 +1971,8 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int topfr->fr_height = height; if (dir != 'v') { // equalize frame widths - /* Compute the maximum number of windows horizontally in this - * frame. */ + // Compute the maximum number of windows horizontally in this + // frame. n = frame_minwidth(topfr, NOWIN); // add one for the rightmost window, it doesn't have a separator if (col + width == Columns) { @@ -2360,8 +2357,8 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev char_u prev_idx[NUMBUFLEN]; sprintf((char *)prev_idx, "%i", tabpage_index(prev_curtab)); - /* Safety check: Autocommands may have closed the window when jumping - * to the other tab page. */ + // Safety check: Autocommands may have closed the window when jumping + // to the other tab page. if (valid_tabpage(prev_curtab) && prev_curtab->tp_firstwin == win) { int h = tabline_height(); @@ -2398,7 +2395,7 @@ int win_close(win_T *win, bool free_buf) const bool had_diffmode = win->w_p_diff; if (last_window() && !win->w_floating) { - EMSG(_("E444: Cannot close last window")); + emsg(_("E444: Cannot close last window")); return FAIL; } @@ -2407,29 +2404,29 @@ int win_close(win_T *win, bool free_buf) return FAIL; // window is already being closed } if (win == aucmd_win) { - EMSG(_(e_autocmd_close)); + emsg(_(e_autocmd_close)); return FAIL; } if ((firstwin == aucmd_win || lastwin == aucmd_win) && one_window()) { - EMSG(_("E814: Cannot close window, only autocmd window would remain")); + emsg(_("E814: Cannot close window, only autocmd window would remain")); return FAIL; } if ((firstwin == win && lastwin_nofloating() == win) && lastwin->w_floating) { // TODO(bfredl): we might close the float also instead - EMSG(e_floatonly); + emsg(e_floatonly); return FAIL; } - /* When closing the last window in a tab page first go to another tab page - * and then close the window and the tab page to avoid that curwin and - * curtab are invalid while we are freeing memory. */ + // When closing the last window in a tab page first go to another tab page + // and then close the window and the tab page to avoid that curwin and + // curtab are invalid while we are freeing memory. if (close_last_window_tabpage(win, free_buf, prev_curtab)) { return FAIL; } - /* When closing the help window, try restoring a snapshot after closing - * the window. Otherwise clear the snapshot, it's now invalid. */ + // When closing the help window, try restoring a snapshot after closing + // the window. Otherwise clear the snapshot, it's now invalid. if (bt_help(win->w_buffer)) { help_window = true; } else { @@ -2575,9 +2572,9 @@ int win_close(win_T *win, bool free_buf) } } - /* Make sure curwin isn't invalid. It can cause severe trouble when - * printing an error message. For win_equal() curbuf needs to be valid - * too. */ + // Make sure curwin isn't invalid. It can cause severe trouble when + // printing an error message. For win_equal() curbuf needs to be valid + // too. if (win == curwin) { curwin = wp; if (wp->w_p_pvw || bt_quickfix(wp->w_buffer)) { @@ -2709,7 +2706,6 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp) // Careful: Autocommands may have closed the tab page or made it the // current tab page. for (ptp = first_tabpage; ptp != NULL && ptp != tp; ptp = ptp->tp_next) { - ; } if (ptp == NULL || tp == curtab) { return; @@ -2895,9 +2891,9 @@ win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp) frp2 == frp_close->fr_next, false); *dirp = 'v'; } else { - /* When 'winfixwidth' is set, try to find another frame in the column - * (as close to the closed frame as possible) to distribute the width - * to. */ + // When 'winfixwidth' is set, try to find another frame in the column + // (as close to the closed frame as possible) to distribute the width + // to. if (frp2->fr_win != NULL && frp2->fr_win->w_p_wfw) { frp = frp_close->fr_prev; frp3 = frp_close->fr_next; @@ -3047,7 +3043,6 @@ static tabpage_T *alt_tabpage(void) // Find the last but one tab page. for (tp = first_tabpage; tp->tp_next != curtab; tp = tp->tp_next) { - ; } return tp; } @@ -3112,8 +3107,8 @@ static void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wf } } while (frp != NULL); } else { // fr_layout == FR_COL - /* Complicated case: Resize a column of frames. Resize the bottom - * frame first, frames above that when needed. */ + // Complicated case: Resize a column of frames. Resize the bottom + // frame first, frames above that when needed. frp = topfrp->fr_child; if (wfh) { @@ -3152,12 +3147,14 @@ static void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wf break; } if (topfirst) { - do + do{ frp = frp->fr_next; + } while (wfh && frp != NULL && frame_fixed_height(frp)); } else { - do + do{ frp = frp->fr_prev; + } while (wfh && frp != NULL && frame_fixed_height(frp)); } // Increase "height" if we could not reduce enough frames. @@ -3310,8 +3307,8 @@ static void frame_new_width(frame_T *topfrp, int width, bool leftfirst, bool wfw } } while (frp != NULL); } else { // fr_layout == FR_ROW - /* Complicated case: Resize a row of frames. Resize the rightmost - * frame first, frames left of it when needed. */ + // Complicated case: Resize a row of frames. Resize the rightmost + // frame first, frames left of it when needed. frp = topfrp->fr_child; if (wfw) { @@ -3350,12 +3347,14 @@ static void frame_new_width(frame_T *topfrp, int width, bool leftfirst, bool wfw break; } if (leftfirst) { - do + do{ frp = frp->fr_next; + } while (wfw && frp != NULL && frame_fixed_width(frp)); } else { - do + do{ frp = frp->fr_prev; + } while (wfw && frp != NULL && frame_fixed_width(frp)); } // Increase "width" if we could not reduce enough frames. @@ -3525,7 +3524,7 @@ void close_others(int message, int forceit) if (curwin->w_floating) { if (message && !autocmd_busy) { - EMSG(e_floatonly); + emsg(e_floatonly); } return; } @@ -3533,7 +3532,7 @@ void close_others(int message, int forceit) if (one_window() && !lastwin->w_floating) { if (message && !autocmd_busy) { - MSG(_(m_onlyone)); + msg(_(m_onlyone)); } return; } @@ -3567,7 +3566,7 @@ void close_others(int message, int forceit) } if (message && !ONE_WINDOW) { - EMSG(_("E445: Other window contains changes")); + emsg(_("E445: Other window contains changes")); } } @@ -4043,8 +4042,8 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, bool trigger_enter_a lastused_tabpage = old_curtab; - /* Apply autocommands after updating the display, when 'rows' and - * 'columns' have been set correctly. */ + // Apply autocommands after updating the display, when 'rows' and + // 'columns' have been set correctly. if (trigger_enter_autocmds) { apply_autocmds(EVENT_TABENTER, NULL, NULL, false, curbuf); if (old_curbuf != curbuf) { @@ -4122,14 +4121,12 @@ void goto_tabpage(int n) for (i = n; i < 0; ++i) { for (tp = first_tabpage; tp->tp_next != ttp && tp->tp_next != NULL; tp = tp->tp_next) { - ; } ttp = tp; } } else if (n == 9999) { // Go to last tab page. for (tp = first_tabpage; tp->tp_next != NULL; tp = tp->tp_next) { - ; } } else { // Go to tab page "n". @@ -4776,8 +4773,8 @@ static void win_free(win_T *wp, tabpage_T *tp) xfree(wp->w_localdir); xfree(wp->w_prevdir); - /* Remove the window from the b_wininfo lists, it may happen that the - * freed memory is re-used for another window. */ + // Remove the window from the b_wininfo lists, it may happen that the + // freed memory is re-used for another window. FOR_ALL_BUFFERS(buf) { for (wip = buf->b_wininfo; wip != NULL; wip = wip->wi_next) { if (wip->wi_win == wp) { @@ -4950,8 +4947,8 @@ void shell_new_rows(void) h = frame_minheight(topframe, NULL); } - /* First try setting the heights of windows with 'winfixheight'. If - * that doesn't result in the right height, forget about that option. */ + // First try setting the heights of windows with 'winfixheight'. If + // that doesn't result in the right height, forget about that option. frame_new_height(topframe, h, false, true); if (!frame_check_height(topframe, h)) { frame_new_height(topframe, h, false, false); @@ -4972,8 +4969,8 @@ void shell_new_columns(void) return; } - /* First try setting the widths of windows with 'winfixwidth'. If that - * doesn't result in the right width, forget about that option. */ + // First try setting the widths of windows with 'winfixwidth'. If that + // doesn't result in the right width, forget about that option. frame_new_width(topframe, Columns, false, true); if (!frame_check_width(topframe, Columns)) { frame_new_width(topframe, Columns, false, false); @@ -5008,7 +5005,6 @@ void do_autocmd_winscrolled(win_T *wp) * Save the size of all windows in "gap". */ void win_size_save(garray_T *gap) - { ga_init(gap, (int)sizeof(int), 1); ga_grow(gap, win_count() * 2 + 1); @@ -5522,7 +5518,7 @@ void win_setminheight(void) } p_wmh--; if (first) { - EMSG(_(e_noroom)); + emsg(_(e_noroom)); first = false; } } @@ -5542,7 +5538,7 @@ void win_setminwidth(void) } p_wmw--; if (first) { - EMSG(_(e_noroom)); + emsg(_(e_noroom)); first = false; } } @@ -5572,8 +5568,8 @@ void win_drag_status_line(win_T *dragwin, int offset) } } - /* If this is the last frame in a column, may want to resize the parent - * frame instead (go two up to skip a row of frames). */ + // If this is the last frame in a column, may want to resize the parent + // frame instead (go two up to skip a row of frames). while (curfr != topframe && curfr->fr_next == NULL) { if (fr != topframe) { fr = fr->fr_parent; @@ -5699,8 +5695,8 @@ void win_drag_vsep_line(win_T *dragwin, int offset) fr = fr->fr_parent; } - /* If this is the last frame in a row, may want to resize a parent - * frame instead. */ + // If this is the last frame in a row, may want to resize a parent + // frame instead. while (curfr->fr_next == NULL) { if (fr == topframe) { break; @@ -6037,7 +6033,7 @@ void command_height(void) if (p_ch > old_p_ch) { // p_ch got bigger while (p_ch > old_p_ch) { if (frp == NULL) { - EMSG(_(e_noroom)); + emsg(_(e_noroom)); p_ch = old_p_ch; curtab->tp_ch_used = p_ch; cmdline_row = Rows - p_ch; @@ -6159,7 +6155,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u } if (*ptr == NUL) { // nothing found if (options & FNAME_MESS) { - EMSG(_("E446: No file name under cursor")); + emsg(_("E446: No file name under cursor")); } return NULL; } @@ -6272,7 +6268,7 @@ static void last_status_rec(frame_T *fr, bool statusline) fp = fr; while (fp->fr_height <= frame_minheight(fp, NULL)) { if (fp == topframe) { - EMSG(_(e_noroom)); + emsg(_(e_noroom)); return; } // In a column of frames: go to frame above. If already at @@ -6302,7 +6298,6 @@ static void last_status_rec(frame_T *fr, bool statusline) } else { // horizontally split window, set status line for last one for (fp = fr->fr_child; fp->fr_next != NULL; fp = fp->fr_next) { - ; } last_status_rec(fp, statusline); } @@ -6683,16 +6678,16 @@ int match_add(win_T *wp, const char *const grp, const char *const pat, int prio, return -1; } if (id < -1 || id == 0) { - EMSGN(_("E799: Invalid ID: %" PRId64 + semsg(_("E799: Invalid ID: %" PRId64 " (must be greater than or equal to 1)"), - id); + (int64_t)id); return -1; } if (id != -1) { cur = wp->w_match_head; while (cur != NULL) { if (cur->id == id) { - EMSGN(_("E801: ID already taken: %" PRId64), id); + semsg(_("E801: ID already taken: %" PRId64), (int64_t)id); return -1; } cur = cur->next; @@ -6702,7 +6697,7 @@ int match_add(win_T *wp, const char *const grp, const char *const pat, int prio, return -1; } if (pat != NULL && (regprog = vim_regcomp((char_u *)pat, RE_MAGIC)) == NULL) { - EMSG2(_(e_invarg2), pat); + semsg(_(e_invarg2), pat); return -1; } @@ -6748,7 +6743,7 @@ int match_add(win_T *wp, const char *const grp, const char *const pat, int prio, const list_T *const subl = TV_LIST_ITEM_TV(li)->vval.v_list; const listitem_T *subli = tv_list_first(subl); if (subli == NULL) { - emsgf(_("E5030: Empty list at position %d"), + semsg(_("E5030: Empty list at position %d"), (int)tv_list_idx_of_item(pos_list, li)); goto fail; } @@ -6790,7 +6785,7 @@ int match_add(win_T *wp, const char *const grp, const char *const pat, int prio, m->pos.pos[i].col = 0; m->pos.pos[i].len = 0; } else { - emsgf(_("E5031: List or number required at position %d"), + semsg(_("E5031: List or number required at position %d"), (int)tv_list_idx_of_item(pos_list, li)); goto fail; } @@ -6862,9 +6857,9 @@ int match_delete(win_T *wp, int id, bool perr) if (id < 1) { if (perr) { - EMSGN(_("E802: Invalid ID: %" PRId64 + semsg(_("E802: Invalid ID: %" PRId64 " (must be greater than or equal to 1)"), - id); + (int64_t)id); } return -1; } @@ -6874,7 +6869,7 @@ int match_delete(win_T *wp, int id, bool perr) } if (cur == NULL) { if (perr) { - EMSGN(_("E803: ID not found: %" PRId64), id); + semsg(_("E803: ID not found: %" PRId64), (int64_t)id); } return -1; } @@ -7162,7 +7157,8 @@ void win_ui_flush(void) } } -win_T *lastwin_nofloating(void) { +win_T *lastwin_nofloating(void) +{ win_T *res = lastwin; while (res->w_floating) { res = res->w_prev; diff --git a/src/uncrustify.cfg b/src/uncrustify.cfg index 13d1f472ed..c06bf41d47 100644 --- a/src/uncrustify.cfg +++ b/src/uncrustify.cfg @@ -160,16 +160,16 @@ sp_pp_stringify = ignore # ignore/add/remove/force/not_defined sp_before_pp_stringify = ignore # ignore/add/remove/force/not_defined # Add or remove space around boolean operators '&&' and '||'. -sp_bool = ignore # ignore/add/remove/force/not_defined +sp_bool = force # ignore/add/remove/force/not_defined # Add or remove space around compare operator '<', '>', '==', etc. -sp_compare = ignore # ignore/add/remove/force/not_defined +sp_compare = force # ignore/add/remove/force/not_defined # Add or remove space inside '(' and ')'. -sp_inside_paren = ignore # ignore/add/remove/force/not_defined +sp_inside_paren = remove # ignore/add/remove/force/not_defined # Add or remove space between nested parentheses, i.e. '((' vs. ') )'. -sp_paren_paren = ignore # ignore/add/remove/force/not_defined +sp_paren_paren = remove # ignore/add/remove/force/not_defined # Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('. sp_cparen_oparen = ignore # ignore/add/remove/force/not_defined @@ -301,7 +301,7 @@ sp_angle_word = ignore # ignore/add/remove/force/not_defined # Add or remove space between '>' and '>' in '>>' (template stuff). # # Default: add -sp_angle_shift = ignore # ignore/add/remove/force/not_defined +sp_angle_shift = add # ignore/add/remove/force/not_defined # (C++11) Permit removal of the space between '>>' in 'foo<bar<int> >'. Note # that sp_angle_shift cannot remove the space without this option. @@ -309,10 +309,10 @@ sp_permit_cpp11_shift = false # true/false # Add or remove space before '(' of control statements ('if', 'for', 'switch', # 'while', etc.). -sp_before_sparen = ignore # ignore/add/remove/force/not_defined +sp_before_sparen = force # ignore/add/remove/force/not_defined # Add or remove space inside '(' and ')' of control statements. -sp_inside_sparen = ignore # ignore/add/remove/force/not_defined +sp_inside_sparen = remove # ignore/add/remove/force/not_defined # Add or remove space after '(' of control statements. # @@ -370,12 +370,12 @@ sp_between_semi_for_empty = ignore # ignore/add/remove/force/not_defined # Add or remove space after ';', except when followed by a comment. # # Default: add -sp_after_semi = ignore # ignore/add/remove/force/not_defined +sp_after_semi = add # ignore/add/remove/force/not_defined # Add or remove space after ';' in non-empty 'for' statements. # # Default: force -sp_after_semi_for = ignore # ignore/add/remove/force/not_defined +sp_after_semi_for = force # ignore/add/remove/force/not_defined # Add or remove space after the final semicolon of an empty part of a for # statement, as in 'for ( ; ; <here> )'. @@ -387,7 +387,7 @@ sp_before_square = ignore # ignore/add/remove/force/not_defined # Add or remove space before '[' for a variable definition. # # Default: remove -sp_before_vardef_square = ignore # ignore/add/remove/force/not_defined +sp_before_vardef_square = remove # ignore/add/remove/force/not_defined # Add or remove space before '[' for asm block. sp_before_square_asm_block = ignore # ignore/add/remove/force/not_defined @@ -432,7 +432,7 @@ sp_between_mdatype_commas = ignore # ignore/add/remove/force/not_defined # i.e. '(,' vs. '( ,'. # # Default: force -sp_paren_comma = ignore # ignore/add/remove/force/not_defined +sp_paren_comma = force # ignore/add/remove/force/not_defined # Add or remove space after the variadic '...' when preceded by a # non-punctuator. @@ -474,12 +474,12 @@ sp_before_class_colon = ignore # ignore/add/remove/force/not_defined # Add or remove space after class constructor ':'. # # Default: add -sp_after_constr_colon = ignore # ignore/add/remove/force/not_defined +sp_after_constr_colon = add # ignore/add/remove/force/not_defined # Add or remove space before class constructor ':'. # # Default: add -sp_before_constr_colon = ignore # ignore/add/remove/force/not_defined +sp_before_constr_colon = add # ignore/add/remove/force/not_defined # Add or remove space before case ':'. # @@ -502,14 +502,14 @@ sp_after_operator_sym_empty = ignore # ignore/add/remove/force/not_defined sp_after_cast = remove # ignore/add/remove/force/not_defined # Add or remove spaces inside cast parentheses. -sp_inside_paren_cast = ignore # ignore/add/remove/force/not_defined +sp_inside_paren_cast = remove # ignore/add/remove/force/not_defined # Add or remove space between the type and open parenthesis in a C++ cast, # i.e. 'int(exp)' vs. 'int (exp)'. sp_cpp_cast_paren = ignore # ignore/add/remove/force/not_defined # Add or remove space between 'sizeof' and '('. -sp_sizeof_paren = ignore # ignore/add/remove/force/not_defined +sp_sizeof_paren = remove # ignore/add/remove/force/not_defined # Add or remove space between 'sizeof' and '...'. sp_sizeof_ellipsis = ignore # ignore/add/remove/force/not_defined @@ -694,12 +694,12 @@ sp_scope_paren = ignore # ignore/add/remove/force/not_defined # Add or remove space between 'super' and '(' in 'super (something)'. # # Default: remove -sp_super_paren = ignore # ignore/add/remove/force/not_defined +sp_super_paren = remove # ignore/add/remove/force/not_defined # Add or remove space between 'this' and '(' in 'this (something)'. # # Default: remove -sp_this_paren = ignore # ignore/add/remove/force/not_defined +sp_this_paren = remove # ignore/add/remove/force/not_defined # Add or remove space between a macro name and its definition. sp_macro = ignore # ignore/add/remove/force/not_defined @@ -751,7 +751,7 @@ sp_word_brace_init_lst = ignore # ignore/add/remove/force/not_defined # Add or remove space between a variable and '{' for a namespace. # # Default: add -sp_word_brace_ns = ignore # ignore/add/remove/force/not_defined +sp_word_brace_ns = add # ignore/add/remove/force/not_defined # Add or remove space before the '::' operator. sp_before_dc = ignore # ignore/add/remove/force/not_defined @@ -765,34 +765,34 @@ sp_d_array_colon = ignore # ignore/add/remove/force/not_defined # Add or remove space after the '!' (not) unary operator. # # Default: remove -sp_not = ignore # ignore/add/remove/force/not_defined +sp_not = remove # ignore/add/remove/force/not_defined # Add or remove space after the '~' (invert) unary operator. # # Default: remove -sp_inv = ignore # ignore/add/remove/force/not_defined +sp_inv = remove # ignore/add/remove/force/not_defined # Add or remove space after the '&' (address-of) unary operator. This does not # affect the spacing after a '&' that is part of a type. # # Default: remove -sp_addr = ignore # ignore/add/remove/force/not_defined +sp_addr = remove # ignore/add/remove/force/not_defined # Add or remove space around the '.' or '->' operators. # # Default: remove -sp_member = ignore # ignore/add/remove/force/not_defined +sp_member = remove # ignore/add/remove/force/not_defined # Add or remove space after the '*' (dereference) unary operator. This does # not affect the spacing after a '*' that is part of a type. # # Default: remove -sp_deref = ignore # ignore/add/remove/force/not_defined +sp_deref = remove # ignore/add/remove/force/not_defined # Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. # # Default: remove -sp_sign = ignore # ignore/add/remove/force/not_defined +sp_sign = remove # ignore/add/remove/force/not_defined # Add or remove space between '++' and '--' the word to which it is being # applied, as in '(--x)' or 'y++;'. @@ -803,7 +803,7 @@ sp_incdec = remove # ignore/add/remove/force/not_defined # Add or remove space before a backslash-newline at the end of a line. # # Default: add -sp_before_nl_cont = ignore # ignore/add/remove/force/not_defined +sp_before_nl_cont = force # ignore/add/remove/force/not_defined # (OC) Add or remove space after the scope '+' or '-', as in '-(void) foo;' # or '+(int) bar;'. @@ -1549,7 +1549,7 @@ nl_enum_identifier_colon = ignore # ignore/add/remove/force/not_defined nl_enum_colon_type = ignore # ignore/add/remove/force/not_defined # Add or remove newline between 'struct and '{'. -nl_struct_brace = ignore # ignore/add/remove/force/not_defined +nl_struct_brace = remove # ignore/add/remove/force/not_defined # Add or remove newline between 'union' and '{'. nl_union_brace = ignore # ignore/add/remove/force/not_defined @@ -1565,16 +1565,16 @@ nl_brace_else = remove # ignore/add/remove/force/not_defined nl_elseif_brace = ignore # ignore/add/remove/force/not_defined # Add or remove newline between 'else' and '{'. -nl_else_brace = ignore # ignore/add/remove/force/not_defined +nl_else_brace = remove # ignore/add/remove/force/not_defined # Add or remove newline between 'else' and 'if'. -nl_else_if = ignore # ignore/add/remove/force/not_defined +nl_else_if = remove # ignore/add/remove/force/not_defined # Add or remove newline before '{' opening brace nl_before_opening_brace_func_class_def = ignore # ignore/add/remove/force/not_defined # Add or remove newline before 'if'/'else if' closing parenthesis. -nl_before_if_closing_paren = ignore # ignore/add/remove/force/not_defined +nl_before_if_closing_paren = remove # ignore/add/remove/force/not_defined # Add or remove newline between '}' and 'finally'. nl_brace_finally = ignore # ignore/add/remove/force/not_defined @@ -1897,7 +1897,7 @@ nl_template_end = false # true/false nl_oc_msg_args = false # true/false # Add or remove newline between function signature and '{'. -nl_fdef_brace = ignore # ignore/add/remove/force/not_defined +nl_fdef_brace = force # ignore/add/remove/force/not_defined # Add or remove newline between function signature and '{', # if signature ends with ')'. Overrides nl_fdef_brace. @@ -1907,7 +1907,7 @@ nl_fdef_brace_cond = ignore # ignore/add/remove/force/not_defined nl_cpp_ldef_brace = ignore # ignore/add/remove/force/not_defined # Add or remove newline between 'return' and the return expression. -nl_return_expr = ignore # ignore/add/remove/force/not_defined +nl_return_expr = remove # ignore/add/remove/force/not_defined # Whether to add a newline after semicolons, except in 'for' statements. nl_after_semicolon = false # true/false @@ -2093,7 +2093,7 @@ donot_add_nl_before_cpp_comment = false # true/false # # The maximum number of consecutive newlines (3 = 2 blank lines). -nl_max = 0 # unsigned number +nl_max = 3 # unsigned number # The maximum number of consecutive newlines in a function. nl_max_blank_in_func = 0 # unsigned number @@ -2886,7 +2886,7 @@ cmt_insert_before_ctor_dtor = false # true/false # # Add or remove braces on a single-line 'do' statement. -mod_full_brace_do = ignore # ignore/add/remove/force/not_defined +mod_full_brace_do = add # ignore/add/remove/force/not_defined # Add or remove braces on a single-line 'for' statement. mod_full_brace_for = add # ignore/add/remove/force/not_defined @@ -2947,10 +2947,10 @@ mod_pawn_semicolon = false # true/false mod_full_paren_if_bool = false # true/false # Whether to remove superfluous semicolons. -mod_remove_extra_semicolon = false # true/false +mod_remove_extra_semicolon = true # true/false # Whether to remove duplicate include. -mod_remove_duplicate_include = false # true/false +mod_remove_duplicate_include = true # true/false # If a function body exceeds the specified number of newlines and doesn't have # a comment after the close brace, a comment will be added. @@ -3022,7 +3022,7 @@ mod_case_brace = remove # ignore/add/remove/force/not_defined mod_remove_empty_return = false # true/false # Add or remove the comma after the last value of an enumeration. -mod_enum_last_comma = ignore # ignore/add/remove/force/not_defined +mod_enum_last_comma = add # ignore/add/remove/force/not_defined # (OC) Whether to organize the properties. If true, properties will be # rearranged according to the mod_sort_oc_property_*_weight factors. @@ -3307,5 +3307,5 @@ set QUESTION REAL_FATTR_CONST set QUESTION REAL_FATTR_NONNULL_ALL set QUESTION REAL_FATTR_PURE set QUESTION REAL_FATTR_WARN_UNUSED_RESULT -# option(s) with 'not default' value: 66 +# option(s) with 'not default' value: 69 # diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua index 01fcfab543..a0c97804b7 100644 --- a/test/functional/api/buffer_spec.lua +++ b/test/functional/api/buffer_spec.lua @@ -711,46 +711,46 @@ describe('api/buf', function() describe('nvim_buf_set_mark', function() it('works with buffer local marks', function() curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'}) - eq(true, curbufmeths.set_mark('z', 1, 1)) + eq(true, curbufmeths.set_mark('z', 1, 1, {})) eq({1, 1}, curbufmeths.get_mark('z')) end) it('works with file/uppercase marks', function() curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'}) - eq(true, curbufmeths.set_mark('Z', 3, 1)) + eq(true, curbufmeths.set_mark('Z', 3, 1, {})) eq({3, 1}, curbufmeths.get_mark('Z')) end) it('fails when invalid marks names are used', function() - eq(false, pcall(curbufmeths.set_mark, '!', 1, 0)) - eq(false, pcall(curbufmeths.set_mark, 'fail', 1, 0)) + eq(false, pcall(curbufmeths.set_mark, '!', 1, 0, {})) + eq(false, pcall(curbufmeths.set_mark, 'fail', 1, 0, {})) end) it('fails when invalid buffer number is used', function() - eq(false, pcall(meths.buf_set_mark, 99, 'a', 1, 1)) + eq(false, pcall(meths.buf_set_mark, 99, 'a', 1, 1, {})) end) end) describe('nvim_buf_del_mark', function() it('works with buffer local marks', function() curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'}) - curbufmeths.set_mark('z', 3, 1) + curbufmeths.set_mark('z', 3, 1, {}) eq(true, curbufmeths.del_mark('z')) eq({0, 0}, curbufmeths.get_mark('z')) end) it('works with file/uppercase marks', function() curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'}) - curbufmeths.set_mark('Z', 3, 3) + curbufmeths.set_mark('Z', 3, 3, {}) eq(true, curbufmeths.del_mark('Z')) eq({0, 0}, curbufmeths.get_mark('Z')) end) it('returns false in marks not set in this buffer', function() local abuf = meths.create_buf(false,true) bufmeths.set_lines(abuf, -1, -1, true, {'a', 'bit of', 'text'}) - bufmeths.set_mark(abuf, 'A', 2, 2) + bufmeths.set_mark(abuf, 'A', 2, 2, {}) eq(false, curbufmeths.del_mark('A')) eq({2, 2}, bufmeths.get_mark(abuf, 'A')) end) it('returns false if mark was not deleted', function() curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'}) - curbufmeths.set_mark('z', 3, 1) + curbufmeths.set_mark('z', 3, 1, {}) eq(true, curbufmeths.del_mark('z')) eq(false, curbufmeths.del_mark('z')) -- Mark was already deleted end) diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua index e408890906..309d9084c8 100644 --- a/test/functional/api/server_requests_spec.lua +++ b/test/functional/api/server_requests_spec.lua @@ -278,8 +278,9 @@ describe('server -> client', function() local nvim_argv = merge_args(helpers.nvim_argv, {'--headless'}) local function connect_test(server, mode, address) local serverpid = funcs.getpid() - local client = spawn(nvim_argv) - set_session(client, true) + local client = spawn(nvim_argv, false, nil, true) + set_session(client) + local clientpid = funcs.getpid() neq(serverpid, clientpid) local id = funcs.sockconnect(mode, address, {rpc=true}) @@ -288,7 +289,7 @@ describe('server -> client', function() funcs.rpcrequest(id, 'nvim_set_current_line', 'hello') local client_id = funcs.rpcrequest(id, 'nvim_get_api_info')[1] - set_session(server, true) + set_session(server) eq(serverpid, funcs.getpid()) eq('hello', meths.get_current_line()) @@ -296,7 +297,7 @@ describe('server -> client', function() funcs.rpcrequest(client_id, 'nvim_set_current_line', 'howdy!') eq(id, funcs.rpcrequest(client_id, 'nvim_get_api_info')[1]) - set_session(client, true) + set_session(client) eq(clientpid, funcs.getpid()) eq('howdy!', meths.get_current_line()) diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index f030cfe00e..21de4925b5 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -22,6 +22,7 @@ local source = helpers.source local next_msg = helpers.next_msg local tmpname = helpers.tmpname local write_file = helpers.write_file +local exec_lua = helpers.exec_lua local pcall_err = helpers.pcall_err local format_string = helpers.format_string @@ -1689,7 +1690,7 @@ describe('API', function() end) local it_maybe_pending = it - if (helpers.isCI('appveyor') and os.getenv('CONFIGURATION') == 'MSVC_32') then + if helpers.isCI() and os.getenv('CONFIGURATION') == 'MSVC_32' then -- For "works with &opt" (flaky on MSVC_32), but not easy to skip alone. #10241 it_maybe_pending = pending end @@ -2264,6 +2265,9 @@ describe('API', function() [2] = {background = tonumber('0xffff40'), bg_indexed = true}; [3] = {background = Screen.colors.Plum1, fg_indexed = true, foreground = tonumber('0x00e000')}; [4] = {bold = true, reverse = true, background = Screen.colors.Plum1}; + [5] = {foreground = Screen.colors.Blue, background = Screen.colors.LightMagenta, bold = true}; + [6] = {bold = true}; + [7] = {reverse = true, background = Screen.colors.LightMagenta}; }) end) @@ -2311,13 +2315,81 @@ describe('API', function() | ]]} end) + + it('can handle input', function() + screen:try_resize(50, 10) + eq({3, 2}, exec_lua [[ + buf = vim.api.nvim_create_buf(1,1) + + stream = '' + do_the_echo = false + function input(_,t1,b1,data) + stream = stream .. data + _G.vals = {t1, b1} + if do_the_echo then + vim.api.nvim_chan_send(t1, data) + end + end + + term = vim.api.nvim_open_term(buf, {on_input=input}) + vim.api.nvim_open_win(buf, true, {width=40, height=5, row=1, col=1, relative='editor'}) + return {term, buf} + ]]) + + screen:expect{grid=[[ + | + {0:~}{1:^ }{0: }| + {0:~}{1: }{0: }| + {0:~}{1: }{0: }| + {0:~}{1: }{0: }| + {0:~}{1: }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]} + + feed 'iba<c-x>bla' + screen:expect{grid=[[ + | + {0:~}{7: }{1: }{0: }| + {0:~}{1: }{0: }| + {0:~}{1: }{0: }| + {0:~}{1: }{0: }| + {0:~}{1: }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + {6:-- TERMINAL --} | + ]]} + + eq('ba\024bla', exec_lua [[ return stream ]]) + eq({3,2}, exec_lua [[ return vals ]]) + + exec_lua [[ do_the_echo = true ]] + feed 'herrejösses!' + + screen:expect{grid=[[ + | + {0:~}{1:herrejösses!}{7: }{1: }{0: }| + {0:~}{1: }{0: }| + {0:~}{1: }{0: }| + {0:~}{1: }{0: }| + {0:~}{1: }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + {6:-- TERMINAL --} | + ]]} + eq('ba\024blaherrejösses!', exec_lua [[ return stream ]]) + end) end) describe('nvim_del_mark', function() it('works', function() local buf = meths.create_buf(false,true) meths.buf_set_lines(buf, -1, -1, true, {'a', 'bit of', 'text'}) - eq(true, meths.buf_set_mark(buf, 'F', 2, 2)) + eq(true, meths.buf_set_mark(buf, 'F', 2, 2, {})) eq(true, meths.del_mark('F')) eq({0, 0}, meths.buf_get_mark(buf, 'F')) end) @@ -2331,9 +2403,9 @@ describe('API', function() it('works', function() local buf = meths.create_buf(false,true) meths.buf_set_lines(buf, -1, -1, true, {'a', 'bit of', 'text'}) - meths.buf_set_mark(buf, 'F', 2, 2) + meths.buf_set_mark(buf, 'F', 2, 2, {}) meths.buf_set_name(buf, "mybuf") - local mark = meths.get_mark('F') + local mark = meths.get_mark('F', {}) -- Compare the path tail ony assert(string.find(mark[4], "mybuf$")) eq({2, 2, buf.id, mark[4]}, mark) @@ -2345,7 +2417,7 @@ describe('API', function() end) it('returns the expected when mark is not set', function() eq(true, meths.del_mark('A')) - eq({0, 0, 0, ''}, meths.get_mark('A')) + eq({0, 0, 0, ''}, meths.get_mark('A', {})) end) it('works with deleted buffers', function() local fname = tmpname() @@ -2353,12 +2425,12 @@ describe('API', function() nvim("command", "edit " .. fname) local buf = meths.get_current_buf() - meths.buf_set_mark(buf, 'F', 2, 2) + meths.buf_set_mark(buf, 'F', 2, 2, {}) nvim("command", "new") -- Create new buf to avoid :bd failing nvim("command", "bd! " .. buf.id) os.remove(fname) - local mark = meths.get_mark('F') + local mark = meths.get_mark('F', {}) -- To avoid comparing relative vs absolute path local mfname = mark[4] local tail_patt = [[[\/][^\/]*$]] diff --git a/test/functional/core/channels_spec.lua b/test/functional/core/channels_spec.lua index 6efa4f9b80..93dec9fb35 100644 --- a/test/functional/core/channels_spec.lua +++ b/test/functional/core/channels_spec.lua @@ -29,11 +29,11 @@ describe('channels', function() end) pending('can connect to socket', function() - local server = spawn(nvim_argv) + local server = spawn(nvim_argv, nil, nil, true) set_session(server) local address = funcs.serverlist()[1] - local client = spawn(nvim_argv) - set_session(client, true) + local client = spawn(nvim_argv, nil, nil, true) + set_session(client) source(init) meths.set_var('address', address) @@ -42,11 +42,11 @@ describe('channels', function() ok(id > 0) command("call chansend(g:id, msgpackdump([[2,'nvim_set_var',['code',23]]]))") - set_session(server, true) + set_session(server) retry(nil, 1000, function() eq(23, meths.get_var('code')) end) - set_session(client, true) + set_session(client) command("call chansend(g:id, msgpackdump([[0,0,'nvim_eval',['2+3']]]))") diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua index cc6e2c8067..d1dce0f8da 100644 --- a/test/functional/core/startup_spec.lua +++ b/test/functional/core/startup_spec.lua @@ -414,6 +414,11 @@ describe('startup', function() eq({'ordinary', 'funky!', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]]) eq({'ordinary', 'funky!', 'mittel', 'ordinary after'}, exec_lua [[ return _G.nested_order ]]) end) + + it("handles the correct order when prepending packpath", function() + clear{args={'--cmd', 'set packpath^=test/functional/fixtures', '--cmd', [[ lua _G.test_loadorder = {} vim.cmd "runtime! filen.lua" ]]}, env={XDG_CONFIG_HOME='test/functional/fixtures/'}} + eq({'ordinary', 'FANCY', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]]) + end) end) describe('sysinit', function() diff --git a/test/functional/editor/meta_key_spec.lua b/test/functional/editor/meta_key_spec.lua index c219204409..2280f5bb24 100644 --- a/test/functional/editor/meta_key_spec.lua +++ b/test/functional/editor/meta_key_spec.lua @@ -1,6 +1,8 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local command = helpers.command +local exec_lua = helpers.exec_lua +local eval = helpers.eval local expect = helpers.expect local funcs = helpers.funcs local eq = helpers.eq @@ -61,4 +63,30 @@ describe('meta-keys #8226 #13042', function() feed('u') expect('hello') end) + + it('ALT/META terminal-mode', function() + exec_lua([[ + _G.input_data = '' + vim.api.nvim_open_term(0, { on_input = function(_, _, _, data) + _G.input_data = _G.input_data .. vim.fn.strtrans(data) + end }) + ]]) + -- Mapped ALT-chord behaves as mapped. + command('tnoremap <M-l> meta-l') + command('tnoremap <A-j> alt-j') + feed('i<M-l> xxx <A-j>') + eq('meta-l xxx alt-j', exec_lua([[return _G.input_data]])) + -- Unmapped ALT-chord is sent to terminal as-is. #16220 + exec_lua([[_G.input_data = '']]) + command('tunmap <M-l>') + feed('<M-l>') + local meta_l_seq = exec_lua([[return _G.input_data]]) + command('tnoremap <Esc> <C-\\><C-N>') + feed('yyy<M-l><A-j>') + eq(meta_l_seq .. 'yyy' .. meta_l_seq .. 'alt-j', exec_lua([[return _G.input_data]])) + eq('t', eval('mode(1)')) + feed('<Esc>j') + eq({ 0, 2, 1, 0, }, funcs.getpos('.')) + eq('nt', eval('mode(1)')) + end) end) diff --git a/test/functional/fixtures/fake-lsp-server.lua b/test/functional/fixtures/fake-lsp-server.lua index 9abf478070..5c0de50731 100644 --- a/test/functional/fixtures/fake-lsp-server.lua +++ b/test/functional/fixtures/fake-lsp-server.lua @@ -275,6 +275,55 @@ function tests.check_forward_content_modified() } end +function tests.check_pending_request_tracked() + skeleton { + on_init = function(_) + return { capabilities = {} } + end; + body = function() + local msg = read_message() + assert_eq('slow_request', msg.method) + expect_notification('release') + respond(msg.id, nil, {}) + expect_notification('finish') + notify('finish') + end; + } +end + +function tests.check_cancel_request_tracked() + skeleton { + on_init = function(_) + return { capabilities = {} } + end; + body = function() + local msg = read_message() + assert_eq('slow_request', msg.method) + expect_notification('$/cancelRequest', {id=msg.id}) + expect_notification('release') + respond(msg.id, {code = -32800}, nil) + notify('finish') + end; + } +end + +function tests.check_tracked_requests_cleared() + skeleton { + on_init = function(_) + return { capabilities = {} } + end; + body = function() + local msg = read_message() + assert_eq('slow_request', msg.method) + expect_notification('$/cancelRequest', {id=msg.id}) + expect_notification('release') + respond(msg.id, nil, {}) + expect_notification('finish') + notify('finish') + end; + } +end + function tests.basic_finish() skeleton { on_init = function(params) @@ -622,6 +671,20 @@ function tests.code_action_with_resolve() } end +function tests.clientside_commands() + skeleton { + on_init = function() + return { + capabilities = {} + } + end; + body = function() + notify('start') + notify('shutdown') + end; + } +end + -- Tests will be indexed by TEST_NAME local kill_timer = vim.loop.new_timer() diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index a26e883370..f152a487af 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -96,10 +96,7 @@ function module.get_session() return session end -function module.set_session(s, keep) - if session and not keep then - session:close() - end +function module.set_session(s) session = s end @@ -366,7 +363,11 @@ local function remove_args(args, args_rm) return new_args end -function module.spawn(argv, merge, env) +function module.spawn(argv, merge, env, keep) + if session and not keep then + session:close() + end + local child_stream = ChildProcessStream.spawn( merge and module.merge_args(prepend_argv, argv) or argv, env) diff --git a/test/functional/lua/api_spec.lua b/test/functional/lua/api_spec.lua index 8551c3d2a0..81e00bba6d 100644 --- a/test/functional/lua/api_spec.lua +++ b/test/functional/lua/api_spec.lua @@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local exc_exec = helpers.exc_exec +local remove_trace = helpers.remove_trace local funcs = helpers.funcs local clear = helpers.clear local eval = helpers.eval @@ -159,44 +160,44 @@ describe('luaeval(vim.api.…)', function() it('errors out correctly when working with API', function() -- Conversion errors eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Cannot convert given lua type', - exc_exec([[call luaeval("vim.api.nvim__id(vim.api.nvim__id)")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim__id(vim.api.nvim__id)")]]))) eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Cannot convert given lua table', - exc_exec([[call luaeval("vim.api.nvim__id({1, foo=42})")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim__id({1, foo=42})")]]))) eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Cannot convert given lua type', - exc_exec([[call luaeval("vim.api.nvim__id({42, vim.api.nvim__id})")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim__id({42, vim.api.nvim__id})")]]))) -- Errors in number of arguments eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 1 argument', - exc_exec([[call luaeval("vim.api.nvim__id()")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim__id()")]]))) eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 1 argument', - exc_exec([[call luaeval("vim.api.nvim__id(1, 2)")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim__id(1, 2)")]]))) eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 2 arguments', - exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2, 3)")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2, 3)")]]))) -- Error in argument types eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua string', - exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2)")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2)")]]))) eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua number', - exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 'test', 1, false)")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 'test', 1, false)")]]))) eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Number is not integral', - exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 1.5, 1, false)")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 1.5, 1, false)")]]))) eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table', - exc_exec([[call luaeval("vim.api.nvim__id_float('test')")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_float('test')")]]))) eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Unexpected type', - exc_exec([[call luaeval("vim.api.nvim__id_float({[vim.type_idx]=vim.types.dictionary})")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_float({[vim.type_idx]=vim.types.dictionary})")]]))) eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table', - exc_exec([[call luaeval("vim.api.nvim__id_array(1)")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_array(1)")]]))) eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Unexpected type', - exc_exec([[call luaeval("vim.api.nvim__id_array({[vim.type_idx]=vim.types.dictionary})")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_array({[vim.type_idx]=vim.types.dictionary})")]]))) eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table', - exc_exec([[call luaeval("vim.api.nvim__id_dictionary(1)")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_dictionary(1)")]]))) eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Unexpected type', - exc_exec([[call luaeval("vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.array})")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.array})")]]))) eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table', - exc_exec([[call luaeval("vim.api.nvim_set_keymap('', '', '', '')")]])) + remove_trace(exc_exec([[call luaeval("vim.api.nvim_set_keymap('', '', '', '')")]]))) -- TODO: check for errors with Tabpage argument -- TODO: check for errors with Window argument diff --git a/test/functional/lua/commands_spec.lua b/test/functional/lua/commands_spec.lua index 2e0d0ea899..9b9ba531b0 100644 --- a/test/functional/lua/commands_spec.lua +++ b/test/functional/lua/commands_spec.lua @@ -17,6 +17,7 @@ local pcall_err = helpers.pcall_err local write_file = helpers.write_file local exec_capture = helpers.exec_capture local curbufmeths = helpers.curbufmeths +local remove_trace = helpers.remove_trace before_each(clear) @@ -46,9 +47,9 @@ describe(':lua command', function() eq([[Vim(lua):E5107: Error loading lua [string ":lua"]:0: unexpected symbol near ')']], pcall_err(command, 'lua ()')) eq([[Vim(lua):E5108: Error executing lua [string ":lua"]:1: TEST]], - exc_exec('lua error("TEST")')) + remove_trace(exc_exec('lua error("TEST")'))) eq([[Vim(lua):E5108: Error executing lua [string ":lua"]:1: Invalid buffer id: -10]], - exc_exec('lua vim.api.nvim_buf_set_lines(-10, 1, 1, false, {"TEST"})')) + remove_trace(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() @@ -95,15 +96,15 @@ describe(':lua command', function() feed(':lua error("fail\\nmuch error\\nsuch details")<cr>') screen:expect{grid=[[ - | - {1:~ }| - {1:~ }| - {1:~ }| {2: }| {3:E5108: Error executing lua [string ":lua}| {3:"]:1: fail} | {3:much error} | {3:such details} | + {3:stack traceback:} | + {3: [C]: in function 'error'} | + {3: [string ":lua"]:1: in main chunk}| + | {4:Press ENTER or type command to continue}^ | ]]} feed('<cr>') @@ -119,24 +120,24 @@ describe(':lua command', function() {1:~ }| | ]]} - eq('E5108: Error executing lua [string ":lua"]:1: fail\nmuch error\nsuch details', eval('v:errmsg')) + eq('E5108: Error executing lua [string ":lua"]:1: fail\nmuch error\nsuch details', remove_trace(eval('v:errmsg'))) local status, err = pcall(command,'lua error("some error\\nin a\\nAPI command")') local expected = 'Vim(lua):E5108: Error executing lua [string ":lua"]:1: some error\nin a\nAPI command' eq(false, status) - eq(expected, string.sub(err, -string.len(expected))) + eq(expected, string.sub(remove_trace(err), -string.len(expected))) feed(':messages<cr>') screen:expect{grid=[[ - | - {1:~ }| - {1:~ }| - {1:~ }| {2: }| {3:E5108: Error executing lua [string ":lua}| {3:"]:1: fail} | {3:much error} | {3:such details} | + {3:stack traceback:} | + {3: [C]: in function 'error'} | + {3: [string ":lua"]:1: in main chunk}| + | {4:Press ENTER or type command to continue}^ | ]]} end) @@ -219,7 +220,7 @@ describe(':luafile', function() 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)) + remove_trace(exc_exec('luafile ' .. fname))) end) it('works with NULL errors', function() write_file(fname, 'error(nil)') diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua index 33469597a1..ec53916024 100644 --- a/test/functional/lua/diagnostic_spec.lua +++ b/test/functional/lua/diagnostic_spec.lua @@ -6,6 +6,8 @@ local clear = helpers.clear local exec_lua = helpers.exec_lua local eq = helpers.eq local nvim = helpers.nvim +local matches = helpers.matches +local pcall_err = helpers.pcall_err describe('vim.diagnostic', function() before_each(function() @@ -47,7 +49,21 @@ describe('vim.diagnostic', function() end function count_extmarks(bufnr, namespace) - return #vim.api.nvim_buf_get_extmarks(bufnr, namespace, 0, -1, {}) + local ns = vim.diagnostic.get_namespace(namespace) + local extmarks = 0 + if ns.user_data.virt_text_ns then + extmarks = extmarks + #vim.api.nvim_buf_get_extmarks(bufnr, ns.user_data.virt_text_ns, 0, -1, {}) + end + if ns.user_data.underline_ns then + extmarks = extmarks + #vim.api.nvim_buf_get_extmarks(bufnr, ns.user_data.underline_ns, 0, -1, {}) + end + return extmarks + end + + function get_virt_text_extmarks(ns) + local ns = vim.diagnostic.get_namespace(ns) + local virt_text_ns = ns.user_data.virt_text_ns + return vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, virt_text_ns, 0, -1, {details = true}) end ]] @@ -252,6 +268,56 @@ describe('vim.diagnostic', function() ]]) end) + describe('show() and hide()', function() + it('works', function() + local result = exec_lua [[ + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + + local result = {} + + vim.diagnostic.config({ underline = false, virtual_text = true }) + + local ns_1_diags = { + make_error("Error 1", 1, 1, 1, 5), + make_warning("Warning on Server 1", 2, 1, 2, 5), + } + local ns_2_diags = { + make_warning("Warning 1", 2, 1, 2, 5), + } + + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diags) + vim.diagnostic.set(other_ns, diagnostic_bufnr, ns_2_diags) + + -- Both + table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns)) + + -- Hide one namespace + vim.diagnostic.hide(diagnostic_ns) + table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns)) + + -- Show one namespace + vim.diagnostic.show(diagnostic_ns) + table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns)) + + -- Hide all namespaces + vim.diagnostic.hide() + table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns)) + + -- Show all namespaces + vim.diagnostic.show() + table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns)) + + return result + ]] + + eq(3, result[1]) + eq(0, result[2]) + eq(2, result[3]) + eq(0, result[4]) + eq(3, result[5]) + end) + end) + describe('reset()', function() it('diagnostic count is 0 and displayed diagnostics are 0 after call', function() -- 1 Error (1) @@ -567,7 +633,7 @@ describe('vim.diagnostic', function() ]] eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]]) - eq(1, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]]) + -- eq(1, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]]) end) it('allows filtering by severity', function() @@ -615,7 +681,7 @@ describe('vim.diagnostic', function() severity_sort = severity_sort, }) - local virt_text = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})[1][4].virt_text + local virt_text = get_virt_text_extmarks(diagnostic_ns)[1][4].virt_text local virt_texts = {} for i = 2, #virt_text do @@ -661,7 +727,7 @@ describe('vim.diagnostic', function() } }) - local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true}) + local extmarks = get_virt_text_extmarks(diagnostic_ns) local virt_text = extmarks[1][4].virt_text[2][1] return virt_text ]] @@ -676,7 +742,7 @@ describe('vim.diagnostic', function() } }, diagnostic_ns) - local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true}) + local extmarks = get_virt_text_extmarks(diagnostic_ns) local virt_text = extmarks[1][4].virt_text[2][1] return virt_text ]] @@ -696,7 +762,7 @@ describe('vim.diagnostic', function() } }) - local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true}) + local extmarks = get_virt_text_extmarks(diagnostic_ns) local virt_text = {extmarks[1][4].virt_text[2][1], extmarks[2][4].virt_text[2][1]} return virt_text ]] @@ -724,7 +790,7 @@ describe('vim.diagnostic', function() make_error('Error', 1, 0, 1, 0), }) - local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true}) + local extmarks = get_virt_text_extmarks(diagnostic_ns) return {extmarks[1][4].virt_text, extmarks[2][4].virt_text} ]] eq(" 👀 Warning", result[1][2][1]) @@ -752,7 +818,7 @@ describe('vim.diagnostic', function() make_error('Error', 1, 0, 1, 0, 'another_linter'), }) - local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true}) + local extmarks = get_virt_text_extmarks(diagnostic_ns) return {extmarks[1][4].virt_text, extmarks[2][4].virt_text} ]] eq(" some_linter: 👀 Warning", result[1][2][1]) @@ -800,13 +866,11 @@ describe('vim.diagnostic', function() virtual_text = true, }) - -- Count how many times we call display. - SetVirtualTextOriginal = vim.diagnostic._set_virtual_text - DisplayCount = 0 - vim.diagnostic._set_virtual_text = function(...) + local set_virtual_text = vim.diagnostic.handlers.virtual_text.show + vim.diagnostic.handlers.virtual_text.show = function(...) DisplayCount = DisplayCount + 1 - return SetVirtualTextOriginal(...) + return set_virtual_text(...) end vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { @@ -850,13 +914,12 @@ describe('vim.diagnostic', function() virtual_text = false, }) - -- Count how many times we call display. - SetVirtualTextOriginal = vim.diagnostic._set_virtual_text DisplayCount = 0 - vim.diagnostic._set_virtual_text = function(...) + local set_virtual_text = vim.diagnostic.handlers.virtual_text.show + vim.diagnostic.handlers.virtual_text.show = function(...) DisplayCount = DisplayCount + 1 - return SetVirtualTextOriginal(...) + return set_virtual_text(...) end vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { @@ -968,8 +1031,102 @@ describe('vim.diagnostic', function() end) end) - describe('show_line_diagnostics()', function() - it('creates floating window and returns popup bufnr and winnr if current line contains diagnostics', function() + describe('open_float()', function() + it('can show diagnostics from the whole buffer', function() + eq({'1. Syntax error', '2. Some warning'}, exec_lua [[ + local diagnostics = { + make_error("Syntax error", 0, 1, 0, 3), + make_warning("Some warning", 1, 1, 1, 3), + } + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header = false}) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]]) + end) + + it('can show diagnostics from a single line', function() + -- Using cursor position + eq({'1. Some warning'}, exec_lua [[ + local diagnostics = { + make_error("Syntax error", 0, 1, 0, 3), + make_warning("Some warning", 1, 1, 1, 3), + } + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + vim.api.nvim_win_set_cursor(0, {2, 1}) + local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header=false, scope="line"}) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]]) + + -- With specified position + eq({'1. Some warning'}, exec_lua [[ + local diagnostics = { + make_error("Syntax error", 0, 1, 0, 3), + make_warning("Some warning", 1, 1, 1, 3), + } + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + vim.api.nvim_win_set_cursor(0, {1, 1}) + local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header=false, scope="line", pos=1}) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]]) + end) + + it('can show diagnostics from a specific position', function() + -- Using cursor position + eq({'Syntax error'}, exec_lua [[ + local diagnostics = { + make_error("Syntax error", 1, 1, 1, 2), + make_warning("Some warning", 1, 3, 1, 4), + } + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + vim.api.nvim_win_set_cursor(0, {2, 2}) + local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header=false, scope="cursor"}) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]]) + + -- With specified position + eq({'Some warning'}, exec_lua [[ + local diagnostics = { + make_error("Syntax error", 1, 1, 1, 2), + make_warning("Some warning", 1, 3, 1, 4), + } + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + vim.api.nvim_win_set_cursor(0, {1, 1}) + local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header=false, scope="cursor", pos={1,3}}) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]]) + + -- With column position past the end of the line. #16062 + eq({'Syntax error'}, exec_lua [[ + local first_line_len = #vim.api.nvim_buf_get_lines(diagnostic_bufnr, 0, 1, true)[1] + local diagnostics = { + make_error("Syntax error", 0, first_line_len + 1, 1, 0), + } + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + vim.api.nvim_win_set_cursor(0, {1, 1}) + local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header=false, scope="cursor", pos={0,first_line_len}}) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]]) + end) + + it('creates floating window and returns float bufnr and winnr if current line contains diagnostics', function() -- Two lines: -- Diagnostic: -- 1. <msg> @@ -979,8 +1136,10 @@ describe('vim.diagnostic', function() } vim.api.nvim_win_set_buf(0, diagnostic_bufnr) vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) - local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics() - return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false) + local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, {scope="line"}) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return #lines ]]) end) @@ -996,8 +1155,10 @@ describe('vim.diagnostic', function() vim.api.nvim_win_set_buf(0, diagnostic_bufnr) vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, buf_1_diagnostics) vim.diagnostic.set(other_ns, other_bufnr, buf_2_diagnostics) - local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics() - return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false) + local float_bufnr, winnr = vim.diagnostic.open_float() + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return #lines ]]) end) @@ -1012,12 +1173,14 @@ describe('vim.diagnostic', function() vim.api.nvim_win_set_buf(0, diagnostic_bufnr) vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diagnostics) vim.diagnostic.set(other_ns, diagnostic_bufnr, ns_2_diagnostics) - local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics({namespace = diagnostic_ns}) - return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false) + local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, {namespace = diagnostic_ns}) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return #lines ]]) end) - it('creates floating window and returns popup bufnr and winnr without header, if requested', function() + it('creates floating window and returns float bufnr and winnr without header, if requested', function() -- One line (since no header): -- 1. <msg> eq(1, exec_lua [[ @@ -1026,8 +1189,10 @@ describe('vim.diagnostic', function() } vim.api.nvim_win_set_buf(0, diagnostic_bufnr) vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) - local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics {show_header = false} - return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false) + local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, {show_header = false}) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return #lines ]]) end) @@ -1038,8 +1203,10 @@ describe('vim.diagnostic', function() } vim.api.nvim_win_set_buf(0, diagnostic_bufnr) vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) - local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics({show_header = false}, diagnostic_bufnr, 5) - return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false) + local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, {show_header = false, scope = "line", pos = 5}) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return #lines ]]) end) @@ -1051,21 +1218,21 @@ describe('vim.diagnostic', function() make_error("Syntax error", 0, 1, 0, 3, "source x"), } vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) - local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics { + local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, { show_header = false, source = "if_many", - } - local lines = vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false) + }) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) vim.api.nvim_win_close(winnr, true) return lines ]]) eq({"1. source x: Syntax error"}, exec_lua [[ - local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics { + local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, { show_header = false, source = "always", - } - local lines = vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false) + }) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) vim.api.nvim_win_close(winnr, true) return lines ]]) @@ -1076,11 +1243,11 @@ describe('vim.diagnostic', function() make_error("Another error", 0, 1, 0, 3, "source y"), } vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) - local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics { + local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, { show_header = false, source = "if_many", - } - local lines = vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false) + }) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) vim.api.nvim_win_close(winnr, true) return lines ]]) @@ -1101,28 +1268,138 @@ describe('vim.diagnostic', function() vim.diagnostic.config({severity_sort = false}) - local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics { show_header = false } - local lines = vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false) + local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, { show_header = false }) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) vim.api.nvim_win_close(winnr, true) return lines ]]) eq({"1. Syntax error", "2. Error", "3. Warning", "4. Info"}, exec_lua [[ vim.diagnostic.config({severity_sort = true}) - local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics { show_header = false } - local lines = vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false) + local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, { show_header = false }) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) vim.api.nvim_win_close(winnr, true) return lines ]]) eq({"1. Info", "2. Warning", "3. Error", "4. Syntax error"}, exec_lua [[ vim.diagnostic.config({severity_sort = { reverse = true } }) - local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics { show_header = false } - local lines = vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false) + local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, { show_header = false }) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) vim.api.nvim_win_close(winnr, true) return lines ]]) end) + + it('can filter by severity', function() + local count_diagnostics_with_severity = function(min_severity, max_severity) + return exec_lua([[ + local min_severity, max_severity = ... + vim.diagnostic.config({ + float = { + severity = {min=min_severity, max=max_severity}, + }, + }) + + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error("Syntax error", 0, 1, 0, 3), + make_info('Info', 0, 3, 0, 4), + make_error('Error', 0, 2, 0, 2), + make_warning('Warning', 0, 0, 0, 1), + }) + + local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, { show_header = false }) + if not float_bufnr then + return 0 + end + + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return #lines + ]], min_severity, max_severity) + end + + eq(2, count_diagnostics_with_severity("ERROR")) + eq(3, count_diagnostics_with_severity("WARN")) + eq(1, count_diagnostics_with_severity("WARN", "WARN")) + eq(4, count_diagnostics_with_severity("HINT")) + eq(0, count_diagnostics_with_severity("HINT", "HINT")) + end) + + it('can add a prefix to diagnostics', function() + -- Default is to add a number + eq({'1. Syntax error', '2. Some warning'}, exec_lua [[ + local diagnostics = { + make_error("Syntax error", 0, 1, 0, 3), + make_warning("Some warning", 1, 1, 1, 3), + } + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header = false, number = "always"}) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]]) + + eq({'Syntax error', 'Some warning'}, exec_lua [[ + local diagnostics = { + make_error("Syntax error", 0, 1, 0, 3), + make_warning("Some warning", 1, 1, 1, 3), + } + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header = false, prefix = ""}) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]]) + + eq({'1. Syntax error', '2. Some warning'}, exec_lua [[ + local diagnostics = { + make_error("Syntax error", 0, 1, 0, 3), + make_warning("Some warning", 1, 1, 1, 3), + } + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + local float_bufnr, winnr = vim.diagnostic.open_float(0, { + show_header = false, + prefix = function(_, i, total) + -- Only show a number if there is more than one diagnostic + if total > 1 then + return string.format("%d. ", i) + end + return "" + end, + }) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]]) + + eq({'Syntax error'}, exec_lua [[ + local diagnostics = { + make_error("Syntax error", 0, 1, 0, 3), + } + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + local float_bufnr, winnr = vim.diagnostic.open_float(0, { + show_header = false, + prefix = function(_, i, total) + -- Only show a number if there is more than one diagnostic + if total > 1 then + return string.format("%d. ", i) + end + return "" + end, + }) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]]) + + eq("Error executing lua: .../diagnostic.lua:0: prefix: expected 'string' or 'function', got 42", + pcall_err(exec_lua, [[ vim.diagnostic.open_float(0, { prefix = 42 }) ]])) + end) end) describe('setloclist()', function() @@ -1243,4 +1520,73 @@ describe('vim.diagnostic', function() eq(result[1], result[2]) end) end) + + describe('handlers', function() + it('checks that a new handler is a table', function() + matches([[.*handler: expected table, got string.*]], pcall_err(exec_lua, [[ vim.diagnostic.handlers.foo = "bar" ]])) + matches([[.*handler: expected table, got function.*]], pcall_err(exec_lua, [[ vim.diagnostic.handlers.foo = function() end ]])) + end) + + it('can add new handlers', function() + eq(true, exec_lua [[ + local handler_called = false + vim.diagnostic.handlers.test = { + show = function(namespace, bufnr, diagnostics, opts) + assert(namespace == diagnostic_ns) + assert(bufnr == diagnostic_bufnr) + assert(#diagnostics == 1) + assert(opts.test.some_opt == 42) + handler_called = true + end, + } + + vim.diagnostic.config({test = {some_opt = 42}}) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_warning("Warning", 0, 0, 0, 0), + }) + return handler_called + ]]) + end) + + it('can disable handlers by setting the corresponding option to false', function() + eq(false, exec_lua [[ + local handler_called = false + vim.diagnostic.handlers.test = { + show = function(namespace, bufnr, diagnostics, opts) + handler_called = true + end, + } + + vim.diagnostic.config({test = false}) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_warning("Warning", 0, 0, 0, 0), + }) + return handler_called + ]]) + end) + + it('always calls a handler\'s hide function if defined', function() + eq({false, true}, exec_lua [[ + local hide_called = false + local show_called = false + vim.diagnostic.handlers.test = { + show = function(namespace, bufnr, diagnostics, opts) + show_called = true + end, + hide = function(namespace, bufnr) + assert(namespace == diagnostic_ns) + assert(bufnr == diagnostic_bufnr) + hide_called = true + end, + } + + vim.diagnostic.config({test = false}) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_warning("Warning", 0, 0, 0, 0), + }) + vim.diagnostic.hide(diagnostic_ns, diagnostic_bufnr) + return {show_called, hide_called} + ]]) + end) + end) end) diff --git a/test/functional/lua/loop_spec.lua b/test/functional/lua/loop_spec.lua index 992d1666f6..7f3787d7bf 100644 --- a/test/functional/lua/loop_spec.lua +++ b/test/functional/lua/loop_spec.lua @@ -84,14 +84,14 @@ describe('vim.loop', function() screen:expect([[ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| {2: }| {3:Error executing luv callback:} | {3:[string "<nvim>"]:5: E5560: nvim_set_var must not }| {3:be called in a lua loop callback} | + {3:stack traceback:} | + {3: [C]: in function 'nvim_set_var'} | + {3: [string "<nvim>"]:5: in function <[string }| + {3:"<nvim>"]:2>} | {4:Press ENTER or type command to continue}^ | ]]) feed('<cr>') diff --git a/test/functional/lua/luaeval_spec.lua b/test/functional/lua/luaeval_spec.lua index 0675ec9abd..c543dd1995 100644 --- a/test/functional/lua/luaeval_spec.lua +++ b/test/functional/lua/luaeval_spec.lua @@ -4,6 +4,7 @@ local Screen = require('test.functional.ui.screen') local pcall_err = helpers.pcall_err local exc_exec = helpers.exc_exec +local remove_trace = helpers.remove_trace local exec_lua = helpers.exec_lua local command = helpers.command local meths = helpers.meths @@ -424,11 +425,11 @@ describe('luaeval()', function() it('errors out correctly when doing incorrect things in lua', function() -- Conversion errors eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: attempt to call field \'xxx_nonexistent_key_xxx\' (a nil value)', - exc_exec([[call luaeval("vim.xxx_nonexistent_key_xxx()")]])) + remove_trace(exc_exec([[call luaeval("vim.xxx_nonexistent_key_xxx()")]]))) eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: ERROR', - exc_exec([[call luaeval("error('ERROR')")]])) + remove_trace(exc_exec([[call luaeval("error('ERROR')")]]))) eq('Vim(call):E5108: Error executing lua [NULL]', - exc_exec([[call luaeval("error(nil)")]])) + remove_trace(exc_exec([[call luaeval("error(nil)")]]))) end) it('does not leak memory when called with too long line', @@ -527,6 +528,12 @@ describe('v:lua', function() ]]} end) + it('supports packages', function() + command('set pp+=test/functional/fixtures') + eq('\tbadval', eval("v:lua.require'leftpad'('badval')")) + eq(9003, eval("v:lua.require'bar'.doit()")) + end) + it('throw errors for invalid use', function() eq('Vim(let):E15: Invalid expression: v:lua.func', pcall_err(command, "let g:Func = v:lua.func")) eq('Vim(let):E15: Invalid expression: v:lua', pcall_err(command, "let g:Func = v:lua")) diff --git a/test/functional/lua/mpack_spec.lua b/test/functional/lua/mpack_spec.lua index ef693f01f3..cc788ed8bb 100644 --- a/test/functional/lua/mpack_spec.lua +++ b/test/functional/lua/mpack_spec.lua @@ -7,16 +7,16 @@ local exec_lua = helpers.exec_lua describe('lua vim.mpack', function() before_each(clear) - it('can pack vim.NIL', function() + it('encodes vim.NIL', function() eq({true, true, true, true}, exec_lua [[ - local var = vim.mpack.unpack(vim.mpack.pack({33, vim.NIL, 77})) + local var = vim.mpack.decode(vim.mpack.encode({33, vim.NIL, 77})) return {var[1]==33, var[2]==vim.NIL, var[3]==77, var[4]==nil} ]]) end) - it('can pack vim.empty_dict()', function() + it('encodes vim.empty_dict()', function() eq({{{}, "foo", {}}, true, false}, exec_lua [[ - local var = vim.mpack.unpack(vim.mpack.pack({{}, "foo", vim.empty_dict()})) + local var = vim.mpack.decode(vim.mpack.encode({{}, "foo", vim.empty_dict()})) return {var, vim.tbl_islist(var[1]), vim.tbl_islist(var[3])} ]]) end) diff --git a/test/functional/lua/overrides_spec.lua b/test/functional/lua/overrides_spec.lua index 636479b81f..b0712ff366 100644 --- a/test/functional/lua/overrides_spec.lua +++ b/test/functional/lua/overrides_spec.lua @@ -161,15 +161,15 @@ describe('debug.debug', function() {0:~ }| {0:~ }| {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| nil | lua_debug> print("TEST") | TEST | | {E:E5108: Error executing lua [string ":lua"]:5: attempt}| {E: to perform arithmetic on local 'a' (a nil value)} | + {E:stack traceback:} | + {E: [string ":lua"]:5: in function 'Test'} | + {E: [string ":lua"]:1: in main chunk} | Interrupt: {cr:Press ENTER or type command to continue}^ | ]]} feed('<C-l>:lua Test()\n') @@ -197,13 +197,13 @@ describe('debug.debug', function() {0:~ }| {0:~ }| {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| nil | lua_debug> | {E:E5108: Error executing lua [string ":lua"]:5: attempt}| {E: to perform arithmetic on local 'a' (a nil value)} | + {E:stack traceback:} | + {E: [string ":lua"]:5: in function 'Test'} | + {E: [string ":lua"]:1: in main chunk} | {cr:Press ENTER or type command to continue}^ | ]]} end) diff --git a/test/functional/lua/ui_spec.lua b/test/functional/lua/ui_spec.lua index 94f1b5840b..2371939204 100644 --- a/test/functional/lua/ui_spec.lua +++ b/test/functional/lua/ui_spec.lua @@ -43,4 +43,29 @@ describe('vim.ui', function() }, result[2]) end) end) + + describe('input', function() + it('can input text', function() + local result = exec_lua[[ + local opts = { + prompt = 'Input: ', + } + local input + local cb = function(item) + input = item + end + -- input would require input and block the test; + local prompt + vim.fn.input = function(opts) + prompt = opts.prompt + return "Inputted text" + end + vim.ui.input(opts, cb) + vim.wait(100, function() return input ~= nil end) + return {input, prompt} + ]] + eq('Inputted text', result[1]) + eq('Input: ', result[2]) + end) + end) end) diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index a739992611..3832d27a22 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -4,7 +4,6 @@ local Screen = require('test.functional.ui.screen') local funcs = helpers.funcs local meths = helpers.meths -local dedent = helpers.dedent local command = helpers.command local insert = helpers.insert local clear = helpers.clear @@ -19,6 +18,7 @@ local source = helpers.source local NIL = helpers.NIL local retry = helpers.retry local next_msg = helpers.next_msg +local remove_trace = helpers.remove_trace before_each(clear) @@ -121,11 +121,6 @@ describe('lua stdlib', function() eq(1, funcs.luaeval('vim.stricmp("\\0C\\0", "\\0B\\0")')) end) - -- for brevity, match only the error header (not the traceback) - local function pcall_header(...) - return string.gsub(string.gsub(pcall_err(exec_lua, ...), '[\r\n].*', ''), '^Error executing lua: ', '') - end - it('vim.startswith', function() eq(true, funcs.luaeval('vim.startswith("123", "1")')) eq(true, funcs.luaeval('vim.startswith("123", "")')) @@ -136,8 +131,10 @@ describe('lua stdlib', function() eq(false, funcs.luaeval('vim.startswith("123", "2")')) eq(false, funcs.luaeval('vim.startswith("123", "1234")')) - eq("vim/shared.lua:0: prefix: expected string, got nil", pcall_header 'return vim.startswith("123", nil)') - eq("vim/shared.lua:0: s: expected string, got nil", pcall_header 'return vim.startswith(nil, "123")') + eq("Error executing lua: vim/shared.lua:0: prefix: expected string, got nil", + pcall_err(exec_lua, 'return vim.startswith("123", nil)')) + eq("Error executing lua: vim/shared.lua:0: s: expected string, got nil", + pcall_err(exec_lua, 'return vim.startswith(nil, "123")')) end) it('vim.endswith', function() @@ -150,8 +147,10 @@ describe('lua stdlib', function() eq(false, funcs.luaeval('vim.endswith("123", "2")')) eq(false, funcs.luaeval('vim.endswith("123", "1234")')) - eq("vim/shared.lua:0: suffix: expected string, got nil", pcall_header 'return vim.endswith("123", nil)') - eq("vim/shared.lua:0: s: expected string, got nil", pcall_header 'return vim.endswith(nil, "123")') + eq("Error executing lua: vim/shared.lua:0: suffix: expected string, got nil", + pcall_err(exec_lua, 'return vim.endswith("123", nil)')) + eq("Error executing lua: vim/shared.lua:0: s: expected string, got nil", + pcall_err(exec_lua, 'return vim.endswith(nil, "123")')) end) it("vim.str_utfindex/str_byteindex", function() @@ -179,6 +178,37 @@ describe('lua stdlib', function() end end) + it("vim.str_utf_start", function() + exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 å بِيَّ"]]) + local expected_positions = {0,0,0,0,-1,0,-1,0,-1,0,0,-1,0,0,-1,-2,0,-1,-2,0,0,-1,-2,0,0,-1,-2,-3,0,0,-1,-2,-3,0,0,0,-1,0,0,-1,0,-1,0,-1,0,-1,0,-1} + eq(expected_positions, exec_lua([[ + local start_codepoint_positions = {} + for idx = 1, #_G.test_text do + table.insert(start_codepoint_positions, vim.str_utf_start(_G.test_text, idx)) + end + return start_codepoint_positions + ]])) + end) + + it("vim.str_utf_end", function() + exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 å بِيَّ"]]) + local expected_positions = {0,0,0,1,0,1,0,1,0,0,1,0,0,2,1,0,2,1,0,0,2,1,0,0,3,2,1,0,0,3,2,1,0,0,0,1,0,0,1,0,1,0,1,0,1,0,1,0 } + eq(expected_positions, exec_lua([[ + local end_codepoint_positions = {} + for idx = 1, #_G.test_text do + table.insert(end_codepoint_positions, vim.str_utf_end(_G.test_text, idx)) + end + return end_codepoint_positions + ]])) + end) + + + it("vim.str_utf_pos", function() + exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 å بِيَّ"]]) + local expected_positions = { 1,2,3,4,6,8,10,11,13,14,17,20,21,24,25,29,30,34,35,36,38,39,41,43,45,47 } + eq(expected_positions, exec_lua("return vim.str_utf_pos(_G.test_text)")) + end) + it("vim.schedule", function() exec_lua([[ test_table = {} @@ -202,7 +232,7 @@ describe('lua stdlib', function() ]]) feed("<cr>") - eq('Error executing vim.schedule lua callback: [string "<nvim>"]:2: big failure\nvery async', eval("v:errmsg")) + eq('Error executing vim.schedule lua callback: [string "<nvim>"]:2: big failure\nvery async', remove_trace(eval("v:errmsg"))) local screen = Screen.new(60,5) screen:set_default_attr_ids({ @@ -228,10 +258,10 @@ describe('lua stdlib', function() end) ]]) screen:expect{grid=[[ - | - {2: }| - {3:Error executing vim.schedule lua callback: [string "<nvim>"]}| - {3::2: Vim(echo):E115: Missing quote: 'err} | + {3:stack traceback:} | + {3: [C]: in function 'nvim_command'} | + {3: [string "<nvim>"]:2: in function <[string "<nvim>"]:}| + {3:1>} | {4:Press ENTER or type command to continue}^ | ]]} end) @@ -275,22 +305,11 @@ describe('lua stdlib', function() -- Validates args. eq(true, pcall(split, 'string', 'string')) - eq(dedent([[ - Error executing lua: vim/shared.lua:0: s: expected string, got number - stack traceback: - vim/shared.lua:0: in function 'gsplit' - vim/shared.lua:0: in function <vim/shared.lua:0>]]), + eq('Error executing lua: vim/shared.lua:0: s: expected string, got number', pcall_err(split, 1, 'string')) - eq(dedent([[ - Error executing lua: vim/shared.lua:0: sep: expected string, got number - stack traceback: - vim/shared.lua:0: in function 'gsplit' - vim/shared.lua:0: in function <vim/shared.lua:0>]]), + eq('Error executing lua: vim/shared.lua:0: sep: expected string, got number', pcall_err(split, 'string', 1)) - eq(dedent([[ - Error executing lua: vim/shared.lua:0: kwargs: expected table, got number - stack traceback: - vim/shared.lua:0: in function <vim/shared.lua:0>]]), + eq('Error executing lua: vim/shared.lua:0: kwargs: expected table, got number', pcall_err(split, 'string', 'string', 1)) end) @@ -311,10 +330,7 @@ describe('lua stdlib', function() end -- Validates args. - eq(dedent([[ - Error executing lua: vim/shared.lua:0: s: expected string, got number - stack traceback: - vim/shared.lua:0: in function <vim/shared.lua:0>]]), + eq('Error executing lua: vim/shared.lua:0: s: expected string, got number', pcall_err(trim, 2)) end) @@ -393,10 +409,7 @@ describe('lua stdlib', function() eq('foo%%%-bar', exec_lua([[return vim.pesc(vim.pesc('foo-bar'))]])) -- Validates args. - eq(dedent([[ - Error executing lua: vim/shared.lua:0: s: expected string, got number - stack traceback: - vim/shared.lua:0: in function <vim/shared.lua:0>]]), + eq('Error executing lua: vim/shared.lua:0: s: expected string, got number', pcall_err(exec_lua, [[return vim.pesc(2)]])) end) @@ -679,10 +692,7 @@ describe('lua stdlib', function() it('vim.list_extend', function() eq({1,2,3}, exec_lua [[ return vim.list_extend({1}, {2,3}) ]]) - eq(dedent([[ - Error executing lua: vim/shared.lua:0: src: expected table, got nil - stack traceback: - vim/shared.lua:0: in function <vim/shared.lua:0>]]), + eq('Error executing lua: vim/shared.lua:0: src: expected table, got nil', pcall_err(exec_lua, [[ return vim.list_extend({1}, nil) ]])) eq({1,2}, exec_lua [[ return vim.list_extend({1}, {2;a=1}) ]]) eq(true, exec_lua [[ local a = {1} return vim.list_extend(a, {2;a=1}) == a ]]) @@ -814,12 +824,12 @@ describe('lua stdlib', function() end) ]]) screen:expect{grid=[[ - foo | - {1:~ }| - {2: }| - {3:Error executing luv callback:} | {3:[string "<nvim>"]:6: E5560: rpcrequest must not be}| {3: called in a lua loop callback} | + {3:stack traceback:} | + {3: [C]: in function 'rpcrequest'} | + {3: [string "<nvim>"]:6: in function <[string }| + {3:"<nvim>"]:2>} | {4:Press ENTER or type command to continue}^ | ]]} feed('<cr>') @@ -883,76 +893,37 @@ describe('lua stdlib', function() exec_lua("vim.validate{arg1={{}, 't' }, arg2={ 'foo', 's' }}") exec_lua("vim.validate{arg1={2, function(a) return (a % 2) == 0 end, 'even number' }}") - eq(dedent([[ - Error executing lua: [string "<nvim>"]:0: opt[1]: expected table, got number - stack traceback: - [string "<nvim>"]:0: in main chunk]]), + eq('Error executing lua: [string "<nvim>"]:0: opt[1]: expected table, got number', pcall_err(exec_lua, "vim.validate{ 1, 'x' }")) - eq(dedent([[ - Error executing lua: [string "<nvim>"]:0: invalid type name: x - stack traceback: - [string "<nvim>"]:0: in main chunk]]), + eq('Error executing lua: [string "<nvim>"]:0: invalid type name: x', pcall_err(exec_lua, "vim.validate{ arg1={ 1, 'x' }}")) - eq(dedent([[ - Error executing lua: [string "<nvim>"]:0: invalid type name: 1 - stack traceback: - [string "<nvim>"]:0: in main chunk]]), + eq('Error executing lua: [string "<nvim>"]:0: invalid type name: 1', pcall_err(exec_lua, "vim.validate{ arg1={ 1, 1 }}")) - eq(dedent([[ - Error executing lua: [string "<nvim>"]:0: invalid type name: nil - stack traceback: - [string "<nvim>"]:0: in main chunk]]), + eq('Error executing lua: [string "<nvim>"]:0: invalid type name: nil', pcall_err(exec_lua, "vim.validate{ arg1={ 1 }}")) -- Validated parameters are required by default. - eq(dedent([[ - Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil - stack traceback: - [string "<nvim>"]:0: in main chunk]]), + eq('Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil', pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's' }}")) -- Explicitly required. - eq(dedent([[ - Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil - stack traceback: - [string "<nvim>"]:0: in main chunk]]), + eq('Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil', pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's', false }}")) - eq(dedent([[ - Error executing lua: [string "<nvim>"]:0: arg1: expected table, got number - stack traceback: - [string "<nvim>"]:0: in main chunk]]), + eq('Error executing lua: [string "<nvim>"]:0: arg1: expected table, got number', pcall_err(exec_lua, "vim.validate{arg1={1, 't'}}")) - eq(dedent([[ - Error executing lua: [string "<nvim>"]:0: arg2: expected string, got number - stack traceback: - [string "<nvim>"]:0: in main chunk]]), + eq('Error executing lua: [string "<nvim>"]:0: arg2: expected string, got number', pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={1, 's'}}")) - eq(dedent([[ - Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil - stack traceback: - [string "<nvim>"]:0: in main chunk]]), + eq('Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil', pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}")) - eq(dedent([[ - Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil - stack traceback: - [string "<nvim>"]:0: in main chunk]]), + eq('Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil', pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}")) - eq(dedent([[ - Error executing lua: [string "<nvim>"]:0: arg1: expected even number, got 3 - stack traceback: - [string "<nvim>"]:0: in main chunk]]), + eq('Error executing lua: [string "<nvim>"]:0: arg1: expected even number, got 3', pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end, 'even number'}}")) - eq(dedent([[ - Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3 - stack traceback: - [string "<nvim>"]:0: in main chunk]]), + eq('Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3', pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end}}")) -- Pass an additional message back. - eq(dedent([[ - Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3. Info: TEST_MSG - stack traceback: - [string "<nvim>"]:0: in main chunk]]), + eq('Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3. Info: TEST_MSG', pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1, 'TEST_MSG' end}}")) end) @@ -996,6 +967,9 @@ describe('lua stdlib', function() vim.g.to_delete = nil ]] eq(NIL, funcs.luaeval "vim.g.to_delete") + + matches([[^Error executing lua: .*: attempt to index .* nil value]], + pcall_err(exec_lua, 'return vim.g[0].testing')) end) it('vim.b', function() @@ -1005,18 +979,25 @@ describe('lua stdlib', function() vim.api.nvim_buf_set_var(0, "floaty", 5120.1) vim.api.nvim_buf_set_var(0, "nullvar", vim.NIL) vim.api.nvim_buf_set_var(0, "to_delete", {hello="world"}) + BUF = vim.api.nvim_create_buf(false, true) + vim.api.nvim_buf_set_var(BUF, "testing", "bye") ]] eq('hi', funcs.luaeval "vim.b.testing") + eq('bye', funcs.luaeval "vim.b[BUF].testing") eq(123, funcs.luaeval "vim.b.other") eq(5120.1, funcs.luaeval "vim.b.floaty") eq(NIL, funcs.luaeval "vim.b.nonexistant") + eq(NIL, funcs.luaeval "vim.b[BUF].nonexistant") eq(NIL, funcs.luaeval "vim.b.nullvar") -- lost over RPC, so test locally: eq({false, true}, exec_lua [[ return {vim.b.nonexistant == vim.NIL, vim.b.nullvar == vim.NIL} ]]) + matches([[^Error executing lua: .*: attempt to index .* nil value]], + pcall_err(exec_lua, 'return vim.b[BUF][0].testing')) + eq({hello="world"}, funcs.luaeval "vim.b.to_delete") exec_lua [[ vim.b.to_delete = nil @@ -1037,11 +1018,22 @@ describe('lua stdlib', function() vim.api.nvim_win_set_var(0, "testing", "hi") vim.api.nvim_win_set_var(0, "other", 123) vim.api.nvim_win_set_var(0, "to_delete", {hello="world"}) + BUF = vim.api.nvim_create_buf(false, true) + WIN = vim.api.nvim_open_win(BUF, false, { + width=10, height=10, + relative='win', row=0, col=0 + }) + vim.api.nvim_win_set_var(WIN, "testing", "bye") ]] eq('hi', funcs.luaeval "vim.w.testing") + eq('bye', funcs.luaeval "vim.w[WIN].testing") eq(123, funcs.luaeval "vim.w.other") eq(NIL, funcs.luaeval "vim.w.nonexistant") + eq(NIL, funcs.luaeval "vim.w[WIN].nonexistant") + + matches([[^Error executing lua: .*: attempt to index .* nil value]], + pcall_err(exec_lua, 'return vim.w[WIN][0].testing')) eq({hello="world"}, funcs.luaeval "vim.w.to_delete") exec_lua [[ @@ -1068,6 +1060,12 @@ describe('lua stdlib', function() eq('hi', funcs.luaeval "vim.t.testing") eq(123, funcs.luaeval "vim.t.other") eq(NIL, funcs.luaeval "vim.t.nonexistant") + eq('hi', funcs.luaeval "vim.t[0].testing") + eq(123, funcs.luaeval "vim.t[0].other") + eq(NIL, funcs.luaeval "vim.t[0].nonexistant") + + matches([[^Error executing lua: .*: attempt to index .* nil value]], + pcall_err(exec_lua, 'return vim.t[0][0].testing')) eq({hello="world"}, funcs.luaeval "vim.t.to_delete") exec_lua [[ @@ -1096,6 +1094,8 @@ describe('lua stdlib', function() eq(funcs.luaeval "vim.api.nvim_get_vvar('progpath')", funcs.luaeval "vim.v.progpath") eq(false, funcs.luaeval "vim.v['false']") eq(NIL, funcs.luaeval "vim.v.null") + matches([[^Error executing lua: .*: attempt to index .* nil value]], + pcall_err(exec_lua, 'return vim.v[0].progpath')) end) it('vim.bo', function() @@ -2030,6 +2030,8 @@ describe('lua stdlib', function() -- Would wait ten seconds if results blocked. wait_result = vim.wait(10000, function() return vim.g.timer_result end) + timer:close() + return { time = (start_time + 5) > get_time(), wait_result = wait_result, @@ -2049,6 +2051,8 @@ describe('lua stdlib', function() wait_result = vim.wait(300, function() return vim.g.timer_result end, nil, true) + timer:close() + return { wait_result = wait_result, } @@ -2069,9 +2073,10 @@ describe('lua stdlib', function() end) it('should not crash when callback errors', function() - eq({false, '[string "<nvim>"]:1: As Expected'}, exec_lua [[ + local result = exec_lua [[ return {pcall(function() vim.wait(1000, function() error("As Expected") end) end)} - ]]) + ]] + eq({false, '[string "<nvim>"]:1: As Expected'}, {result[1], remove_trace(result[2])}) end) it('if callback is passed, it must be a function', function() diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua index b84e9d1533..b567b3e20c 100644 --- a/test/functional/plugin/health_spec.lua +++ b/test/functional/plugin/health_spec.lua @@ -134,7 +134,7 @@ describe('health.vim', function() command("checkhealth test_plug*") local buf_lines = helpers.curbuf('get_lines', 0, -1, true) -- avoid dealing with path separators - local received = table.concat(buf_lines, '\n', 1, #buf_lines - 2) + local received = table.concat(buf_lines, '\n', 1, #buf_lines - 5) local expected = helpers.dedent([[ test_plug: require("test_plug.health").check() @@ -175,10 +175,10 @@ describe('health.vim', function() it("gracefully handles broken lua healthcheck", function() command("checkhealth test_plug.submodule_failed") local buf_lines = helpers.curbuf('get_lines', 0, -1, true) - local received = table.concat(buf_lines, '\n', 1, #buf_lines - 2) + local received = table.concat(buf_lines, '\n', 1, #buf_lines - 5) -- avoid dealing with path separators local lua_err = "attempt to perform arithmetic on a nil value" - local last_line = buf_lines[#buf_lines - 1] + local last_line = buf_lines[#buf_lines - 4] assert(string.find(last_line, lua_err) ~= nil, "Lua error not present") local expected = global_helpers.dedent([[ diff --git a/test/functional/plugin/lsp/codelens_spec.lua b/test/functional/plugin/lsp/codelens_spec.lua index c8b75e65fc..ecc2f579b8 100644 --- a/test/functional/plugin/lsp/codelens_spec.lua +++ b/test/functional/plugin/lsp/codelens_spec.lua @@ -60,31 +60,4 @@ describe('vim.lsp.codelens', function() eq({[1] = {'Lens1', 'LspCodeLens'}}, virtual_text_chunks) end) - it('codelens uses client commands', function() - local fake_uri = "file:///fake/uri" - local cmd = exec_lua([[ - fake_uri = ... - local bufnr = vim.uri_to_bufnr(fake_uri) - vim.fn.bufload(bufnr) - vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {'One line'}) - local lenses = { - { - range = { - start = { line = 0, character = 0, }, - ['end'] = { line = 0, character = 8 } - }, - command = { title = 'Lens1', command = 'Dummy' } - }, - } - vim.lsp.codelens.on_codelens(nil, lenses, {method='textDocument/codeLens', client_id=1, bufnr=bufnr}) - local cmd_called = nil - vim.lsp.commands['Dummy'] = function(command) - cmd_called = command - end - vim.api.nvim_set_current_buf(bufnr) - vim.lsp.codelens.run() - return cmd_called - ]], fake_uri) - eq({ command = 'Dummy', title = 'Lens1' }, cmd) - end) end) diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua index 243ad6bdb8..1269a2350c 100644 --- a/test/functional/plugin/lsp/diagnostic_spec.lua +++ b/test/functional/plugin/lsp/diagnostic_spec.lua @@ -3,7 +3,6 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local exec_lua = helpers.exec_lua local eq = helpers.eq -local nvim = helpers.nvim describe('vim.lsp.diagnostic', function() local fake_uri @@ -45,11 +44,32 @@ describe('vim.lsp.diagnostic', function() } end - count_of_extmarks_for_client = function(bufnr, client_id) - return #vim.api.nvim_buf_get_extmarks( - bufnr, vim.lsp.diagnostic.get_namespace(client_id), 0, -1, {} - ) + function get_extmarks(bufnr, client_id) + local namespace = vim.lsp.diagnostic.get_namespace(client_id) + local ns = vim.diagnostic.get_namespace(namespace) + local extmarks = {} + if ns.user_data.virt_text_ns then + for _, e in pairs(vim.api.nvim_buf_get_extmarks(bufnr, ns.user_data.virt_text_ns, 0, -1, {details=true})) do + table.insert(extmarks, e) + end + end + if ns.user_data.underline_ns then + for _, e in pairs(vim.api.nvim_buf_get_extmarks(bufnr, ns.user_data.underline_ns, 0, -1, {details=true})) do + table.insert(extmarks, e) + end + end + return extmarks end + + client_id = vim.lsp.start_client { + cmd_env = { + NVIM_LUA_NOTRACK = "1"; + }; + cmd = { + vim.v.progpath, '-es', '-u', 'NONE', '--headless' + }; + offset_encoding = "utf-16"; + } ]] fake_uri = "file:///fake/uri" @@ -69,366 +89,6 @@ describe('vim.lsp.diagnostic', function() end) describe('vim.lsp.diagnostic', function() - describe('handle_publish_diagnostics', function() - it('should be able to retrieve diagnostics from all buffers and clients', function() - local result = exec_lua [[ - vim.lsp.diagnostic.save( - { - make_error('Diagnostic #1', 1, 1, 1, 1), - make_error('Diagnostic #2', 2, 1, 2, 1), - }, 1, 1 - ) - vim.lsp.diagnostic.save( - { - make_error('Diagnostic #3', 3, 1, 3, 1), - }, 2, 2 - ) - return vim.lsp.diagnostic.get_all() - ]] - eq(2, #result) - eq(2, #result[1]) - eq('Diagnostic #1', result[1][1].message) - end) - it('should be able to save and count a single client error', function() - eq(1, exec_lua [[ - vim.lsp.diagnostic.save( - { - make_error('Diagnostic #1', 1, 1, 1, 1), - }, 0, 1 - ) - return vim.lsp.diagnostic.get_count(0, "Error", 1) - ]]) - end) - - it('should be able to save and count from two clients', function() - eq(2, exec_lua [[ - vim.lsp.diagnostic.save( - { - make_error('Diagnostic #1', 1, 1, 1, 1), - make_error('Diagnostic #2', 2, 1, 2, 1), - }, 0, 1 - ) - return vim.lsp.diagnostic.get_count(0, "Error", 1) - ]]) - end) - - it('should be able to save and count from multiple clients', function() - eq({1, 1, 2}, exec_lua [[ - vim.lsp.diagnostic.save( - { - make_error('Diagnostic From Server 1', 1, 1, 1, 1), - }, 0, 1 - ) - vim.lsp.diagnostic.save( - { - make_error('Diagnostic From Server 2', 1, 1, 1, 1), - }, 0, 2 - ) - return { - -- Server 1 - vim.lsp.diagnostic.get_count(0, "Error", 1), - -- Server 2 - vim.lsp.diagnostic.get_count(0, "Error", 2), - -- All servers - vim.lsp.diagnostic.get_count(0, "Error", nil), - } - ]]) - end) - - it('should be able to save and count from multiple clients with respect to severity', function() - eq({3, 0, 3}, exec_lua [[ - vim.lsp.diagnostic.save( - { - make_error('Diagnostic From Server 1:1', 1, 1, 1, 1), - make_error('Diagnostic From Server 1:2', 2, 2, 2, 2), - make_error('Diagnostic From Server 1:3', 2, 3, 3, 2), - }, 0, 1 - ) - vim.lsp.diagnostic.save( - { - make_warning('Warning From Server 2', 3, 3, 3, 3), - }, 0, 2 - ) - return { - -- Server 1 - vim.lsp.diagnostic.get_count(0, "Error", 1), - -- Server 2 - vim.lsp.diagnostic.get_count(0, "Error", 2), - -- All servers - vim.lsp.diagnostic.get_count(0, "Error", nil), - } - ]]) - end) - it('should handle one server clearing highlights while the other still has highlights', function() - -- 1 Error (1) - -- 1 Warning (2) - -- 1 Warning (2) + 1 Warning (1) - -- 2 highlights and 2 underlines (since error) - -- 1 highlight + 1 underline - local all_highlights = {1, 1, 2, 4, 2} - eq(all_highlights, exec_lua [[ - local server_1_diags = { - make_error("Error 1", 1, 1, 1, 5), - make_warning("Warning on Server 1", 2, 1, 2, 5), - } - local server_2_diags = { - make_warning("Warning 1", 2, 1, 2, 5), - } - - vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_1_diags }, {client_id=1}) - vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_2_diags }, {client_id=2}) - return { - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1), - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2), - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil), - count_of_extmarks_for_client(diagnostic_bufnr, 1), - count_of_extmarks_for_client(diagnostic_bufnr, 2), - } - ]]) - - -- Clear diagnostics from server 1, and make sure we have the right amount of stuff for client 2 - eq({1, 1, 2, 0, 2}, exec_lua [[ - vim.lsp.diagnostic.disable(diagnostic_bufnr, 1) - return { - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1), - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2), - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil), - count_of_extmarks_for_client(diagnostic_bufnr, 1), - count_of_extmarks_for_client(diagnostic_bufnr, 2), - } - ]]) - - -- Show diagnostics from server 1 again - eq(all_highlights, exec_lua([[ - vim.lsp.diagnostic.enable(diagnostic_bufnr, 1) - return { - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1), - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2), - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil), - count_of_extmarks_for_client(diagnostic_bufnr, 1), - count_of_extmarks_for_client(diagnostic_bufnr, 2), - } - ]])) - end) - - it('should not display diagnostics when disabled', function() - eq({0, 2}, exec_lua [[ - local server_1_diags = { - make_error("Error 1", 1, 1, 1, 5), - make_warning("Warning on Server 1", 2, 1, 2, 5), - } - local server_2_diags = { - make_warning("Warning 1", 2, 1, 2, 5), - } - - vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_1_diags }, {client_id=1}) - vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_2_diags }, {client_id=2}) - - vim.lsp.diagnostic.disable(diagnostic_bufnr, 1) - - return { - count_of_extmarks_for_client(diagnostic_bufnr, 1), - count_of_extmarks_for_client(diagnostic_bufnr, 2), - } - ]]) - - eq({4, 0}, exec_lua [[ - vim.lsp.diagnostic.enable(diagnostic_bufnr, 1) - vim.lsp.diagnostic.disable(diagnostic_bufnr, 2) - - return { - count_of_extmarks_for_client(diagnostic_bufnr, 1), - count_of_extmarks_for_client(diagnostic_bufnr, 2), - } - ]]) - end) - - describe('reset', function() - it('diagnostic count is 0 and displayed diagnostics are 0 after call', function() - -- 1 Error (1) - -- 1 Warning (2) - -- 1 Warning (2) + 1 Warning (1) - -- 2 highlights and 2 underlines (since error) - -- 1 highlight + 1 underline - local all_highlights = {1, 1, 2, 4, 2} - eq(all_highlights, exec_lua [[ - local server_1_diags = { - make_error("Error 1", 1, 1, 1, 5), - make_warning("Warning on Server 1", 2, 1, 2, 5), - } - local server_2_diags = { - make_warning("Warning 1", 2, 1, 2, 5), - } - - vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_1_diags }, {client_id=1}) - vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_2_diags }, {client_id=2}) - return { - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1), - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2), - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil), - count_of_extmarks_for_client(diagnostic_bufnr, 1), - count_of_extmarks_for_client(diagnostic_bufnr, 2), - } - ]]) - - -- Reset diagnostics from server 1 - exec_lua([[ vim.lsp.diagnostic.reset(1, { [ diagnostic_bufnr ] = { [ 1 ] = true ; [ 2 ] = true } } )]]) - - -- Make sure we have the right diagnostic count - eq({0, 1, 1, 0, 2} , exec_lua [[ - local diagnostic_count = {} - vim.wait(100, function () diagnostic_count = { - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1), - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2), - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil), - count_of_extmarks_for_client(diagnostic_bufnr, 1), - count_of_extmarks_for_client(diagnostic_bufnr, 2), - } end ) - return diagnostic_count - ]]) - - -- Reset diagnostics from server 2 - exec_lua([[ vim.lsp.diagnostic.reset(2, { [ diagnostic_bufnr ] = { [ 1 ] = true ; [ 2 ] = true } } )]]) - - -- Make sure we have the right diagnostic count - eq({0, 0, 0, 0, 0}, exec_lua [[ - local diagnostic_count = {} - vim.wait(100, function () diagnostic_count = { - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1), - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2), - vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil), - count_of_extmarks_for_client(diagnostic_bufnr, 1), - count_of_extmarks_for_client(diagnostic_bufnr, 2), - } end ) - return diagnostic_count - ]]) - - end) - end) - - describe('get_next_diagnostic_pos', function() - it('can find the next pos with only one client', function() - eq({1, 1}, exec_lua [[ - vim.lsp.diagnostic.save( - { - make_error('Diagnostic #1', 1, 1, 1, 1), - }, diagnostic_bufnr, 1 - ) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - return vim.lsp.diagnostic.get_next_pos() - ]]) - end) - - it('can find next pos with two errors', function() - eq({4, 4}, exec_lua [[ - vim.lsp.diagnostic.save( - { - make_error('Diagnostic #1', 1, 1, 1, 1), - make_error('Diagnostic #2', 4, 4, 4, 4), - }, diagnostic_bufnr, 1 - ) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {3, 1}) - return vim.lsp.diagnostic.get_next_pos { client_id = 1 } - ]]) - end) - - it('can cycle when position is past error', function() - eq({1, 1}, exec_lua [[ - vim.lsp.diagnostic.save( - { - make_error('Diagnostic #1', 1, 1, 1, 1), - }, diagnostic_bufnr, 1 - ) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {3, 1}) - return vim.lsp.diagnostic.get_next_pos { client_id = 1 } - ]]) - end) - - it('will not cycle when wrap is off', function() - eq(false, exec_lua [[ - vim.lsp.diagnostic.save( - { - make_error('Diagnostic #1', 1, 1, 1, 1), - }, diagnostic_bufnr, 1 - ) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {3, 1}) - return vim.lsp.diagnostic.get_next_pos { client_id = 1, wrap = false } - ]]) - end) - - it('can cycle even from the last line', function() - eq({4, 4}, exec_lua [[ - vim.lsp.diagnostic.save( - { - make_error('Diagnostic #2', 4, 4, 4, 4), - }, diagnostic_bufnr, 1 - ) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {vim.api.nvim_buf_line_count(0), 1}) - return vim.lsp.diagnostic.get_prev_pos { client_id = 1 } - ]]) - end) - end) - - describe('get_prev_diagnostic_pos', function() - it('can find the prev pos with only one client', function() - eq({1, 1}, exec_lua [[ - vim.lsp.diagnostic.save( - { - make_error('Diagnostic #1', 1, 1, 1, 1), - }, diagnostic_bufnr, 1 - ) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {3, 1}) - return vim.lsp.diagnostic.get_prev_pos() - ]]) - end) - - it('can find prev pos with two errors', function() - eq({1, 1}, exec_lua [[ - vim.lsp.diagnostic.save( - { - make_error('Diagnostic #1', 1, 1, 1, 1), - make_error('Diagnostic #2', 4, 4, 4, 4), - }, diagnostic_bufnr, 1 - ) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {3, 1}) - return vim.lsp.diagnostic.get_prev_pos { client_id = 1 } - ]]) - end) - - it('can cycle when position is past error', function() - eq({4, 4}, exec_lua [[ - vim.lsp.diagnostic.save( - { - make_error('Diagnostic #2', 4, 4, 4, 4), - }, diagnostic_bufnr, 1 - ) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {3, 1}) - return vim.lsp.diagnostic.get_prev_pos { client_id = 1 } - ]]) - end) - - it('respects wrap parameter', function() - eq(false, exec_lua [[ - vim.lsp.diagnostic.save( - { - make_error('Diagnostic #2', 4, 4, 4, 4), - }, diagnostic_bufnr, 1 - ) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {3, 1}) - return vim.lsp.diagnostic.get_prev_pos { client_id = 1, wrap = false} - ]]) - end) - end) - end) - it('maintains LSP information when translating diagnostics', function() local result = exec_lua [[ local diagnostics = { @@ -442,7 +102,7 @@ describe('vim.lsp.diagnostic', function() vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = diagnostics, - }, {client_id=1}) + }, {client_id=client_id}) return { vim.diagnostic.get(diagnostic_bufnr, {lnum=1})[1], @@ -456,246 +116,7 @@ describe('vim.lsp.diagnostic', function() end) end) - describe("vim.lsp.diagnostic.get_line_diagnostics", function() - it('should return an empty table when no diagnostics are present', function() - eq({}, exec_lua [[return vim.lsp.diagnostic.get_line_diagnostics(diagnostic_bufnr, 1)]]) - end) - - it('should return all diagnostics when no severity is supplied', function() - eq(2, exec_lua [[ - vim.lsp.diagnostic.on_publish_diagnostics(nil, { - uri = fake_uri, - diagnostics = { - make_error("Error 1", 1, 1, 1, 5), - make_warning("Warning on Server 1", 1, 1, 2, 5), - make_error("Error On Other Line", 2, 1, 1, 5), - } - }, {client_id=1}) - - return #vim.lsp.diagnostic.get_line_diagnostics(diagnostic_bufnr, 1) - ]]) - end) - - it('should return only requested diagnostics when severity_limit is supplied', function() - eq(2, exec_lua [[ - vim.lsp.diagnostic.on_publish_diagnostics(nil, { - uri = fake_uri, - diagnostics = { - make_error("Error 1", 1, 1, 1, 5), - make_warning("Warning on Server 1", 1, 1, 2, 5), - make_information("Ignored information", 1, 1, 2, 5), - make_error("Error On Other Line", 2, 1, 1, 5), - } - }, {client_id=1}) - - return #vim.lsp.diagnostic.get_line_diagnostics(diagnostic_bufnr, 1, { severity_limit = "Warning" }) - ]]) - end) - end) - describe("vim.lsp.diagnostic.on_publish_diagnostics", function() - it('can use functions for config values', function() - exec_lua [[ - vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { - virtual_text = function() return true end, - })(nil, { - uri = fake_uri, - diagnostics = { - make_error('Delayed Diagnostic', 4, 4, 4, 4), - } - }, {client_id=1} - ) - ]] - - eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) - eq(2, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) - - -- Now, don't enable virtual text. - -- We should have one less extmark displayed. - exec_lua [[ - vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { - virtual_text = function() return false end, - })(nil, { - uri = fake_uri, - diagnostics = { - make_error('Delayed Diagnostic', 4, 4, 4, 4), - } - }, {client_id=1} - ) - ]] - - eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) - eq(1, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) - end) - - it('can perform updates after insert_leave', function() - exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]] - nvim("input", "o") - eq({mode='i', blocking=false}, nvim("get_mode")) - - -- Save the diagnostics - exec_lua [[ - vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { - update_in_insert = false, - })(nil, { - uri = fake_uri, - diagnostics = { - make_error('Delayed Diagnostic', 4, 4, 4, 4), - } - }, {client_id=1} - ) - ]] - - -- No diagnostics displayed yet. - eq({mode='i', blocking=false}, nvim("get_mode")) - eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) - eq(0, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) - - nvim("input", "<esc>") - eq({mode='n', blocking=false}, nvim("get_mode")) - - eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) - eq(2, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) - end) - - it('does not perform updates when not needed', function() - exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]] - nvim("input", "o") - eq({mode='i', blocking=false}, nvim("get_mode")) - - -- Save the diagnostics - exec_lua [[ - PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { - update_in_insert = false, - virtual_text = true, - }) - - -- Count how many times we call display. - SetVirtualTextOriginal = vim.diagnostic._set_virtual_text - - DisplayCount = 0 - vim.diagnostic._set_virtual_text = function(...) - DisplayCount = DisplayCount + 1 - return SetVirtualTextOriginal(...) - end - - PublishDiagnostics(nil, { - uri = fake_uri, - diagnostics = { - make_error('Delayed Diagnostic', 4, 4, 4, 4), - } - }, {client_id=1} - ) - ]] - - -- No diagnostics displayed yet. - eq({mode='i', blocking=false}, nvim("get_mode")) - eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) - eq(0, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) - eq(0, exec_lua [[return DisplayCount]]) - - nvim("input", "<esc>") - eq({mode='n', blocking=false}, nvim("get_mode")) - - eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) - eq(2, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) - eq(1, exec_lua [[return DisplayCount]]) - - -- Go in and out of insert mode one more time. - nvim("input", "o") - eq({mode='i', blocking=false}, nvim("get_mode")) - - nvim("input", "<esc>") - eq({mode='n', blocking=false}, nvim("get_mode")) - - -- Should not have set the virtual text again. - eq(1, exec_lua [[return DisplayCount]]) - end) - - it('never sets virtual text, in combination with insert leave', function() - exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]] - nvim("input", "o") - eq({mode='i', blocking=false}, nvim("get_mode")) - - -- Save the diagnostics - exec_lua [[ - PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { - update_in_insert = false, - virtual_text = false, - }) - - -- Count how many times we call display. - SetVirtualTextOriginal = vim.lsp.diagnostic.set_virtual_text - - DisplayCount = 0 - vim.lsp.diagnostic.set_virtual_text = function(...) - DisplayCount = DisplayCount + 1 - return SetVirtualTextOriginal(...) - end - - PublishDiagnostics(nil, { - uri = fake_uri, - diagnostics = { - make_error('Delayed Diagnostic', 4, 4, 4, 4), - } - }, {client_id=1} - ) - ]] - - -- No diagnostics displayed yet. - eq({mode='i', blocking=false}, nvim("get_mode")) - eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) - eq(0, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) - eq(0, exec_lua [[return DisplayCount]]) - - nvim("input", "<esc>") - eq({mode='n', blocking=false}, nvim("get_mode")) - - eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) - eq(1, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) - eq(0, exec_lua [[return DisplayCount]]) - - -- Go in and out of insert mode one more time. - nvim("input", "o") - eq({mode='i', blocking=false}, nvim("get_mode")) - - nvim("input", "<esc>") - eq({mode='n', blocking=false}, nvim("get_mode")) - - -- Should not have set the virtual text still. - eq(0, exec_lua [[return DisplayCount]]) - end) - - it('can perform updates while in insert mode, if desired', function() - exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]] - nvim("input", "o") - eq({mode='i', blocking=false}, nvim("get_mode")) - - -- Save the diagnostics - exec_lua [[ - vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { - update_in_insert = true, - })(nil, { - uri = fake_uri, - diagnostics = { - make_error('Delayed Diagnostic', 4, 4, 4, 4), - } - }, {client_id=1} - ) - ]] - - -- Diagnostics are displayed, because the user wanted them that way! - eq({mode='i', blocking=false}, nvim("get_mode")) - eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) - eq(2, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) - - nvim("input", "<esc>") - eq({mode='n', blocking=false}, nvim("get_mode")) - - eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) - eq(2, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) - end) - it('allows configuring the virtual text via vim.lsp.with', function() local expected_spacing = 10 local extmarks = exec_lua([[ @@ -710,16 +131,10 @@ describe('vim.lsp.diagnostic', function() diagnostics = { make_error('Delayed Diagnostic', 4, 4, 4, 4), } - }, {client_id=1} + }, {client_id=client_id} ) - return vim.api.nvim_buf_get_extmarks( - diagnostic_bufnr, - vim.lsp.diagnostic.get_namespace(1), - 0, - -1, - { details = true } - ) + return get_extmarks(diagnostic_bufnr, client_id) ]], expected_spacing) local virt_text = extmarks[1][4].virt_text @@ -728,7 +143,6 @@ describe('vim.lsp.diagnostic', function() eq(expected_spacing, #spacing) end) - it('allows configuring the virtual text via vim.lsp.with using a function', function() local expected_spacing = 10 local extmarks = exec_lua([[ @@ -747,16 +161,10 @@ describe('vim.lsp.diagnostic', function() diagnostics = { make_error('Delayed Diagnostic', 4, 4, 4, 4), } - }, {client_id=1} + }, {client_id=client_id} ) - return vim.api.nvim_buf_get_extmarks( - diagnostic_bufnr, - vim.lsp.diagnostic.get_namespace(1), - 0, - -1, - { details = true } - ) + return get_extmarks(diagnostic_bufnr, client_id) ]], expected_spacing) local virt_text = extmarks[1][4].virt_text @@ -780,10 +188,10 @@ describe('vim.lsp.diagnostic', function() diagnostics = { make_warning('Delayed Diagnostic', 4, 4, 4, 4), } - }, {client_id=1} + }, {client_id=client_id} ) - return count_of_extmarks_for_client(diagnostic_bufnr, 1) + return #get_extmarks(diagnostic_bufnr, client_id) ]], severity_limit) end @@ -799,16 +207,6 @@ describe('vim.lsp.diagnostic', function() local line = "All 💼 and no 🎉 makes Jack a dull 👦" local result = exec_lua([[ local line = ... - local client_id = vim.lsp.start_client { - cmd_env = { - NVIM_LUA_NOTRACK = "1"; - }; - cmd = { - vim.v.progpath, '-es', '-u', 'NONE', '--headless' - }; - offset_encoding = "utf-16"; - } - vim.api.nvim_buf_set_lines(diagnostic_bufnr, 0, -1, false, {line}) vim.lsp.diagnostic.on_publish_diagnostics(nil, { @@ -829,145 +227,4 @@ describe('vim.lsp.diagnostic', function() eq(exec_lua([[return vim.str_byteindex(..., 8, true)]], line), result[1].end_col) end) end) - - describe('lsp.util.show_line_diagnostics', function() - it('creates floating window and returns popup bufnr and winnr if current line contains diagnostics', function() - -- Two lines: - -- Diagnostic: - -- 1. <msg> - eq(2, exec_lua [[ - local buffer = vim.api.nvim_create_buf(false, true) - vim.api.nvim_buf_set_lines(buffer, 0, -1, false, { - "testing"; - "123"; - }) - local diagnostics = { - { - range = { - start = { line = 0; character = 1; }; - ["end"] = { line = 0; character = 3; }; - }; - severity = vim.lsp.protocol.DiagnosticSeverity.Error; - message = "Syntax error"; - }, - } - vim.api.nvim_win_set_buf(0, buffer) - vim.lsp.diagnostic.save(diagnostics, buffer, 1) - local popup_bufnr, winnr = vim.lsp.diagnostic.show_line_diagnostics() - return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false) - ]]) - end) - - it('creates floating window and returns popup bufnr and winnr without header, if requested', function() - -- One line (since no header): - -- 1. <msg> - eq(1, exec_lua [[ - local buffer = vim.api.nvim_create_buf(false, true) - vim.api.nvim_buf_set_lines(buffer, 0, -1, false, { - "testing"; - "123"; - }) - local diagnostics = { - { - range = { - start = { line = 0; character = 1; }; - ["end"] = { line = 0; character = 3; }; - }; - severity = vim.lsp.protocol.DiagnosticSeverity.Error; - message = "Syntax error"; - }, - } - vim.api.nvim_win_set_buf(0, buffer) - vim.lsp.diagnostic.save(diagnostics, buffer, 1) - local popup_bufnr, winnr = vim.lsp.diagnostic.show_line_diagnostics { show_header = false } - return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false) - ]]) - end) - end) - - describe('set_signs', function() - -- TODO(tjdevries): Find out why signs are not displayed when set from Lua...?? - pending('sets signs by default', function() - exec_lua [[ - PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { - update_in_insert = true, - signs = true, - }) - - local diagnostics = { - make_error('Delayed Diagnostic', 1, 1, 1, 2), - make_error('Delayed Diagnostic', 3, 3, 3, 3), - } - - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.lsp.diagnostic.on_publish_diagnostics(nil, { - uri = fake_uri, - diagnostics = diagnostics - }, {client_id=1} - ) - - vim.lsp.diagnostic.set_signs(diagnostics, diagnostic_bufnr, 1) - -- return vim.fn.sign_getplaced() - ]] - - nvim("input", "o") - nvim("input", "<esc>") - - -- TODO(tjdevries): Find a way to get the signs to display in the test... - eq(nil, exec_lua [[ - return im.fn.sign_getplaced()[1].signs - ]]) - end) - end) - - describe('set_loclist()', function() - it('sets diagnostics in lnum order', function() - local loc_list = exec_lua [[ - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - - vim.lsp.diagnostic.on_publish_diagnostics(nil, { - uri = fake_uri, - diagnostics = { - make_error('Farther Diagnostic', 4, 4, 4, 4), - make_error('Lower Diagnostic', 1, 1, 1, 1), - } - }, {client_id=1} - ) - - vim.lsp.diagnostic.set_loclist() - - return vim.fn.getloclist(0) - ]] - - assert(loc_list[1].lnum < loc_list[2].lnum) - end) - - it('sets diagnostics in lnum order, regardless of client', function() - local loc_list = exec_lua [[ - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - - vim.lsp.diagnostic.on_publish_diagnostics(nil, { - uri = fake_uri, - diagnostics = { - make_error('Lower Diagnostic', 1, 1, 1, 1), - } - }, {client_id=1} - ) - - vim.lsp.diagnostic.on_publish_diagnostics(nil, { - uri = fake_uri, - diagnostics = { - make_warning('Farther Diagnostic', 4, 4, 4, 4), - } - }, {client_id=2} - ) - - vim.lsp.diagnostic.set_loclist() - - return vim.fn.getloclist(0) - ]] - - assert(loc_list[1].lnum < loc_list[2].lnum) - end) - end) end) diff --git a/test/functional/plugin/lsp/incremental_sync_spec.lua b/test/functional/plugin/lsp/incremental_sync_spec.lua new file mode 100644 index 0000000000..fe4f8f3593 --- /dev/null +++ b/test/functional/plugin/lsp/incremental_sync_spec.lua @@ -0,0 +1,266 @@ +-- Test suite for testing interactions with the incremental sync algorithms powering the LSP client +local helpers = require('test.functional.helpers')(after_each) + +local meths = helpers.meths +local clear = helpers.clear +local eq = helpers.eq +local exec_lua = helpers.exec_lua +local feed = helpers.feed + +before_each(function () + clear() + exec_lua [[ + local evname = ... + local sync = require('vim.lsp.sync') + local events = {} + local buffer_cache = {} + + -- local format_line_ending = { + -- ["unix"] = '\n', + -- ["dos"] = '\r\n', + -- ["mac"] = '\r', + -- } + + -- local line_ending = format_line_ending[vim.api.nvim_buf_get_option(0, 'fileformat')] + + + function test_register(bufnr, id, offset_encoding, line_ending) + local curr_lines + local prev_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true) + + local function callback(_, bufnr, changedtick, firstline, lastline, new_lastline) + if test_unreg == id then + return true + end + + local curr_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true) + local incremental_change = sync.compute_diff( + prev_lines, curr_lines, firstline, lastline, new_lastline, offset_encoding, line_ending) + + table.insert(events, incremental_change) + prev_lines = curr_lines + end + local opts = {on_lines=callback, on_detach=callback, on_reload=callback} + vim.api.nvim_buf_attach(bufnr, false, opts) + end + + function get_events() + local ret_events = events + events = {} + return ret_events + end + ]] +end) + +local function test_edit(prev_buffer, edit_operations, expected_text_changes, offset_encoding, line_ending) + offset_encoding = offset_encoding or 'utf-16' + line_ending = line_ending or '\n' + + meths.buf_set_lines(0, 0, -1, true, prev_buffer) + exec_lua("return test_register(...)", 0, "test1", offset_encoding, line_ending) + + for _, edit in ipairs(edit_operations) do + feed(edit) + end + eq(expected_text_changes, exec_lua("return get_events(...)" )) + exec_lua("test_unreg = 'test1'") + +end +describe('incremental synchronization', function() + describe('single line edit', function() + it('inserting a character in an empty buffer', function() + local expected_text_changes = { + { + range = { + ['start'] = { + character = 0, + line = 0 + }, + ['end'] = { + character = 0, + line = 0 + } + }, + rangeLength = 0, + text = 'a' + } + } + test_edit({""}, {"ia"}, expected_text_changes, 'utf-16', '\n') + end) + it('inserting a character in the middle of a the first line', function() + local expected_text_changes = { + { + range = { + ['start'] = { + character = 1, + line = 0 + }, + ['end'] = { + character = 1, + line = 0 + } + }, + rangeLength = 0, + text = 'a' + } + } + test_edit({"ab"}, {"lia"}, expected_text_changes, 'utf-16', '\n') + end) + it('deleting the only character in a buffer', function() + local expected_text_changes = { + { + range = { + ['start'] = { + character = 0, + line = 0 + }, + ['end'] = { + character = 1, + line = 0 + } + }, + rangeLength = 1, + text = '' + } + } + test_edit({"a"}, {"x"}, expected_text_changes, 'utf-16', '\n') + end) + it('deleting a character in the middle of the line', function() + local expected_text_changes = { + { + range = { + ['start'] = { + character = 1, + line = 0 + }, + ['end'] = { + character = 2, + line = 0 + } + }, + rangeLength = 1, + text = '' + } + } + test_edit({"abc"}, {"lx"}, expected_text_changes, 'utf-16', '\n') + end) + it('replacing a character', function() + local expected_text_changes = { + { + range = { + ['start'] = { + character = 0, + line = 0 + }, + ['end'] = { + character = 1, + line = 0 + } + }, + rangeLength = 1, + text = 'b' + } + } + test_edit({"a"}, {"rb"}, expected_text_changes, 'utf-16', '\n') + end) + describe('multi-byte edits', function() + it('join and undo', function() + local expected_text_changes = { + { + range = { + ['start'] = { + character = 11, + line = 0 + }, + ['end'] = { + character = 11, + line = 0 + } + }, + rangeLength = 0, + text = ' test3' + },{ + range = { + ['start'] = { + character = 0, + line = 1 + }, + ['end'] = { + character = 0, + line = 2 + } + }, + rangeLength = 6, + text = '' + },{ + range = { + ['start'] = { + character = 11, + line = 0 + }, + ['end'] = { + character = 17, + line = 0 + } + }, + rangeLength = 6, + text = '\ntest3' + }, + } + test_edit({"test1 test2", "test3"}, {"J", "u"}, expected_text_changes, 'utf-16', '\n') + end) + end) + end) + describe('multi-byte edits', function() + it('deleting a multibyte character', function() + local expected_text_changes = { + { + range = { + ['start'] = { + character = 0, + line = 0 + }, + ['end'] = { + character = 2, + line = 0 + } + }, + rangeLength = 2, + text = '' + } + } + test_edit({"🔥"}, {"x"}, expected_text_changes, 'utf-16', '\n') + end) + it('deleting a multiple lines containing multibyte characters', function() + local expected_text_changes = { + { + range = { + ['start'] = { + character = 0, + line = 1 + }, + ['end'] = { + character = 0, + line = 3 + } + }, + --utf 16 len of 🔥 is 2 + rangeLength = 8, + text = '' + } + } + test_edit({"a🔥", "b🔥", "c🔥", "d🔥"}, {"j2dd"}, expected_text_changes, 'utf-16', '\n') + end) + end) +end) + +-- TODO(mjlbach): Add additional tests +-- deleting single lone line +-- 2 lines -> 2 line delete -> undo -> redo +-- describe('future tests', function() +-- -- This test is currently wrong, ask bjorn why dd on an empty line triggers on_lines +-- it('deleting an empty line', function() +-- local expected_text_changes = {{ }} +-- test_edit({""}, {"ggdd"}, expected_text_changes, 'utf-16', '\n') +-- end) +-- end) diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index ce50abb50d..228fc06e9b 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -3,9 +3,11 @@ local helpers = require('test.functional.helpers')(after_each) local assert_log = helpers.assert_log local clear = helpers.clear local buf_lines = helpers.buf_lines +local command = helpers.command local dedent = helpers.dedent local exec_lua = helpers.exec_lua local eq = helpers.eq +local eval = helpers.eval local matches = helpers.matches local pcall_err = helpers.pcall_err local pesc = helpers.pesc @@ -272,7 +274,7 @@ describe('LSP', function() return end local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; + {NIL, {}, {method="shutdown", bufnr=1, client_id=1}}; {NIL, {}, {method="test", client_id=1}}; } test_rpc_server { @@ -486,7 +488,7 @@ describe('LSP', function() it('should forward ContentModified to callback', function() local expected_handlers = { {NIL, {}, {method="finish", client_id=1}}; - {{code = -32801}, NIL, {method = "error_code_test", client_id=1}}; + {{code = -32801}, NIL, {method = "error_code_test", bufnr=1, client_id=1}}; } local client test_rpc_server { @@ -509,6 +511,140 @@ describe('LSP', function() } end) + it('should track pending requests to the language server', function() + local expected_handlers = { + {NIL, {}, {method="finish", client_id=1}}; + {NIL, {}, {method="slow_request", bufnr=1, client_id=1}}; + } + local client + test_rpc_server { + test_name = "check_pending_request_tracked"; + on_init = function(_client) + client = _client + client.request("slow_request") + local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) + eq("slow_request", request.method) + eq("pending", request.type) + client.notify("release") + end; + on_exit = function(code, signal) + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, #expected_handlers, "did not call expected handler") + end; + on_handler = function(err, _, ctx) + eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler") + if ctx.method == 'slow_request' then + local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) + eq(NIL, request) + client.notify("finish") + end + if ctx.method == 'finish' then client.stop() end + end; + } + end) + + it('should track cancel requests to the language server', function() + local expected_handlers = { + {NIL, {}, {method="finish", client_id=1}}; + } + local client + test_rpc_server { + test_name = "check_cancel_request_tracked"; + on_init = function(_client) + client = _client + client.request("slow_request") + client.cancel_request(2) + local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) + eq("slow_request", request.method) + eq("cancel", request.type) + client.notify("release") + end; + on_exit = function(code, signal) + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, #expected_handlers, "did not call expected handler") + end; + on_handler = function(err, _, ctx) + eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler") + local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) + eq(NIL, request) + if ctx.method == 'finish' then client.stop() end + end; + } + end) + + it('should clear pending and cancel requests on reply', function() + local expected_handlers = { + {NIL, {}, {method="finish", client_id=1}}; + {NIL, {}, {method="slow_request", bufnr=1, client_id=1}}; + } + local client + test_rpc_server { + test_name = "check_tracked_requests_cleared"; + on_init = function(_client) + client = _client + client.request("slow_request") + local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) + eq("slow_request", request.method) + eq("pending", request.type) + client.cancel_request(2) + request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) + eq("slow_request", request.method) + eq("cancel", request.type) + client.notify("release") + end; + on_exit = function(code, signal) + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, #expected_handlers, "did not call expected handler") + end; + on_handler = function(err, _, ctx) + eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler") + if ctx.method == 'slow_request' then + local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) + eq(NIL, request) + client.notify("finish") + end + if ctx.method == 'finish' then client.stop() end + end; + } + end) + + it('should trigger LspRequest autocmd when requests table changes', function() + local expected_handlers = { + {NIL, {}, {method="finish", client_id=1}}; + {NIL, {}, {method="slow_request", bufnr=1, client_id=1}}; + } + local client + test_rpc_server { + test_name = "check_tracked_requests_cleared"; + on_init = function(_client) + command('let g:requests = 0') + command('autocmd User LspRequest let g:requests+=1') + client = _client + client.request("slow_request") + eq(1, eval('g:requests')) + client.cancel_request(2) + eq(2, eval('g:requests')) + client.notify("release") + end; + on_exit = function(code, signal) + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, #expected_handlers, "did not call expected handler") + eq(3, eval('g:requests')) + end; + on_handler = function(err, _, ctx) + eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler") + if ctx.method == 'slow_request' then + client.notify("finish") + end + if ctx.method == 'finish' then client.stop() end + end; + } + end) + it('should not send didOpen if the buffer closes before init', function() local expected_handlers = { {NIL, {}, {method="shutdown", client_id=1}}; @@ -790,7 +926,7 @@ describe('LSP', function() -- TODO(askhan) we don't support full for now, so we can disable these tests. pending('should check the body and didChange incremental normal mode editing', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; + {NIL, {}, {method="shutdown", bufnr=1, client_id=1}}; {NIL, {}, {method="finish", client_id=1}}; {NIL, {}, {method="start", client_id=1}}; } @@ -1017,15 +1153,9 @@ describe('LSP', function() end) it('should invalid cmd argument', function() - eq(dedent([[ - Error executing lua: .../lsp.lua:0: cmd: expected list, got nvim - stack traceback: - .../lsp.lua:0: in function <.../lsp.lua:0>]]), + eq('Error executing lua: .../lsp.lua:0: cmd: expected list, got nvim', pcall_err(_cmd_parts, 'nvim')) - eq(dedent([[ - Error executing lua: .../lsp.lua:0: cmd argument: expected string, got number - stack traceback: - .../lsp.lua:0: in function <.../lsp.lua:0>]]), + eq('Error executing lua: .../lsp.lua:0: cmd argument: expected string, got number', pcall_err(_cmd_parts, {'nvim', 1})) end) end) @@ -1605,6 +1735,7 @@ describe('LSP', function() -- after rename the target file must have the contents of the source file local bufnr = vim.fn.bufadd(new) + vim.fn.bufload(new) return vim.api.nvim_buf_get_lines(bufnr, 0, -1, true) ]], old, new) eq({'Test content'}, lines) @@ -2305,9 +2436,9 @@ describe('LSP', function() local bufnr = vim.api.nvim_get_current_buf() lsp.buf_attach_client(bufnr, TEST_RPC_CLIENT_ID) vim.lsp._stubs = {} - vim.fn.input = function(prompt, text) - vim.lsp._stubs.input_prompt = prompt - vim.lsp._stubs.input_text = text + vim.fn.input = function(opts, on_confirm) + vim.lsp._stubs.input_prompt = opts.prompt + vim.lsp._stubs.input_text = opts.default return 'renameto' -- expect this value in fake lsp end vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {'', 'this is line two'}) @@ -2395,4 +2526,57 @@ describe('LSP', function() ) end) end) + describe('vim.lsp.codelens', function() + it('uses client commands', function() + local client + local expected_handlers = { + {NIL, {}, {method="shutdown", client_id=1}}; + {NIL, {}, {method="start", client_id=1}}; + } + test_rpc_server { + test_name = 'clientside_commands', + on_init = function(client_) + client = client_ + end, + on_setup = function() + end, + on_exit = function(code, signal) + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) + end, + on_handler = function(err, result, ctx) + eq(table.remove(expected_handlers), {err, result, ctx}) + if ctx.method == 'start' then + local fake_uri = "file:///fake/uri" + local cmd = exec_lua([[ + fake_uri = ... + local bufnr = vim.uri_to_bufnr(fake_uri) + vim.fn.bufload(bufnr) + vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {'One line'}) + local lenses = { + { + range = { + start = { line = 0, character = 0, }, + ['end'] = { line = 0, character = 8 } + }, + command = { title = 'Lens1', command = 'Dummy' } + }, + } + vim.lsp.codelens.on_codelens(nil, lenses, {method='textDocument/codeLens', client_id=1, bufnr=bufnr}) + local cmd_called = nil + vim.lsp.commands['Dummy'] = function(command) + cmd_called = command + end + vim.api.nvim_set_current_buf(bufnr) + vim.lsp.codelens.run() + return cmd_called + ]], fake_uri) + eq({ command = 'Dummy', title = 'Lens1' }, cmd) + elseif ctx.method == 'shutdown' then + client.stop() + end + end + } + end) + end) end) diff --git a/test/functional/terminal/channel_spec.lua b/test/functional/terminal/channel_spec.lua new file mode 100644 index 0000000000..7d37dcccc8 --- /dev/null +++ b/test/functional/terminal/channel_spec.lua @@ -0,0 +1,49 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear = helpers.clear +local eq = helpers.eq +local command = helpers.command +local exc_exec = helpers.exc_exec +local feed = helpers.feed +local sleep = helpers.sleep +local poke_eventloop = helpers.poke_eventloop + +describe('associated channel is closed and later freed for terminal', function() + before_each(clear) + + it('opened by nvim_open_term() and deleted by :bdelete!', function() + command([[let id = nvim_open_term(0, {})]]) + -- channel hasn't been freed yet + eq("Vim(call):Can't send data to closed stream", exc_exec([[bdelete! | call chansend(id, 'test')]])) + -- process free_channel_event + poke_eventloop() + -- channel has been freed + eq("Vim(call):E900: Invalid channel id", exc_exec([[call chansend(id, 'test')]])) + end) + + it('opened by termopen(), exited, and deleted by pressing a key', function() + command([[let id = termopen('echo')]]) + sleep(500) + -- process has exited + eq("Vim(call):Can't send data to closed stream", exc_exec([[call chansend(id, 'test')]])) + -- delete terminal + feed('i<CR>') + -- process term_delayed_free and free_channel_event + poke_eventloop() + -- channel has been freed + eq("Vim(call):E900: Invalid channel id", exc_exec([[call chansend(id, 'test')]])) + end) + + -- This indirectly covers #16264 + it('opened by termopen(), exited, and deleted by :bdelete', function() + command([[let id = termopen('echo')]]) + sleep(500) + -- process has exited + eq("Vim(call):Can't send data to closed stream", exc_exec([[call chansend(id, 'test')]])) + -- channel hasn't been freed yet + eq("Vim(call):Can't send data to closed stream", exc_exec([[bdelete | call chansend(id, 'test')]])) + -- process term_delayed_free and free_channel_event + poke_eventloop() + -- channel has been freed + eq("Vim(call):E900: Invalid channel id", exc_exec([[call chansend(id, 'test')]])) + end) +end) diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index f7520b14d4..6b9586b4de 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -494,6 +494,8 @@ describe('TUI', function() it('paste: recovers from vim.paste() failure', function() child_session:request('nvim_exec_lua', [[ _G.save_paste_fn = vim.paste + -- Stack traces for this test are non-deterministic, so disable them + _G.debug.traceback = function(msg) return msg end vim.paste = function(lines, phase) error("fake fail") end ]], {}) -- Prepare something for dot-repeat/redo. @@ -514,7 +516,7 @@ describe('TUI', function() foo | | {5: }| - {8:paste: Error executing lua: [string "<nvim>"]:2: f}| + {8:paste: Error executing lua: [string "<nvim>"]:4: f}| {8:ake fail} | {10:Press ENTER or type command to continue}{1: } | {3:-- TERMINAL --} | @@ -579,12 +581,16 @@ describe('TUI', function() it("paste: 'nomodifiable' buffer", function() child_session:request('nvim_command', 'set nomodifiable') + child_session:request('nvim_exec_lua', [[ + -- Stack traces for this test are non-deterministic, so disable them + _G.debug.traceback = function(msg) return msg end + ]], {}) feed_data('\027[200~fail 1\nfail 2\n\027[201~') screen:expect{grid=[[ | {4:~ }| {5: }| - {MATCH:paste: Error executing lua: vim.lua:%d+: Vim:E21: }| + {8:paste: Error executing lua: vim.lua:243: Vim:E21: }| {8:Cannot make changes, 'modifiable' is off} | {10:Press ENTER or type command to continue}{1: } | {3:-- TERMINAL --} | @@ -671,8 +677,8 @@ describe('TUI', function() item 2997 | item 2998 | item 2999 | - item 3000 en{1:d}d | - {5:[No Name] [+] 5999,13 Bot}| + item 3000 en{1:d} | + {5:[No Name] [+] 3000,13 Bot}| | {3:-- TERMINAL --} | ]]) diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index 8074f91215..dce6384b9b 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -901,15 +901,15 @@ if (h->n_buckets < new_n_buckets) { // expand screen:expect{grid=[[ if (h->n_buckets < new_n_buckets) { // expand | khkey_t *new_keys = (khkey_t *) | + {1:>> }{2:krealloc}: change the size of an allocation | {3:krealloc}((void *)h->keys, new_n_buckets * sizeof(k| hkey_t)); | h->keys = new_keys; | if (kh_is_map && val_size) { | - char *new_vals = {3:krealloc}( h->vals_buf, new_n_| - buck^ets * val_size); | + ^char *new_vals = {3:krealloc}( h->vals_buf, new_n_| + buckets * val_size); | {5:^^ REVIEW:}{6: new_vals variable seems unneccesary?} | h->vals_buf = new_vals; | - } | | ]]} @@ -992,7 +992,7 @@ if (h->n_buckets < new_n_buckets) { // expand ]]} end) - it('works with text et the end of the buffer', function() + it('works with text at the end of the buffer', function() insert(example_text) feed 'G' @@ -1213,7 +1213,7 @@ if (h->n_buckets < new_n_buckets) { // expand | ]]} - meths.buf_set_extmark(0, ns, 2, 0, { + local markid = meths.buf_set_extmark(0, ns, 2, 0, { virt_lines={ {{"Some special", "Special"}}; {{"remark about codes", "Comment"}}; @@ -1241,6 +1241,7 @@ if (h->n_buckets < new_n_buckets) { // expand {{"remark about codes", "Comment"}}; }; virt_lines_leftcol=true; + id=markid; }) screen:expect{grid=[[ {8: }{9: 1 }^if (h->n_buckets < new_n_buckets) { // expan| diff --git a/test/functional/ui/diff_spec.lua b/test/functional/ui/diff_spec.lua index df750a1a68..13949b0756 100644 --- a/test/functional/ui/diff_spec.lua +++ b/test/functional/ui/diff_spec.lua @@ -1196,4 +1196,27 @@ it('Align the filler lines when changing text in diff mode', function() {8:[No Name] [+] }{3:[No Name] [+] }| | ]]} + feed('<C-W>lay<Esc>') + screen:expect{grid=[[ + {1: }{2:-----------------}{3:│}{1: }{4:6 }| + {1: }{2:-----------------}{3:│}{1: }{4:7 }| + {1: }{2:-----------------}{3:│}{1: }{4:8 }| + {1: }9 {3:│}{1: }9 | + {1: }10 {3:│}{1: }10 | + {1: }11 {3:│}{1: }11 | + {1: }12 {3:│}{1: }12 | + {1: }13 {3:│}{1: }13 | + {1: }14 {3:│}{1: }14 | + {1: }{5:15}{6:x}{5: }{3:│}{1: }{5:15}{6:^y}{5: }| + {7:~ }{3:│}{7:~ }| + {7:~ }{3:│}{7:~ }| + {7:~ }{3:│}{7:~ }| + {7:~ }{3:│}{7:~ }| + {7:~ }{3:│}{7:~ }| + {7:~ }{3:│}{7:~ }| + {7:~ }{3:│}{7:~ }| + {7:~ }{3:│}{7:~ }| + {3:[No Name] [+] }{8:[No Name] [+] }| + | + ]]} end) diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 6c2c4b398a..5f29261b17 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -1,11 +1,13 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') +local global_helpers = require('test.helpers') local os = require('os') local clear, feed = helpers.clear, helpers.feed local assert_alive = helpers.assert_alive local command, feed_command = helpers.command, helpers.feed_command local eval = helpers.eval local eq = helpers.eq +local neq = helpers.neq local exec_lua = helpers.exec_lua local insert = helpers.insert local meths = helpers.meths @@ -13,6 +15,7 @@ local curbufmeths = helpers.curbufmeths local funcs = helpers.funcs local run = helpers.run local pcall_err = helpers.pcall_err +local tbl_contains = global_helpers.tbl_contains describe('float window', function() before_each(function() @@ -294,6 +297,125 @@ describe('float window', function() eq(12, pos[2]) end) + it('is not operated on by windo when non-focusable #15374', function() + command([[ + let winids = [] + windo call add(winids, win_getid()) + ]]) + local windo_count_before = eval('len(winids)') + local winid = exec_lua([[ + local bufnr = vim.api.nvim_create_buf(false, true) + local opts = { + relative = 'editor', + focusable = false, + height = 5, + width = 5, + col = 5, + row = 5, + } + return vim.api.nvim_open_win(bufnr, false, opts) + ]]) + command([[ + let winids = [] + windo call add(winids, win_getid()) + ]]) + local windo_count_after = eval('len(winids)') + eq(windo_count_before, windo_count_after) + eq(false, tbl_contains(eval('winids'), winid)) + end) + + it('is operated on by windo when focusable', function() + command([[ + let winids = [] + windo call add(winids, win_getid()) + ]]) + local windo_count_before = eval('len(winids)') + local winid = exec_lua([[ + local bufnr = vim.api.nvim_create_buf(false, true) + local opts = { + relative = 'editor', + focusable = true, + height = 5, + width = 5, + col = 5, + row = 5, + } + return vim.api.nvim_open_win(bufnr, false, opts) + ]]) + command([[ + let winids = [] + windo call add(winids, win_getid()) + ]]) + local windo_count_after = eval('len(winids)') + eq(windo_count_before + 1, windo_count_after) + eq(true, tbl_contains(eval('winids'), winid)) + end) + + it('is not active after windo when non-focusable #15374', function() + local winid = exec_lua([[ + local bufnr = vim.api.nvim_create_buf(false, true) + local opts = { + relative = 'editor', + focusable = false, + height = 5, + width = 5, + col = 5, + row = 5, + } + return vim.api.nvim_open_win(bufnr, false, opts) + ]]) + command('windo echo') + neq(eval('win_getid()'), winid) + end) + + it('is active after windo when focusable', function() + local winid = exec_lua([[ + local bufnr = vim.api.nvim_create_buf(false, true) + local opts = { + relative = 'editor', + focusable = true, + height = 5, + width = 5, + col = 5, + row = 5, + } + return vim.api.nvim_open_win(bufnr, false, opts) + ]]) + command('windo echo') + eq(eval('win_getid()'), winid) + end) + + it('supports windo with focusable and non-focusable floats', function() + local winids = exec_lua([[ + local result = {vim.api.nvim_get_current_win()} + local bufnr = vim.api.nvim_create_buf(false, true) + local opts = { + relative = 'editor', + focusable = false, + height = 5, + width = 5, + col = 5, + row = 5, + } + vim.api.nvim_open_win(bufnr, false, opts) + opts.focusable = true + table.insert(result, vim.api.nvim_open_win(bufnr, false, opts)) + opts.focusable = false + vim.api.nvim_open_win(bufnr, false, opts) + opts.focusable = true + table.insert(result, vim.api.nvim_open_win(bufnr, false, opts)) + opts.focusable = false + vim.api.nvim_open_win(bufnr, false, opts) + return result + ]]) + table.sort(winids) + command([[ + let winids = [] + windo call add(winids, win_getid()) + call sort(winids) + ]]) + eq(winids, eval('winids')) + end) local function with_ext_multigrid(multigrid) local screen @@ -1194,6 +1316,49 @@ describe('float window', function() ]]} end + meths.win_set_config(win, {border={"", "_", "", "", "", "-", "", ""}}) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 5 + {5:_________}| + {1: halloj! }| + {1: BORDAA }| + {5:---------}| + ]], float_pos={ + [5] = { { id = 1002 }, "NW", 1, 2, 5, true } + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }{5:_________}{0: }| + {0:~ }{1: halloj! }{0: }| + {0:~ }{1: BORDAA }{0: }| + {0:~ }{5:---------}{0: }| + | + ]]} + end + insert [[ neeed some dummy background text diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index c238898244..f038348253 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -750,8 +750,13 @@ describe('ui/ext_messages', function() {1:~ }| {1:~ }| ]], messages={{ - content = {{'E5108: Error executing lua [string ":lua"]:1: such\nmultiline\nerror', 2}}, - kind = "lua_error" + content = {{[[E5108: Error executing lua [string ":lua"]:1: such +multiline +error +stack traceback: + [C]: in function 'error' + [string ":lua"]:1: in main chunk]], 2}}, + kind = "lua_error", }}} end) @@ -1048,12 +1053,12 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim -- edge case: just covers statusline feed(':set colorcolumn=5 | lua error("x\\n\\nx")<cr>') screen:expect{grid=[[ - | - {1:~ }| - {3: }| {2:E5108: Error executing lua [string ":lua"]:1: x} | | {2:x} | + {2:stack traceback:} | + {2: [C]: in function 'error'} | + {2: [string ":lua"]:1: in main chunk} | {4:Press ENTER or type command to continue}^ | ]]} @@ -1071,24 +1076,24 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim -- edge case: just covers lowest window line feed(':set colorcolumn=5 | lua error("x\\n\\n\\nx")<cr>') screen:expect{grid=[[ - | - {3: }| {2:E5108: Error executing lua [string ":lua"]:1: x} | | | {2:x} | - {4:Press ENTER or type command to continue}^ | + {2:stack traceback:} | + {2: [C]: in function 'error'} | + {4:-- More --}^ | ]]} feed('<cr>') screen:expect{grid=[[ | - {1:~ }| - {8:[No Name] }| - ^ {9: } | - {1:~ }| - {3:[No Name] }| | + {2:x} | + {2:stack traceback:} | + {2: [C]: in function 'error'} | + {2: [string ":lua"]:1: in main chunk} | + {4:Press ENTER or type command to continue}^ | ]]} end) end) @@ -1360,14 +1365,14 @@ aliquip ex ea commodo consequat.]]) ]]} feed('d') screen:expect{grid=[[ + {2:mpor} | {2:incididunt ut labore et dolore magn}| {2:a aliqua.} | {2:Ut enim ad minim veniam, quis nostr}| {2:ud xercitation} | {2:ullamco laboris nisi ut} | {2:aliquip ex ea commodo consequat.} | - {4:Press ENTER or type command to cont}| - {4:inue}^ | + {4:-- More --}^ | ]]} feed('u') screen:expect{grid=[[ @@ -1460,14 +1465,14 @@ aliquip ex ea commodo consequat.]]) ]]} feed('d') screen:expect{grid=[[ + {3:mpor}{5: }| {3:incididunt ut labore et dolore magn}| {3:a aliqua.}{5: }| {3:Ut enim ad minim veniam, quis nostr}| {3:ud xercitation}{5: }| {3:ullamco laboris nisi ut}{5: }| {3:aliquip ex ea commodo consequat.}{5: }| - {6:Press ENTER or type command to cont}| - {6:inue}{5:^ }| + {6:-- More --}{5:^ }| ]]} feed('u') screen:expect{grid=[[ @@ -1667,6 +1672,7 @@ aliquip ex ea commodo consequat.]]) -- wrapped at the new screen size. feed('<cr>') screen:expect{grid=[[ + {2:":lua"]:1: Lorem ipsum dolor s}| {2:et, consectetur} | {2:adipisicing elit, sed do eiusm}| {2:mpore} | @@ -1677,8 +1683,7 @@ aliquip ex ea commodo consequat.]]) {2:ullamco laboris nisi ut} | {2:aliquip ex ea commodo consequa}| {2:t.} | - {4:Press ENTER or type command to}| - {4: continue}^ | + {4:-- More --}^ | ]]} feed('q') diff --git a/test/functional/vimscript/executable_spec.lua b/test/functional/vimscript/executable_spec.lua index 28aefb72e5..048a65188d 100644 --- a/test/functional/vimscript/executable_spec.lua +++ b/test/functional/vimscript/executable_spec.lua @@ -18,7 +18,7 @@ describe('executable()', function() end) it('fails for invalid values', function() - for _, input in ipairs({'""', 'v:null', 'v:true', 'v:false', '{}', '[]'}) do + for _, input in ipairs({'v:null', 'v:true', 'v:false', '{}', '[]'}) do eq('Vim(call):E928: String required', exc_exec('call executable('..input..')')) end command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")') @@ -27,6 +27,10 @@ describe('executable()', function() end end) + it('returns 0 for empty strings', function() + eq(0, call('executable', '""')) + end) + it('returns 0 for non-existent files', function() eq(0, call('executable', 'no_such_file_exists_209ufq23f')) end) diff --git a/test/functional/vimscript/exepath_spec.lua b/test/functional/vimscript/exepath_spec.lua index 08d2c59af8..bbca954511 100644 --- a/test/functional/vimscript/exepath_spec.lua +++ b/test/functional/vimscript/exepath_spec.lua @@ -20,9 +20,10 @@ describe('exepath()', function() end) it('fails for invalid values', function() - for _, input in ipairs({'""', 'v:null', 'v:true', 'v:false', '{}', '[]'}) do + for _, input in ipairs({'v:null', 'v:true', 'v:false', '{}', '[]'}) do eq('Vim(call):E928: String required', exc_exec('call exepath('..input..')')) end + eq('Vim(call):E1142: Non-empty string required', exc_exec('call exepath("")')) command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")') for _, input in ipairs({'v:null', 'v:true', 'v:false'}) do eq('Vim(call):E928: String required', exc_exec('call exepath('..input..')')) diff --git a/test/functional/vimscript/has_spec.lua b/test/functional/vimscript/has_spec.lua index a3af2d1a20..c03fd13e0c 100644 --- a/test/functional/vimscript/has_spec.lua +++ b/test/functional/vimscript/has_spec.lua @@ -59,7 +59,12 @@ describe('has()', function() end) it('"wsl"', function() - if 1 == funcs.has('win32') or 1 == funcs.has('mac') then + local luv = require('luv') + local is_wsl = + luv.os_uname()['release']:lower():match('microsoft') and true or false + if is_wsl then + eq(1, funcs.has('wsl')) + else eq(0, funcs.has('wsl')) end end) diff --git a/test/functional/vimscript/null_spec.lua b/test/functional/vimscript/null_spec.lua index 7ecbcd2fd6..f23f00bcc5 100644 --- a/test/functional/vimscript/null_spec.lua +++ b/test/functional/vimscript/null_spec.lua @@ -161,7 +161,7 @@ describe('NULL', function() null_test('does not crash :echomsg', 'echomsg S', 0) null_test('does not crash :execute', 'execute S', 0) null_expr_test('does not crash execute()', 'execute(S)', 0, '') - null_expr_test('makes executable() error out', 'executable(S)', 'E928: String required', 0) + null_expr_test('does not crash executable()', 'executable(S)', 0, 0) null_expr_test('makes timer_start() error out', 'timer_start(0, S)', 'E921: Invalid callback argument', -1) null_expr_test('does not crash filereadable()', 'filereadable(S)', 0, 0) null_expr_test('does not crash filewritable()', 'filewritable(S)', 0, 0) diff --git a/test/helpers.lua b/test/helpers.lua index 9ac3904776..09b113c01d 100644 --- a/test/helpers.lua +++ b/test/helpers.lua @@ -155,12 +155,20 @@ function module.pcall_err_withfile(fn, ...) return errmsg end -function module.pcall_err(fn, ...) +function module.pcall_err_withtrace(fn, ...) local errmsg = module.pcall_err_withfile(fn, ...) return errmsg:gsub('.../helpers.lua:0: ', '') end +function module.pcall_err(...) + return module.remove_trace(module.pcall_err_withtrace(...)) +end + +function module.remove_trace(s) + return (s:gsub("\n%s*stack traceback:.*", "")) +end + -- initial_path: directory to recurse into -- re: include pattern (string) -- exc_re: exclude pattern(s) (string or table) diff --git a/test/unit/api/private_helpers_spec.lua b/test/unit/api/private_helpers_spec.lua index a534d83165..dbb4b3ae5a 100644 --- a/test/unit/api/private_helpers_spec.lua +++ b/test/unit/api/private_helpers_spec.lua @@ -18,7 +18,7 @@ local type_key = api_helpers.type_key local obj2lua = api_helpers.obj2lua local func_type = api_helpers.func_type -local api = cimport('./src/nvim/api/private/helpers.h') +local api = cimport('./src/nvim/api/private/helpers.h', './src/nvim/api/private/converter.h') describe('vim_to_object', function() local vim_to_object = function(l) diff --git a/test/unit/marktree_spec.lua b/test/unit/marktree_spec.lua index cd9c7bef13..10d02d2eb4 100644 --- a/test/unit/marktree_spec.lua +++ b/test/unit/marktree_spec.lua @@ -97,7 +97,7 @@ describe('marktree', function() for i = 1,100 do for j = 1,100 do local gravitate = (i%2) > 0 - local id = tonumber(lib.marktree_put(tree, j, i, gravitate)) + local id = tonumber(lib.marktree_put(tree, j, i, gravitate, 0)) ok(id > 0) eq(nil, shadow[id]) shadow[id] = {j,i,gravitate} @@ -191,7 +191,7 @@ describe('marktree', function() -- https://github.com/neovim/neovim/pull/14719 lib.marktree_clear(tree) for i = 1,20 do - lib.marktree_put(tree, i, i, false) + lib.marktree_put(tree, i, i, false, 0) end lib.marktree_itr_get(tree, 10, 10, iter) diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 29ff0daa8d..8ad71cfd3a 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -151,8 +151,8 @@ set(MSGPACK_URL https://github.com/msgpack/msgpack-c/releases/download/cpp-3.0.0 set(MSGPACK_SHA256 bfbb71b7c02f806393bc3cbc491b40523b89e64f83860c58e3e54af47de176e4) # https://github.com/LuaJIT/LuaJIT/tree/v2.1 -set(LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/787736990ac3b7d5ceaba2697c7d0f58f77bb782.tar.gz) -set(LUAJIT_SHA256 2e3f74bc279f46cc463abfc67b36e69faaf0366237004771f4cac4bf2a9f5efb) +set(LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/b4b2dce9fc3ffaaaede39b36d06415311e2aa516.tar.gz) +set(LUAJIT_SHA256 6c9e46877db2df16ca0fa76db4043ed30a1ae60c89d9ba2c3e4d35eb2360cd4d) set(LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz) set(LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333) @@ -169,9 +169,9 @@ set(LIBTERMKEY_SHA256 6945bd3c4aaa83da83d80a045c5563da4edd7d0374c62c0d35aec09eb3 set(LIBVTERM_URL http://www.leonerd.org.uk/code/libvterm/libvterm-0.1.4.tar.gz) set(LIBVTERM_SHA256 bc70349e95559c667672fc8c55b9527d9db9ada0fb80a3beda533418d782d3dd) -set(LUV_VERSION 1.42.0-0) +set(LUV_VERSION 1.42.0-1) set(LUV_URL https://github.com/luvit/luv/archive/${LUV_VERSION}.tar.gz) -set(LUV_SHA256 8caee38de2fba0da32abbe96f55244e4a2c67d6cdde161a1935af94bffd5470f) +set(LUV_SHA256 a55563e6da9294ea26f77a2111598aa49188c5806b8bd1e1f4bdf402f340713e) set(LUA_COMPAT53_URL https://github.com/keplerproject/lua-compat-5.3/archive/v0.9.tar.gz) set(LUA_COMPAT53_SHA256 ad05540d2d96a48725bb79a1def35cf6652a4e2ec26376e2617c8ce2baa6f416) diff --git a/third-party/cmake/BuildLibuv.cmake b/third-party/cmake/BuildLibuv.cmake index c5f7d6d5ab..dce64c777b 100644 --- a/third-party/cmake/BuildLibuv.cmake +++ b/third-party/cmake/BuildLibuv.cmake @@ -1,5 +1,3 @@ -include(CMakeParseArguments) - # BuildLibuv(TARGET targetname CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...) # Reusable function to build libuv, wraps ExternalProject_Add. # Failing to pass a command argument will result in no command being run @@ -7,7 +5,7 @@ function(BuildLibuv) cmake_parse_arguments(_libuv "BUILD_IN_SOURCE" "TARGET" - "CONFIGURE_COMMAND;BUILD_COMMAND;INSTALL_COMMAND" + "PATCH_COMMAND;CONFIGURE_COMMAND;BUILD_COMMAND;INSTALL_COMMAND" ${ARGN}) if(NOT _libuv_CONFIGURE_COMMAND AND NOT _libuv_BUILD_COMMAND @@ -30,6 +28,7 @@ function(BuildLibuv) -DTARGET=${_libuv_TARGET} -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake + PATCH_COMMAND "${_libuv_PATCH_COMMAND}" BUILD_IN_SOURCE ${_libuv_BUILD_IN_SOURCE} CONFIGURE_COMMAND "${_libuv_CONFIGURE_COMMAND}" BUILD_COMMAND "${_libuv_BUILD_COMMAND}" @@ -64,6 +63,10 @@ elseif(WIN32) set(BUILD_SHARED ON) elseif(MINGW) set(BUILD_SHARED OFF) + set(LIBUV_PATCH_COMMAND + ${GIT_EXECUTABLE} -C ${DEPS_BUILD_DIR}/src/libuv init + COMMAND ${GIT_EXECUTABLE} -C ${DEPS_BUILD_DIR}/src/libuv apply --ignore-whitespace + ${CMAKE_CURRENT_SOURCE_DIR}/patches/libuv-disable-typedef-MinGW.patch) else() message(FATAL_ERROR "Trying to build libuv in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}") endif() @@ -77,6 +80,7 @@ elseif(WIN32) -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DBUILD_SHARED_LIBS=${BUILD_SHARED} -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR} + PATCH_COMMAND ${LIBUV_PATCH_COMMAND} BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE} INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config ${CMAKE_BUILD_TYPE}) diff --git a/third-party/cmake/BuildLibvterm.cmake b/third-party/cmake/BuildLibvterm.cmake index c3485dac25..09f2ba7f2c 100644 --- a/third-party/cmake/BuildLibvterm.cmake +++ b/third-party/cmake/BuildLibvterm.cmake @@ -1,5 +1,3 @@ -include(CMakeParseArguments) - # BuildLibvterm(CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...) # Failing to pass a command argument will result in no command being run function(BuildLibvterm) diff --git a/third-party/cmake/BuildLua.cmake b/third-party/cmake/BuildLua.cmake index c3f789509e..a40cb7dcb2 100644 --- a/third-party/cmake/BuildLua.cmake +++ b/third-party/cmake/BuildLua.cmake @@ -1,5 +1,3 @@ -include(CMakeParseArguments) - # BuildLua(CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...) # Reusable function to build lua, wraps ExternalProject_Add. # Failing to pass a command argument will result in no command being run diff --git a/third-party/cmake/BuildLuajit.cmake b/third-party/cmake/BuildLuajit.cmake index ca41a7cee3..c4e5112dce 100644 --- a/third-party/cmake/BuildLuajit.cmake +++ b/third-party/cmake/BuildLuajit.cmake @@ -1,5 +1,3 @@ -include(CMakeParseArguments) - # BuildLuajit(TARGET targetname CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...) # Reusable function to build luajit, wraps ExternalProject_Add. # Failing to pass a command argument will result in no command being run @@ -55,7 +53,7 @@ else() endif() set(INSTALLCMD_UNIX ${MAKE_PRG} CFLAGS=-fPIC CFLAGS+=-DLUA_USE_APICHECK - CFLAGS+=-DLUA_USE_ASSERT + CFLAGS+=-funwind-tables ${NO_STACK_CHECK} ${AMD64_ABI} CCDEBUG+=-g @@ -111,7 +109,7 @@ elseif(MINGW) BuildLuaJit(BUILD_COMMAND ${LUAJIT_MAKE_PRG} CC=${DEPS_C_COMPILER} PREFIX=${DEPS_INSTALL_DIR} CFLAGS+=-DLUA_USE_APICHECK - CFLAGS+=-DLUA_USE_ASSERT + CFLAGS+=-funwind-tables CCDEBUG+=-g BUILDMODE=static # Build a DLL too diff --git a/third-party/cmake/BuildLuv.cmake b/third-party/cmake/BuildLuv.cmake index f5d45c7ff7..69f3b60ecf 100644 --- a/third-party/cmake/BuildLuv.cmake +++ b/third-party/cmake/BuildLuv.cmake @@ -1,5 +1,3 @@ -include(CMakeParseArguments) - # BuildLuv(PATCH_COMMAND ... CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...) # Reusable function to build luv, wraps ExternalProject_Add. # Failing to pass a command argument will result in no command being run diff --git a/third-party/cmake/BuildMsgpack.cmake b/third-party/cmake/BuildMsgpack.cmake index 30af5f060b..39a8a64d23 100644 --- a/third-party/cmake/BuildMsgpack.cmake +++ b/third-party/cmake/BuildMsgpack.cmake @@ -1,5 +1,3 @@ -include(CMakeParseArguments) - # BuildMsgpack(CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...) # Reusable function to build msgpack, wraps ExternalProject_Add. # Failing to pass a command argument will result in no command being run diff --git a/third-party/cmake/BuildTreesitter.cmake b/third-party/cmake/BuildTreesitter.cmake index a55b2e36e8..0aa2706d7d 100644 --- a/third-party/cmake/BuildTreesitter.cmake +++ b/third-party/cmake/BuildTreesitter.cmake @@ -1,5 +1,3 @@ -include(CMakeParseArguments) - # BuildTreeSitter(TARGET targetname CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...) function(BuildTreeSitter) cmake_parse_arguments(_treesitter diff --git a/third-party/cmake/GetBinaryDeps.cmake b/third-party/cmake/GetBinaryDeps.cmake index 982bf62265..04e3f95a29 100644 --- a/third-party/cmake/GetBinaryDeps.cmake +++ b/third-party/cmake/GetBinaryDeps.cmake @@ -1,6 +1,3 @@ -# 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 DEPS_PREFIX. # The INSTALL_COMMAND is executed in the folder where downloaded files are diff --git a/third-party/patches/libuv-disable-typedef-MinGW.patch b/third-party/patches/libuv-disable-typedef-MinGW.patch new file mode 100644 index 0000000000..a47893cede --- /dev/null +++ b/third-party/patches/libuv-disable-typedef-MinGW.patch @@ -0,0 +1,19 @@ +diff --git a/include/uv/win.h b/include/uv/win.h +index f5f1d3a3..64a0dfd9 100644 +--- a/include/uv/win.h ++++ b/include/uv/win.h +@@ -45,7 +45,14 @@ typedef struct pollfd { + #endif + + #include <mswsock.h> ++// Disable the typedef in mstcpip.h of MinGW. ++#define _TCP_INITIAL_RTO_PARAMETERS _TCP_INITIAL_RTO_PARAMETERS__ ++#define TCP_INITIAL_RTO_PARAMETERS TCP_INITIAL_RTO_PARAMETERS__ ++#define PTCP_INITIAL_RTO_PARAMETERS PTCP_INITIAL_RTO_PARAMETERS__ + #include <ws2tcpip.h> ++#undef _TCP_INITIAL_RTO_PARAMETERS ++#undef TCP_INITIAL_RTO_PARAMETERS ++#undef PTCP_INITIAL_RTO_PARAMETERS + #include <windows.h> + + #include <process.h> |