diff options
196 files changed, 7942 insertions, 4728 deletions
diff --git a/.gitignore b/.gitignore index 94bb54c661..766c323c34 100644 --- a/.gitignore +++ b/.gitignore @@ -23,9 +23,6 @@ tags # Files generated by the tests /src/nvim/testdir/del -/src/nvim/testdir/mbyte.vim -/src/nvim/testdir/small.vim -/src/nvim/testdir/tiny.vim /src/nvim/testdir/test*.out /src/nvim/testdir/test.log /src/nvim/testdir/messages @@ -45,27 +42,12 @@ tags # luarocks, not added as a subtree because of the large number of blobs /third-party/luarocks -# luajit files -/third-party/luajit/src/host/buildvm -/third-party/luajit/src/host/buildvm_arch.h -/third-party/luajit/src/host/minilua -/third-party/luajit/src/jit/vmdef.lua -/third-party/luajit/src/libluajit.a -/third-party/luajit/src/lj_bcdef.h -/third-party/luajit/src/lj_ffdef.h -/third-party/luajit/src/lj_folddef.h -/third-party/luajit/src/lj_libdef.h -/third-party/luajit/src/lj_recdef.h -/third-party/luajit/src/lj_vm.s -/third-party/luajit/src/luajit - # local make targets local.mk # runtime/doc /runtime/doc/*.html /runtime/doc/tags.ref -/runtime/doc/doctags /runtime/doc/errors.log # clint errors, generated by `make lint` diff --git a/.travis.yml b/.travis.yml index 985a5c5381..1158acf076 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ env: # Update PATH for pip and MinGW. - PATH="$(python2.7 -c 'import site; print(site.getuserbase())')/bin:$HOME/.local/mingw32/bin:$PATH" # LLVM symbolizer path. - - LLVM_SYMBOLIZER="$(which llvm-symbolizer-3.6)" + - LLVM_SYMBOLIZER="$(which llvm-symbolizer-3.4)" # Build directory for Neovim. - BUILD_DIR="$TRAVIS_BUILD_DIR/build" # Build directory for third-party dependencies. @@ -72,13 +72,13 @@ matrix: compiler: gcc-5 -m32 env: BUILD_32BIT=ON - os: linux - compiler: clang-3.6 - env: GCOV=llvm-cov-3.6 CLANG_SANITIZER=ASAN_UBSAN CMAKE_FLAGS="$CMAKE_FLAGS -DUSE_GCOV=ON" + compiler: clang + env: GCOV=llvm-cov CLANG_SANITIZER=ASAN_UBSAN CMAKE_FLAGS="$CMAKE_FLAGS -DUSE_GCOV=ON" - os: linux - compiler: clang-3.6 + compiler: clang env: CLANG_SANITIZER=MSAN - os: linux - compiler: clang-3.6 + compiler: clang env: CLANG_SANITIZER=TSAN - os: osx compiler: clang @@ -103,13 +103,12 @@ addons: sources: # TODO: Remove PPA when Travis gets Python >=3.3. - deadsnakes - - llvm-toolchain-precise-3.6 - ubuntu-toolchain-r-test packages: - autoconf - automake - build-essential - - clang-3.6 + - clang-3.4 - cmake - g++-5-multilib - g++-multilib @@ -118,7 +117,7 @@ addons: - gdb - libc6-dev-i386 - libtool - - llvm-3.6-dev + - llvm-3.4-dev - pkg-config - python3.3-dev - unzip diff --git a/CMakeLists.txt b/CMakeLists.txt index 317d2a1a5b..f736508641 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -300,11 +300,19 @@ include_directories(SYSTEM ${LIBUV_INCLUDE_DIRS}) find_package(Msgpack 1.0.0 REQUIRED) include_directories(SYSTEM ${MSGPACK_INCLUDE_DIRS}) -find_package(Unibilium REQUIRED) -include_directories(SYSTEM ${UNIBILIUM_INCLUDE_DIRS}) +if(UNIX) + option(FEAT_TUI "Enable the Terminal UI" ON) +else() + option(FEAT_TUI "Enable the Terminal UI" OFF) +endif() -find_package(LibTermkey REQUIRED) -include_directories(SYSTEM ${LIBTERMKEY_INCLUDE_DIRS}) +if(FEAT_TUI) + find_package(Unibilium REQUIRED) + include_directories(SYSTEM ${UNIBILIUM_INCLUDE_DIRS}) + + find_package(LibTermkey REQUIRED) + include_directories(SYSTEM ${LIBTERMKEY_INCLUDE_DIRS}) +endif() find_package(LibVterm REQUIRED) include_directories(SYSTEM ${LIBVTERM_INCLUDE_DIRS}) @@ -366,7 +374,7 @@ endforeach() include(LuaHelpers) set(LUA_DEPENDENCIES lpeg mpack bit) if(NOT LUA_PRG) - foreach(CURRENT_LUA_PRG luajit lua) + foreach(CURRENT_LUA_PRG luajit lua5.1 lua5.2 lua) # If LUA_PRG is set find_program() will not search unset(LUA_PRG CACHE) unset(LUA_PRG_WORKS) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1787a4322b..dbc048d939 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,160 +3,96 @@ ## Getting started - Help us review [open pull requests](https://github.com/neovim/neovim/pulls)! -- Look for [entry-level issues][entry-level] to work on. - - [Documentation](https://github.com/neovim/neovim/labels/documentation) - improvements are also much appreciated. -- Look at [Waffle][waffle] to see who is working on what issues. -- If needed, refer to [the wiki][wiki-contributing] for guidance. + See [Reviewing](#reviewing) for guidelines. +- Try an [entry-level issue][entry-level] if you are wondering where to start. +- Or [merge a Vim patch]. ## Reporting problems -Before reporting an issue, see the following wiki articles: +- Check the [**FAQ**][wiki-faq]. +- Search [existing issues][github-issues] (including closed!) +- Update Neovim to the latest version to see if your problem persists. +- If you're using a plugin manager, comment out your plugins, then add them back + in one by one, to narrow down the cause of the issue. +- Crash reports which include a stacktrace are 10x more valuable. +- [Bisecting][git-bisect] to the cause of a regression often leads to an + immediate fix. + +## Pull requests ("PRs") + +- To avoid duplicate work, you may want to create a `[WIP]` pull request so that + others know what you are working on. +- Avoid cosmetic changes to unrelated files in the same commit: extra noise + makes reviews more difficult. +- Use a [feature branch][git-feature-branch] instead of the master branch. +- [Rebase your feature branch][git-rebasing] onto (upstream) master before + opening the PR. +- After addressing the review comments, it's fine to rebase and force-push to + your review. +- Try to [tidy your history][git-history-rewriting]: combine related commits + with interactive rebasing, separate monolithic commits, etc. -- [Troubleshooting][wiki-troubleshooting] -- [Frequently asked questions][wiki-faq] +### Stages: WIP, RFC -If your issue isn't mentioned there: +Pull requests are processed in two stages: _WIP_ (Work In Progress) and _RFC_ +(Request For Comment). -- Verify that it hasn't already been reported. -- If not already running the latest version of Neovim, update to it to see if - your problem persists. -- If you're experiencing compile or runtime warnings/failures, try searching for - the error message(s) you received (if any) on [Neovim's issue tracker][github-issues]. -- For runtime issues, try reproducing it using `nvim` with the smallest - possible `vimrc` (or none at all via `nvim -u NONE`), to rule out bugs in - plugins you're using. If you're using a plugin manager, comment out your - plugins, then add them back in one by one. +- Untagged PRs are assumed to be RFC, meaning the work is ready for review and + you would like feedback. +- Preprend `[WIP]` to the PR title if you are _not_ ready for feedback and the + work is still in flux. This saves time and confusion. -Include as much detail as possible; we generally need to know: +### Commit messages -- What operating system you're using. -- Which version of Neovim you're using. To get this, run `nvim --version` from - a shell, or run `:version` from inside `nvim`. -- Whether the bug is present in Vim (not Neovim), and if so which version of - Vim. It's fine to report Vim bugs on the Neovim bug tracker, but it saves - everyone time if we know from the start that the bug is not a regression - caused by Neovim. -- This isn't required, but what commit introduced the issue for you. You can - use [`git bisect`][git-bisect] for this. +Follow [commit message hygiene][hygiene] to *make reviews easier* and to make +the VCS/git logs more valuable. -## Submitting contributions +- Try to keep the first line under 72 characters. +- **Prefix the commit subject with a _scope_:** `doc:`, `test:`, `foo.c:`, + `runtime:`, ... + - For commits that contain only style/lint changes, a single-word subject + line is preferred: `style` or `lint`. +- A blank line must separate the subject from the description. +- Use the _imperative voice_: "Fix bug" rather than "Fixed bug" or "Fixes bug." -- Make it clear in the issue tracker what you are working on. -- Be descriptive in your pull request description: what is it for, why is it - needed, etc. -- Do ***not*** make cosmetic changes to unrelated files in the same pull - request. This creates noise, making reviews harder to do. If your text - editor strips all trailing whitespace in a file when you edit it, disable - it. +### Automated builds (CI) -### Tagging in the issue tracker +Each pull request must pass the automated builds ([travis CI] and [quickbuild]). -When submitting pull requests (commonly referred to as "PRs"), include one of -the following tags prepended to the title: +- CI builds are compiled with [`-Werror`][gcc-warnings], so if your PR + introduces any compiler warnings, the build will fail. +- If any tests fail, the build will fail. + See [Building Neovim#running-tests][wiki-run-tests] to run tests locally. + Passing locally doesn't guarantee passing the CI build, because of the + different compilers and platforms tested against. +- CI runs [ASan] and other analyzers. To run valgrind locally: + `VALGRIND=1 make test` +- The `lint` build ([#3174][3174]) checks modified lines _and their immediate + neighbors_. This is to encourage incrementally updating the legacy style to + meet our style guidelines. + - A single word (`lint` or `style`) is sufficient as the subject line of + a commit that contains only style changes. +- [How to investigate QuickBuild failures](https://github.com/neovim/neovim/pull/4718#issuecomment-217631350) -- `[WIP]` - Work In Progress: the PR will change, so while there is no - immediate need for review, the submitter still might appreciate it. -- `[RFC]` - Request For Comment: the PR needs reviewing and/or comments. -- `[RDY]` - Ready: the PR has been reviewed by at least one other person and - has no outstanding issues. +### Coverity -Assuming the above criteria has been met, feel free to change your PR's tag -yourself, as opposed to waiting for a contributor to do it for you. +[Coverity](https://scan.coverity.com/projects/neovim-neovim) runs against the +master build. If you want to view the defects, just request access at the +_Contributor_ level. An Admin will grant you permission. -### Branching & history +Use this commit-message format for coverity fixes: -- Do ***not*** work on your PR on the master branch, [use a feature branch - instead][git-feature-branch]. -- [Rebase your feature branch onto][git-rebasing] (upstream) master before - opening the PR. -- Keep up to date with changes in (upstream) master so your PR is easy to - merge. -- [Try to actively tidy your history][git-history-rewriting]: combine related - commits with interactive rebasing, separate monolithic commits, etc. If your - PR is still `[WIP]`, feel free to force-push to your feature branch to tidy - your history. - -### For code pull requests - -#### Testing - -We are unlikely to merge your PR if the Travis build fails: - -- Travis builds are compiled with the [`-Werror`][gcc-warnings] flag, so if - your PR introduces any compiler warnings then the Travis build will fail. -- If any tests fail, the Travis build will fail. - See [Building Neovim#running-tests][wiki-building-running-tests] for - information on running tests locally. - Tests passing locally doesn't guarantee they'll pass in the Travis - build, as different compilers and platforms will be used. -- Travis runs [Valgrind][valgrind] for the GCC/Linux build, but you may also - do so locally by running the following from a shell: `VALGRIND=1 make test` - -#### Coding style - -We have a [style guide][style-guide] that all new code should follow. -However, large portions of the existing Vim codebase violate it to some -degree, and fixing them would increase merge conflicts and add noise to `git -blame`. - -Weigh those costs when making cosmetic changes. In general, avoid pull -requests dominated by style changes, but feel free to fix up lines that you -happen to be modifying anyway. Fix anything that looks outright -[barbarous](http://www.orwell.ru/library/essays/politics/english/e_polit), but -otherwise prefer to leave things as they are. - -For new code, run `make lint` (which runs [clint.py][clint]) to detect style -errors. It's not perfect, so some warnings may be false positives/negatives. -To have `clint.py` ignore certain cases, put `// NOLINT` at the end of the -line. - -We also provide a configuration file for [`clang-format`][clang-format], which -can be used to format code according to the style guidelines. Be aware that -this formatting method might need user supervision. To have `clang-format` -ignore certain line ranges, use the following special comments: - -```c -int formatted_code; -// clang-format off - void unformatted_code ; -// clang-format on - void formatted_code_again; -``` - -### Commit guidelines - -The purpose of these guidelines is to *make reviews easier* and make the -[VCS][vcs] logs more valuable. + coverity/<id>: <description of what fixed the defect> -- Try to keep the first line under 72 characters. -- If necessary, include further description after a blank line. - - Don't make the description too verbose by including obvious things, but - don't spare clarifications for anything that may be not so obvious. - Some commit messages are pages long, and that's fine if there's no - better place for those comments to live. - - **Recommended:** Prefix logically-related commits with a consistent - identifier in each commit message. For already used identifiers, see the - commit history for the respective file(s) you're editing. - [For example](https://github.com/neovim/neovim/commits?author=elmart), - the following commits are related by task (*Introduce nvim namespace*) and - sub-task (*Contrib YCM*). - <br/> `Introduce nvim namespace: Contrib YCM: Fix style issues` - <br/> `Introduce nvim namespace: Contrib YCM: Fix build dir calculation` - - Sub-tasks can be *activity-oriented* (doing different things on the same area) - or *scope-oriented* (doing the same thing in different areas). - - Granularity helps, but it's conceptual size that matters, not extent size. -- Use the [imperative voice][imperative]: "Fix bug" rather than "Fixed bug" or "Fixes bug." - -### Reviewing pull requests - -Using a checklist during reviews is highly recommended, so we [provide one at -the wiki][wiki-review-checklist]. If you think it could be improved, feel free -to edit it. +where `<id>` is the Coverity ID (CID). For example see [#804](https://github.com/neovim/neovim/pull/804). + +## Reviewing + +To help review pull requests, start with [this checklist][review-checklist]. Reviewing can be done on GitHub, but you may find it easier to do locally. -Using [`hub`][hub], you can do the following to create a new branch with the -contents of a pull request, such as [#1820][github-pr-1820]: +Using [`hub`][hub], you can create a new branch with the contents of a pull +request, e.g. [#1820][1820]: hub checkout https://github.com/neovim/neovim/pull/1820 @@ -165,11 +101,7 @@ commits in the feature branch which aren't in the `master` branch; `-p` shows each commit's diff. To show the whole surrounding function of a change as context, use the `-W` argument as well. -You may find it easier to instead use an interactive program for code reviews, -such as [`tig`][tig]. -[clang-format]: http://clang.llvm.org/docs/ClangFormat.html -[clint]: clint.py [entry-level]: https://github.com/neovim/neovim/issues?labels=entry-level&state=open [gcc-warnings]: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html [git-bisect]: http://git-scm.com/book/tr/v2/Git-Tools-Debugging-with-Git @@ -178,16 +110,15 @@ such as [`tig`][tig]. [git-history-rewriting]: http://git-scm.com/book/en/v2/Git-Tools-Rewriting-History [git-rebasing]: http://git-scm.com/book/en/v2/Git-Branching-Rebasing [github-issues]: https://github.com/neovim/neovim/issues -[github-pr-1820]: https://github.com/neovim/neovim/pull/1820 +[1820]: https://github.com/neovim/neovim/pull/1820 [hub]: https://hub.github.com/ -[imperative]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html +[hygiene]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html [style-guide]: http://neovim.io/develop/style-guide.xml -[tig]: https://github.com/jonas/tig -[valgrind]: http://valgrind.org/ -[vcs]: https://en.wikipedia.org/wiki/Revision_control -[waffle]: https://waffle.io/neovim/neovim -[wiki-building-running-tests]: https://github.com/neovim/neovim/wiki/Building-Neovim#running-tests -[wiki-contributing]: https://github.com/neovim/neovim/wiki/Contributing +[ASan]: http://clang.llvm.org/docs/AddressSanitizer.html +[wiki-run-tests]: https://github.com/neovim/neovim/wiki/Building-Neovim#running-tests [wiki-faq]: https://github.com/neovim/neovim/wiki/FAQ -[wiki-review-checklist]: https://github.com/neovim/neovim/wiki/Code-review-checklist -[wiki-troubleshooting]: https://github.com/neovim/neovim/wiki/Troubleshooting +[review-checklist]: https://github.com/neovim/neovim/wiki/Code-review-checklist +[3174]: https://github.com/neovim/neovim/issues/3174 +[travis CI]: https://travis-ci.org/neovim/neovim +[quickbuild]: http://neovim-qb.szakmeister.net/dashboard +[merge a Vim patch]: https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-Vim diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index d9fd758177..011739396d 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1,5 +1,5 @@ -- Neovim version: -- [ ] Vim behaves differently? Vim version: +- `nvim --version`: +- Vim (version: ) behaves differently? - Operating system/version: - Terminal name/version: - `$TERM`: @@ -85,10 +85,10 @@ endif mkdir -p build touch $@ -oldtest: | nvim tags +oldtest: | nvim helptags +$(SINGLE_MAKE) -C src/nvim/testdir $(MAKEOVERRIDES) -tags: | nvim +helptags: | nvim +$(BUILD_CMD) -C build runtime/doc/tags functionaltest: | nvim @@ -119,7 +119,7 @@ install: | nvim +$(BUILD_CMD) -C build install clint: - cmake -DLINT_PRG=./clint.py \ + cmake -DLINT_PRG=./src/clint.py \ -DLINT_DIR=src \ -DLINT_SUPPRESS_URL="$(DOC_DOWNLOAD_URL_BASE)$(CLINT_ERRORS_FILE_PATH)" \ -P cmake/RunLint.cmake @@ -18,7 +18,7 @@ Neovim is a project that seeks to aggressively refactor Vim in order to: -- Simplify maintenance and encourage [contributions](https://github.com/neovim/neovim/wiki/Contributing) +- Simplify maintenance and encourage [contributions](CONTRIBUTING.md) - Split the work between multiple developers - Enable the implementation of new/modern user interfaces without any modifications to the core source @@ -42,7 +42,7 @@ See the [progress page](https://github.com/neovim/neovim/wiki/Progress) for a co ### What's being worked on now -- Port all IO to [libuv](https://github.com/libuv/libuv/blob/master/README.md) +- Port all IO to [libuv](https://github.com/libuv/libuv/) - Convert legacy tests to Lua tests - VimL => Lua translator @@ -51,10 +51,6 @@ See the [progress page](https://github.com/neovim/neovim/wiki/Progress) for a co There is a formula for OSX/homebrew, a PKGBUILD for Arch Linux, RPM, deb, and more. See [the wiki](https://github.com/neovim/neovim/wiki/Installing-Neovim)! -### Contributing - -...would be awesome! See [the wiki](https://github.com/neovim/neovim/wiki/Contributing) for more details. - ### License Neovim is licensed under the terms of the Apache 2.0 license, except for diff --git a/config/config.h.in b/config/config.h.in index 5c5b008f7e..867278de0d 100644 --- a/config/config.h.in +++ b/config/config.h.in @@ -49,7 +49,7 @@ #cmakedefine UNIX #cmakedefine USE_FNAME_CASE -#define FEAT_CSCOPE +#cmakedefine FEAT_TUI #ifndef UNIT_TESTING #cmakedefine HAVE_JEMALLOC diff --git a/neovim.rb b/neovim.rb deleted file mode 100644 index 859ebdf39d..0000000000 --- a/neovim.rb +++ /dev/null @@ -1,9 +0,0 @@ -odie <<-EOS.undent - - Whoops, the neovim Homebrew Formula has moved! Please instead run: - - brew tap neovim/homebrew-neovim - brew install --HEAD neovim - - Thanks! -EOS diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index cad8da6ffb..4dbd193dab 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -31,7 +31,7 @@ add_custom_command(OUTPUT copy_docfiles ${PROJECT_SOURCE_DIR}/runtime/doc ${GENERATED_RUNTIME_DIR}/doc ) -add_custom_command(OUTPUT ${GENERATED_HELP_TAGS} +add_custom_target(helptags COMMAND "${PROJECT_BINARY_DIR}/bin/nvim" -u NONE -i NONE @@ -45,6 +45,18 @@ add_custom_command(OUTPUT ${GENERATED_HELP_TAGS} WORKING_DIRECTORY "${GENERATED_RUNTIME_DIR}/doc" ) +add_custom_command(OUTPUT ${GENERATED_HELP_TAGS} + DEPENDS + helptags +) + +add_custom_target(doc_html + COMMAND make html + DEPENDS + ${GENERATED_HELP_TAGS} + WORKING_DIRECTORY "${GENERATED_RUNTIME_DIR}/doc" +) + add_custom_target( runtime ALL DEPENDS diff --git a/runtime/autoload/csscomplete.vim b/runtime/autoload/csscomplete.vim index 9eebb87d5b..50048a37fd 100644 --- a/runtime/autoload/csscomplete.vim +++ b/runtime/autoload/csscomplete.vim @@ -1,429 +1,740 @@ " Vim completion script -" Language: CSS 2.1 -" Maintainer: Mikolaj Machowski ( mikmach AT wp DOT pl ) -" Last Change: 2007 May 5 +" Language: CSS +" Based on MDN CSS Reference at 2016 Jan <https://developer.mozilla.org/en-US/docs/Web/CSS/Reference> +" plus CSS Speech Module <http://www.w3.org/TR/css3-speech/> +" Maintainer: Kao, Wei-Ko(othree) ( othree AT gmail DOT com ) +" Original Author: Mikolaj Machowski ( mikmach AT wp DOT pl ) +" Last Change: 2016 Jan 11 - let s:values = split("azimuth background background-attachment background-color background-image background-position background-repeat border bottom border-collapse border-color border-spacing border-style border-top border-right border-bottom border-left border-top-color border-right-color border-bottom-color border-left-color border-top-style border-right-style border-bottom-style border-left-style border-top-width border-right-width border-bottom-width border-left-width border-width caption-side clear clip color content counter-increment counter-reset cue cue-after cue-before cursor display direction elevation empty-cells float font font-family font-size font-style font-variant font-weight height left letter-spacing line-height list-style list-style-image list-style-position list-style-type margin margin-right margin-left margin-top margin-bottom max-height max-width min-height min-width orphans outline outline-color outline-style outline-width overflow padding padding-top padding-right padding-bottom padding-left page-break-after page-break-before page-break-inside pause pause-after pause-before pitch pitch-range play-during position quotes right richness speak speak-header speak-numeral speak-punctuation speech-rate stress table-layout text-align text-decoration text-indent text-transform top unicode-bidi vertical-align visibility voice-family volume white-space width widows word-spacing z-index") +let s:values = split("all additive-symbols align-content align-items align-self animation animation-delay animation-direction animation-duration animation-fill-mode animation-iteration-count animation-name animation-play-state animation-timing-function backface-visibility background background-attachment background-blend-mode background-clip background-color background-image background-origin background-position background-repeat background-size block-size border border-block-end border-block-end-color border-block-end-style border-block-end-width border-block-start border-block-start-color border-block-start-style border-block-start-width border-bottom border-bottom-color border-bottom-left-radius border-bottom-right-radius border-bottom-style border-bottom-width border-collapse border-color border-image border-image-outset border-image-repeat border-image-slice border-image-source border-image-width border-inline-end border-inline-end-color border-inline-end-style border-inline-end-width border-inline-start border-inline-start-color border-inline-start-style border-inline-start-width border-left border-left-color border-left-style border-left-width border-radius border-right border-right-color border-right-style border-right-width border-spacing border-style border-top border-top-color border-top-left-radius border-top-right-radius border-top-style border-top-width border-width bottom box-decoration-break box-shadow box-sizing break-after break-before break-inside caption-side clear clip clip-path color columns column-count column-fill column-gap column-rule column-rule-color column-rule-style column-rule-width column-span column-width content counter-increment counter-reset cue cue-before cue-after cursor direction display empty-cells fallback filter flex flex-basis flex-direction flex-flow flex-grow flex-shrink flex-wrap float font font-family font-feature-settings font-kerning font-language-override font-size font-size-adjust font-stretch font-style font-synthesis font-variant font-variant-alternates font-variant-caps font-variant-east-asian font-variant-ligatures font-variant-numeric font-variant-position font-weight grid grid-area grid-auto-columns grid-auto-flow grid-auto-position grid-auto-rows grid-column grid-column-start grid-column-end grid-row grid-row-start grid-row-end grid-template grid-template-areas grid-template-rows grid-template-columns height hyphens image-rendering image-resolution image-orientation ime-mode inline-size isolation justify-content left letter-spacing line-break line-height list-style list-style-image list-style-position list-style-type margin margin-block-end margin-block-start margin-bottom margin-inline-end margin-inline-start margin-left margin-right margin-top marks mask mask-type max-block-size max-height max-inline-size max-width max-zoom min-block-size min-height min-inline-size min-width min-zoom mix-blend-mode negative object-fit object-position offset-block-end offset-block-start offset-inline-end offset-inline-start opacity order orientation orphans outline outline-color outline-offset outline-style outline-width overflow overflow-wrap overflow-x overflow-y pad padding padding-block-end padding-block-start padding-bottom padding-inline-end padding-inline-start padding-left padding-right padding-top page-break-after page-break-before page-break-inside pause-before pause-after pause perspective perspective-origin pointer-events position prefix quotes range resize rest rest-before rest-after right ruby-align ruby-merge ruby-position scroll-behavior scroll-snap-coordinate scroll-snap-destination scroll-snap-points-x scroll-snap-points-y scroll-snap-type scroll-snap-type-x scroll-snap-type-y shape-image-threshold shape-margin shape-outside speak speak-as suffix symbols system table-layout tab-size text-align text-align-last text-combine-upright text-decoration text-decoration-color text-decoration-line text-emphasis text-emphasis-color text-emphasis-position text-emphasis-style text-indent text-orientation text-overflow text-rendering text-shadow text-transform text-underline-position top touch-action transform transform-box transform-origin transform-style transition transition-delay transition-duration transition-property transition-timing-function unicode-bidi unicode-range user-zoom vertical-align visibility voice-balance voice-duration voice-family voice-pitch voice-rate voice-range voice-stress voice-volume white-space widows width will-change word-break word-spacing word-wrap writing-mode z-index zoom") -function! csscomplete#CompleteCSS(findstart, base) - -if a:findstart - " We need whole line to proper checking - let line = getline('.') - let start = col('.') - 1 - let compl_begin = col('.') - 2 - while start >= 0 && line[start - 1] =~ '\%(\k\|-\)' - let start -= 1 - endwhile - let b:compl_context = line[0:compl_begin] - return start -endif - -" There are few chars important for context: -" ^ ; : { } /* */ -" Where ^ is start of line and /* */ are comment borders -" Depending on their relative position to cursor we will know what should -" be completed. -" 1. if nearest are ^ or { or ; current word is property -" 2. if : it is value (with exception of pseudo things) -" 3. if } we are outside of css definitions -" 4. for comments ignoring is be the easiest but assume they are the same -" as 1. -" 5. if @ complete at-rule -" 6. if ! complete important -if exists("b:compl_context") - let line = b:compl_context - unlet! b:compl_context -else - let line = a:base -endif - -let res = [] -let res2 = [] -let borders = {} - -" Check last occurrence of sequence - -let openbrace = strridx(line, '{') -let closebrace = strridx(line, '}') -let colon = strridx(line, ':') -let semicolon = strridx(line, ';') -let opencomm = strridx(line, '/*') -let closecomm = strridx(line, '*/') -let style = strridx(line, 'style\s*=') -let atrule = strridx(line, '@') -let exclam = strridx(line, '!') - -if openbrace > -1 - let borders[openbrace] = "openbrace" -endif -if closebrace > -1 - let borders[closebrace] = "closebrace" -endif -if colon > -1 - let borders[colon] = "colon" -endif -if semicolon > -1 - let borders[semicolon] = "semicolon" -endif -if opencomm > -1 - let borders[opencomm] = "opencomm" -endif -if closecomm > -1 - let borders[closecomm] = "closecomm" -endif -if style > -1 - let borders[style] = "style" -endif -if atrule > -1 - let borders[atrule] = "atrule" -endif -if exclam > -1 - let borders[exclam] = "exclam" -endif - - -if len(borders) == 0 || borders[max(keys(borders))] =~ '^\%(openbrace\|semicolon\|opencomm\|closecomm\|style\)$' - " Complete properties - - - let entered_property = matchstr(line, '.\{-}\zs[a-zA-Z-]*$') - - for m in s:values - if m =~? '^'.entered_property - call add(res, m . ':') - elseif m =~? entered_property - call add(res2, m . ':') - endif - endfor - - return res + res2 - -elseif borders[max(keys(borders))] == 'colon' - " Get name of property - let prop = tolower(matchstr(line, '\zs[a-zA-Z-]*\ze\s*:[^:]\{-}$')) - - if prop == 'azimuth' - let values = ["left-side", "far-left", "left", "center-left", "center", "center-right", "right", "far-right", "right-side", "behind", "leftwards", "rightwards"] - elseif prop == 'background-attachment' - let values = ["scroll", "fixed"] - elseif prop == 'background-color' - let values = ["transparent", "rgb(", "#"] - elseif prop == 'background-image' - let values = ["url(", "none"] - elseif prop == 'background-position' - let vals = matchstr(line, '.*:\s*\zs.*') - if vals =~ '^\%([a-zA-Z]\+\)\?$' - let values = ["top", "center", "bottom"] - elseif vals =~ '^[a-zA-Z]\+\s\+\%([a-zA-Z]\+\)\?$' - let values = ["left", "center", "right"] - else - return [] - endif - elseif prop == 'background-repeat' - let values = ["repeat", "repeat-x", "repeat-y", "no-repeat"] - elseif prop == 'background' - let values = ["url(", "scroll", "fixed", "transparent", "rgb(", "#", "none", "top", "center", "bottom" , "left", "right", "repeat", "repeat-x", "repeat-y", "no-repeat"] - elseif prop == 'border-collapse' - let values = ["collapse", "separate"] - elseif prop == 'border-color' - let values = ["rgb(", "#", "transparent"] - elseif prop == 'border-spacing' - return [] - elseif prop == 'border-style' - let values = ["none", "hidden", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"] - elseif prop =~ 'border-\%(top\|right\|bottom\|left\)$' - let vals = matchstr(line, '.*:\s*\zs.*') - if vals =~ '^\%([a-zA-Z0-9.]\+\)\?$' - let values = ["thin", "thick", "medium"] - elseif vals =~ '^[a-zA-Z0-9.]\+\s\+\%([a-zA-Z]\+\)\?$' - let values = ["none", "hidden", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"] - elseif vals =~ '^[a-zA-Z0-9.]\+\s\+[a-zA-Z]\+\s\+\%([a-zA-Z(]\+\)\?$' - let values = ["rgb(", "#", "transparent"] - else - return [] - endif - elseif prop =~ 'border-\%(top\|right\|bottom\|left\)-color' - let values = ["rgb(", "#", "transparent"] - elseif prop =~ 'border-\%(top\|right\|bottom\|left\)-style' - let values = ["none", "hidden", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"] - elseif prop =~ 'border-\%(top\|right\|bottom\|left\)-width' - let values = ["thin", "thick", "medium"] - elseif prop == 'border-width' - let values = ["thin", "thick", "medium"] - elseif prop == 'border' - let vals = matchstr(line, '.*:\s*\zs.*') - if vals =~ '^\%([a-zA-Z0-9.]\+\)\?$' - let values = ["thin", "thick", "medium"] - elseif vals =~ '^[a-zA-Z0-9.]\+\s\+\%([a-zA-Z]\+\)\?$' - let values = ["none", "hidden", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"] - elseif vals =~ '^[a-zA-Z0-9.]\+\s\+[a-zA-Z]\+\s\+\%([a-zA-Z(]\+\)\?$' - let values = ["rgb(", "#", "transparent"] - else - return [] - endif - elseif prop == 'bottom' - let values = ["auto"] - elseif prop == 'caption-side' - let values = ["top", "bottom"] - elseif prop == 'clear' - let values = ["none", "left", "right", "both"] - elseif prop == 'clip' - let values = ["auto", "rect("] - elseif prop == 'color' - let values = ["rgb(", "#"] - elseif prop == 'content' - let values = ["normal", "attr(", "open-quote", "close-quote", "no-open-quote", "no-close-quote"] - elseif prop =~ 'counter-\%(increment\|reset\)$' - let values = ["none"] - elseif prop =~ '^\%(cue-after\|cue-before\|cue\)$' - let values = ["url(", "none"] - elseif prop == 'cursor' - let values = ["url(", "auto", "crosshair", "default", "pointer", "move", "e-resize", "ne-resize", "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize", "text", "wait", "help", "progress"] - elseif prop == 'direction' - let values = ["ltr", "rtl"] - elseif prop == 'display' - let values = ["inline", "block", "list-item", "run-in", "inline-block", "table", "inline-table", "table-row-group", "table-header-group", "table-footer-group", "table-row", "table-column-group", "table-column", "table-cell", "table-caption", "none"] - elseif prop == 'elevation' - let values = ["below", "level", "above", "higher", "lower"] - elseif prop == 'empty-cells' - let values = ["show", "hide"] - elseif prop == 'float' - let values = ["left", "right", "none"] - elseif prop == 'font-family' - let values = ["sans-serif", "serif", "monospace", "cursive", "fantasy"] - elseif prop == 'font-size' - let values = ["xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "larger", "smaller"] - elseif prop == 'font-style' - let values = ["normal", "italic", "oblique"] - elseif prop == 'font-variant' - let values = ["normal", "small-caps"] - elseif prop == 'font-weight' - let values = ["normal", "bold", "bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900"] - elseif prop == 'font' - let values = ["normal", "italic", "oblique", "small-caps", "bold", "bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900", "xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "larger", "smaller", "sans-serif", "serif", "monospace", "cursive", "fantasy", "caption", "icon", "menu", "message-box", "small-caption", "status-bar"] - elseif prop =~ '^\%(height\|width\)$' - let values = ["auto"] - elseif prop =~ '^\%(left\|rigth\)$' - let values = ["auto"] - elseif prop == 'letter-spacing' - let values = ["normal"] - elseif prop == 'line-height' - let values = ["normal"] - elseif prop == 'list-style-image' - let values = ["url(", "none"] - elseif prop == 'list-style-position' - let values = ["inside", "outside"] - elseif prop == 'list-style-type' - let values = ["disc", "circle", "square", "decimal", "decimal-leading-zero", "lower-roman", "upper-roman", "lower-latin", "upper-latin", "none"] - elseif prop == 'list-style' - return [] - elseif prop == 'margin' - let values = ["auto"] - elseif prop =~ 'margin-\%(right\|left\|top\|bottom\)$' - let values = ["auto"] - elseif prop == 'max-height' - let values = ["auto"] - elseif prop == 'max-width' - let values = ["none"] - elseif prop == 'min-height' - let values = ["none"] - elseif prop == 'min-width' - let values = ["none"] - elseif prop == 'orphans' - return [] - elseif prop == 'outline-color' - let values = ["rgb(", "#"] - elseif prop == 'outline-style' - let values = ["none", "hidden", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"] - elseif prop == 'outline-width' - let values = ["thin", "thick", "medium"] - elseif prop == 'outline' - let vals = matchstr(line, '.*:\s*\zs.*') - if vals =~ '^\%([a-zA-Z0-9,()#]\+\)\?$' - let values = ["rgb(", "#"] - elseif vals =~ '^[a-zA-Z0-9,()#]\+\s\+\%([a-zA-Z]\+\)\?$' - let values = ["none", "hidden", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"] - elseif vals =~ '^[a-zA-Z0-9,()#]\+\s\+[a-zA-Z]\+\s\+\%([a-zA-Z(]\+\)\?$' - let values = ["thin", "thick", "medium"] - else - return [] - endif - elseif prop == 'overflow' - let values = ["visible", "hidden", "scroll", "auto"] - elseif prop == 'padding' - return [] - elseif prop =~ 'padding-\%(top\|right\|bottom\|left\)$' - return [] - elseif prop =~ 'page-break-\%(after\|before\)$' - let values = ["auto", "always", "avoid", "left", "right"] - elseif prop == 'page-break-inside' - let values = ["auto", "avoid"] - elseif prop =~ 'pause-\%(after\|before\)$' - return [] - elseif prop == 'pause' - return [] - elseif prop == 'pitch-range' - return [] - elseif prop == 'pitch' - let values = ["x-low", "low", "medium", "high", "x-high"] - elseif prop == 'play-during' - let values = ["url(", "mix", "repeat", "auto", "none"] - elseif prop == 'position' - let values = ["static", "relative", "absolute", "fixed"] - elseif prop == 'quotes' - let values = ["none"] - elseif prop == 'richness' - return [] - elseif prop == 'speak-header' - let values = ["once", "always"] - elseif prop == 'speak-numeral' - let values = ["digits", "continuous"] - elseif prop == 'speak-punctuation' - let values = ["code", "none"] - elseif prop == 'speak' - let values = ["normal", "none", "spell-out"] - elseif prop == 'speech-rate' - let values = ["x-slow", "slow", "medium", "fast", "x-fast", "faster", "slower"] - elseif prop == 'stress' - return [] - elseif prop == 'table-layout' - let values = ["auto", "fixed"] - elseif prop == 'text-align' - let values = ["left", "right", "center", "justify"] - elseif prop == 'text-decoration' - let values = ["none", "underline", "overline", "line-through", "blink"] - elseif prop == 'text-indent' - return [] - elseif prop == 'text-transform' - let values = ["capitalize", "uppercase", "lowercase", "none"] - elseif prop == 'top' - let values = ["auto"] - elseif prop == 'unicode-bidi' - let values = ["normal", "embed", "bidi-override"] - elseif prop == 'vertical-align' - let values = ["baseline", "sub", "super", "top", "text-top", "middle", "bottom", "text-bottom"] - elseif prop == 'visibility' - let values = ["visible", "hidden", "collapse"] - elseif prop == 'voice-family' - return [] - elseif prop == 'volume' - let values = ["silent", "x-soft", "soft", "medium", "loud", "x-loud"] - elseif prop == 'white-space' - let values = ["normal", "pre", "nowrap", "pre-wrap", "pre-line"] - elseif prop == 'widows' - return [] - elseif prop == 'word-spacing' - let values = ["normal"] - elseif prop == 'z-index' - let values = ["auto"] - else - " If no property match it is possible we are outside of {} and - " trying to complete pseudo-(class|element) - let element = tolower(matchstr(line, '\zs[a-zA-Z1-6]*\ze:[^:[:space:]]\{-}$')) - if stridx(',a,abbr,acronym,address,area,b,base,bdo,big,blockquote,body,br,button,caption,cite,code,col,colgroup,dd,del,dfn,div,dl,dt,em,fieldset,form,head,h1,h2,h3,h4,h5,h6,hr,html,i,img,input,ins,kbd,label,legend,li,link,map,meta,noscript,object,ol,optgroup,option,p,param,pre,q,samp,script,select,small,span,strong,style,sub,sup,table,tbody,td,textarea,tfoot,th,thead,title,tr,tt,ul,var,', ','.element.',') > -1 - let values = ["first-child", "link", "visited", "hover", "active", "focus", "lang", "first-line", "first-letter", "before", "after"] - else - return [] - endif - endif - - " Complete values - let entered_value = matchstr(line, '.\{-}\zs[a-zA-Z0-9#,.(_-]*$') - - for m in values - if m =~? '^'.entered_value - call add(res, m) - elseif m =~? entered_value - call add(res2, m) - endif - endfor - - return res + res2 - -elseif borders[max(keys(borders))] == 'closebrace' - - return [] - -elseif borders[max(keys(borders))] == 'exclam' - - " Complete values - let entered_imp = matchstr(line, '.\{-}!\s*\zs[a-zA-Z ]*$') - - let values = ["important"] - - for m in values - if m =~? '^'.entered_imp - call add(res, m) - endif - endfor - - return res - -elseif borders[max(keys(borders))] == 'atrule' - - let afterat = matchstr(line, '.*@\zs.*') - - if afterat =~ '\s' - - let atrulename = matchstr(line, '.*@\zs[a-zA-Z-]\+\ze') - - if atrulename == 'media' - let values = ["screen", "tty", "tv", "projection", "handheld", "print", "braille", "aural", "all"] - - let entered_atruleafter = matchstr(line, '.*@media\s\+\zs.*$') - - elseif atrulename == 'import' - let entered_atruleafter = matchstr(line, '.*@import\s\+\zs.*$') - - if entered_atruleafter =~ "^[\"']" - let filestart = matchstr(entered_atruleafter, '^.\zs.*') - let files = split(glob(filestart.'*'), '\n') - let values = map(copy(files), '"\"".v:val') - - elseif entered_atruleafter =~ "^url(" - let filestart = matchstr(entered_atruleafter, "^url([\"']\\?\\zs.*") - let files = split(glob(filestart.'*'), '\n') - let values = map(copy(files), '"url(".v:val') - - else - let values = ['"', 'url('] - - endif - - else - return [] - - endif - - for m in values - if m =~? '^'.entered_atruleafter - call add(res, m) - elseif m =~? entered_atruleafter - call add(res2, m) - endif - endfor - - return res + res2 - - endif - - let values = ["charset", "page", "media", "import", "font-face"] - let entered_atrule = matchstr(line, '.*@\zs[a-zA-Z-]*$') - - for m in values - if m =~? '^'.entered_atrule - call add(res, m .' ') - elseif m =~? entered_atrule - call add(res2, m .' ') - endif - endfor - - return res + res2 - -endif +function! csscomplete#CompleteCSS(findstart, base) -return [] + if a:findstart + " We need whole line to proper checking + let line = getline('.') + let start = col('.') - 1 + let compl_begin = col('.') - 2 + while start >= 0 && line[start - 1] =~ '\%(\k\|-\)' + let start -= 1 + endwhile + let b:after = line[compl_begin :] + let b:compl_context = line[0:compl_begin] + return start + endif + + " There are few chars important for context: + " ^ ; : { } /* */ + " Where ^ is start of line and /* */ are comment borders + " Depending on their relative position to cursor we will know what should + " be completed. + " 1. if nearest are ^ or { or ; current word is property + " 2. if : it is value (with exception of pseudo things) + " 3. if } we are outside of css definitions + " 4. for comments ignoring is be the easiest but assume they are the same + " as 1. + " 5. if @ complete at-rule + " 6. if ! complete important + if exists("b:compl_context") + let line = b:compl_context + let after = b:after + unlet! b:compl_context + else + let line = a:base + endif + + let res = [] + let res2 = [] + let borders = {} + + " Check last occurrence of sequence + + let openbrace = strridx(line, '{') + let closebrace = strridx(line, '}') + let colon = strridx(line, ':') + let semicolon = strridx(line, ';') + let opencomm = strridx(line, '/*') + let closecomm = strridx(line, '*/') + let style = strridx(line, 'style\s*=') + let atrule = strridx(line, '@') + let exclam = strridx(line, '!') + + if openbrace > -1 + let borders[openbrace] = "openbrace" + endif + if closebrace > -1 + let borders[closebrace] = "closebrace" + endif + if colon > -1 + let borders[colon] = "colon" + endif + if semicolon > -1 + let borders[semicolon] = "semicolon" + endif + if opencomm > -1 + let borders[opencomm] = "opencomm" + endif + if closecomm > -1 + let borders[closecomm] = "closecomm" + endif + if style > -1 + let borders[style] = "style" + endif + if atrule > -1 + let borders[atrule] = "atrule" + endif + if exclam > -1 + let borders[exclam] = "exclam" + endif + + + if len(borders) == 0 || borders[max(keys(borders))] =~ '^\%(openbrace\|semicolon\|opencomm\|closecomm\|style\)$' + " Complete properties + + + let entered_property = matchstr(line, '.\{-}\zs[a-zA-Z-]*$') + + for m in s:values + if m =~? '^'.entered_property + call add(res, m . ':') + elseif m =~? entered_property + call add(res2, m . ':') + endif + endfor + + return res + res2 + + elseif borders[max(keys(borders))] == 'colon' + " Get name of property + let prop = tolower(matchstr(line, '\zs[a-zA-Z-]*\ze\s*:[^:]\{-}$')) + + let wide_keywords = ["initial", "inherit", "unset"] + let color_values = ["transparent", "rgb(", "rgba(", "hsl(", "hsla(", "#"] + let border_style_values = ["none", "hidden", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"] + let border_width_values = ["thin", "thick", "medium"] + let list_style_type_values = ["decimal", "decimal-leading-zero", "arabic-indic", "armenian", "upper-armenian", "lower-armenian", "bengali", "cambodian", "khmer", "cjk-decimal", "devanagari", "georgian", "gujarati", "gurmukhi", "hebrew", "kannada", "lao", "malayalam", "mongolian", "myanmar", "oriya", "persian", "lower-roman", "upper-roman", "tamil", "telugu", "thai", "tibetan", "lower-alpha", "lower-latin", "upper-alpha", "upper-latin", "cjk-earthly-branch", "cjk-heavenly-stem", "lower-greek", "hiragana", "hiragana-iroha", "katakana", "katakana-iroha", "disc", "circle", "square", "disclosure-open", "disclosure-closed"] + let timing_functions = ["cubic-bezier(", "steps(", "linear", "ease", "ease-in", "ease-in-out", "ease-out", "step-start", "step-end"] + + if prop == 'all' + let values = [] + elseif prop == 'additive-symbols' + let values = [] + elseif prop == 'align-content' + let values = ["flex-start", "flex-end", "center", "space-between", "space-around", "stretch"] + elseif prop == 'align-items' + let values = ["flex-start", "flex-end", "center", "baseline", "stretch"] + elseif prop == 'align-self' + let values = ["auto", "flex-start", "flex-end", "center", "baseline", "stretch"] + elseif prop == 'animation' + let values = timing_functions + ["normal", "reverse", "alternate", "alternate-reverse"] + ["none", "forwards", "backwards", "both"] + ["running", "paused"] + elseif prop == 'animation-delay' + let values = [] + elseif prop == 'animation-direction' + let values = ["normal", "reverse", "alternate", "alternate-reverse"] + elseif prop == 'animation-duration' + let values = [] + elseif prop == 'animation-fill-mode' + let values = ["none", "forwards", "backwards", "both"] + elseif prop == 'animation-iteration-count' + let values = [] + elseif prop == 'animation-name' + let values = [] + elseif prop == 'animation-play-state' + let values = ["running", "paused"] + elseif prop == 'animation-timing-function' + let values = timing_functions + elseif prop == 'background-attachment' + let values = ["scroll", "fixed"] + elseif prop == 'background-color' + let values = color_values + elseif prop == 'background-image' + let values = ["url(", "none"] + elseif prop == 'background-position' + let vals = matchstr(line, '.*:\s*\zs.*') + if vals =~ '^\%([a-zA-Z]\+\)\?$' + let values = ["top", "center", "bottom"] + elseif vals =~ '^[a-zA-Z]\+\s\+\%([a-zA-Z]\+\)\?$' + let values = ["left", "center", "right"] + else + return [] + endif + elseif prop == 'background-repeat' + let values = ["repeat", "repeat-x", "repeat-y", "no-repeat"] + elseif prop == 'background-size' + let values = ["auto", "contain", "cover"] + elseif prop == 'background' + let values = ["scroll", "fixed"] + color_values + ["url(", "none"] + ["top", "center", "bottom", "left", "right"] + ["repeat", "repeat-x", "repeat-y", "no-repeat"] + ["auto", "contain", "cover"] + elseif prop =~ 'border\%(-top\|-right\|-bottom\|-left\|-block-start\|-block-end\)\?$' + let vals = matchstr(line, '.*:\s*\zs.*') + if vals =~ '^\%([a-zA-Z0-9.]\+\)\?$' + let values = border_width_values + elseif vals =~ '^[a-zA-Z0-9.]\+\s\+\%([a-zA-Z]\+\)\?$' + let values = border_style_values + elseif vals =~ '^[a-zA-Z0-9.]\+\s\+[a-zA-Z]\+\s\+\%([a-zA-Z(]\+\)\?$' + let values = color_values + else + return [] + endif + elseif prop =~ 'border-\%(top\|right\|bottom\|left\|block-start\|block-end\)-color' + let values = color_values + elseif prop =~ 'border-\%(top\|right\|bottom\|left\|block-start\|block-end\)-style' + let values = border_style_values + elseif prop =~ 'border-\%(top\|right\|bottom\|left\|block-start\|block-end\)-width' + let values = border_width_values + elseif prop == 'border-color' + let values = color_values + elseif prop == 'border-style' + let values = border_style_values + elseif prop == 'border-width' + let values = border_width_values + elseif prop == 'bottom' + let values = ["auto"] + elseif prop == 'box-decoration-break' + let values = ["slice", "clone"] + elseif prop == 'box-shadow' + let values = ["inset"] + elseif prop == 'box-sizing' + let values = ["border-box", "content-box"] + elseif prop =~ 'break-\%(before\|after\)' + let values = ["auto", "always", "avoid", "left", "right", "page", "column", "region", "recto", "verso", "avoid-page", "avoid-column", "avoid-region"] + elseif prop == 'break-inside' + let values = ["auto", "avoid", "avoid-page", "avoid-column", "avoid-region"] + elseif prop == 'caption-side' + let values = ["top", "bottom"] + elseif prop == 'clear' + let values = ["none", "left", "right", "both"] + elseif prop == 'clip' + let values = ["auto", "rect("] + elseif prop == 'clip-path' + let values = ["fill-box", "stroke-box", "view-box", "none"] + elseif prop == 'color' + let values = color_values + elseif prop == 'columns' + let values = [] + elseif prop == 'column-count' + let values = ['auto'] + elseif prop == 'column-fill' + let values = ['auto', 'balance'] + elseif prop == 'column-rule-color' + let values = color_values + elseif prop == 'column-rule-style' + let values = border_style_values + elseif prop == 'column-rule-width' + let values = border_width_values + elseif prop == 'column-rule' + let vals = matchstr(line, '.*:\s*\zs.*') + if vals =~ '^\%([a-zA-Z0-9.]\+\)\?$' + let values = border_width_values + elseif vals =~ '^[a-zA-Z0-9.]\+\s\+\%([a-zA-Z]\+\)\?$' + let values = border_style_values + elseif vals =~ '^[a-zA-Z0-9.]\+\s\+[a-zA-Z]\+\s\+\%([a-zA-Z(]\+\)\?$' + let values = color_values + else + return [] + endif + elseif prop == 'column-span' + let values = ["none", "all"] + elseif prop == 'column-width' + let values = ["auto"] + elseif prop == 'content' + let values = ["normal", "attr(", "open-quote", "close-quote", "no-open-quote", "no-close-quote"] + elseif prop =~ 'counter-\%(increment\|reset\)$' + let values = ["none"] + elseif prop =~ 'cue\%(-after\|-before\)\=$' + let values = ["url("] + elseif prop == 'cursor' + let values = ["url(", "auto", "crosshair", "default", "pointer", "move", "e-resize", "ne-resize", "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize", "text", "wait", "help", "progress"] + elseif prop == 'direction' + let values = ["ltr", "rtl"] + elseif prop == 'display' + let values = ["inline", "block", "list-item", "inline-list-item", "run-in", "inline-block", "table", "inline-table", "table-row-group", "table-header-group", "table-footer-group", "table-row", "table-column-group", "table-column", "table-cell", "table-caption", "none", "flex", "inline-flex", "grid", "inline-grid", "ruby", "ruby-base", "ruby-text", "ruby-base-container", "ruby-text-container", "contents"] + elseif prop == 'elevation' + let values = ["below", "level", "above", "higher", "lower"] + elseif prop == 'empty-cells' + let values = ["show", "hide"] + elseif prop == 'fallback' + let values = list_style_type_values + elseif prop == 'filter' + let values = ["blur(", "brightness(", "contrast(", "drop-shadow(", "grayscale(", "hue-rotate(", "invert(", "opacity(", "sepia(", "saturate("] + elseif prop == 'flex-basis' + let values = ["auto", "content"] + elseif prop == 'flex-flow' + let values = ["row", "row-reverse", "column", "column-reverse", "nowrap", "wrap", "wrap-reverse"] + elseif prop == 'flex-grow' + let values = [] + elseif prop == 'flex-shrink' + let values = [] + elseif prop == 'flex-wrap' + let values = ["nowrap", "wrap", "wrap-reverse"] + elseif prop == 'flex' + let values = ["nowrap", "wrap", "wrap-reverse"] + ["row", "row-reverse", "column", "column-reverse", "nowrap", "wrap", "wrap-reverse"] + ["auto", "content"] + elseif prop == 'float' + let values = ["left", "right", "none"] + elseif prop == 'font-family' + let values = ["sans-serif", "serif", "monospace", "cursive", "fantasy"] + elseif prop == 'font-feature-settings' + let values = ["normal", '"aalt"', '"abvf"', '"abvm"', '"abvs"', '"afrc"', '"akhn"', '"blwf"', '"blwm"', '"blws"', '"calt"', '"case"', '"ccmp"', '"cfar"', '"cjct"', '"clig"', '"cpct"', '"cpsp"', '"cswh"', '"curs"', '"cv', '"c2pc"', '"c2sc"', '"dist"', '"dlig"', '"dnom"', '"dtls"', '"expt"', '"falt"', '"fin2"', '"fin3"', '"fina"', '"flac"', '"frac"', '"fwid"', '"half"', '"haln"', '"halt"', '"hist"', '"hkna"', '"hlig"', '"hngl"', '"hojo"', '"hwid"', '"init"', '"isol"', '"ital"', '"jalt"', '"jp78"', '"jp83"', '"jp90"', '"jp04"', '"kern"', '"lfbd"', '"liga"', '"ljmo"', '"lnum"', '"locl"', '"ltra"', '"ltrm"', '"mark"', '"med2"', '"medi"', '"mgrk"', '"mkmk"', '"mset"', '"nalt"', '"nlck"', '"nukt"', '"numr"', '"onum"', '"opbd"', '"ordn"', '"ornm"', '"palt"', '"pcap"', '"pkna"', '"pnum"', '"pref"', '"pres"', '"pstf"', '"psts"', '"pwid"', '"qwid"', '"rand"', '"rclt"', '"rkrf"', '"rlig"', '"rphf"', '"rtbd"', '"rtla"', '"rtlm"', '"ruby"', '"salt"', '"sinf"', '"size"', '"smcp"', '"smpl"', '"ss01"', '"ss02"', '"ss03"', '"ss04"', '"ss05"', '"ss06"', '"ss07"', '"ss08"', '"ss09"', '"ss10"', '"ss11"', '"ss12"', '"ss13"', '"ss14"', '"ss15"', '"ss16"', '"ss17"', '"ss18"', '"ss19"', '"ss20"', '"ssty"', '"stch"', '"subs"', '"sups"', '"swsh"', '"titl"', '"tjmo"', '"tnam"', '"tnum"', '"trad"', '"twid"', '"unic"', '"valt"', '"vatu"', '"vert"', '"vhal"', '"vjmo"', '"vkna"', '"vkrn"', '"vpal"', '"vrt2"', '"zero"'] + elseif prop == 'font-kerning' + let values = ["auto", "normal", "none"] + elseif prop == 'font-language-override' + let values = ["normal"] + elseif prop == 'font-size' + let values = ["xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "larger", "smaller"] + elseif prop == 'font-size-adjust' + let values = [] + elseif prop == 'font-stretch' + let values = ["normal", "ultra-condensed", "extra-condensed", "condensed", "semi-condensed", "semi-expanded", "expanded", "extra-expanded", "ultra-expanded"] + elseif prop == 'font-style' + let values = ["normal", "italic", "oblique"] + elseif prop == 'font-synthesis' + let values = ["none", "weight", "style"] + elseif prop == 'font-variant-alternates' + let values = ["normal", "historical-forms", "stylistic(", "styleset(", "character-variant(", "swash(", "ornaments(", "annotation("] + elseif prop == 'font-variant-caps' + let values = ["normal", "small-caps", "all-small-caps", "petite-caps", "all-petite-caps", "unicase", "titling-caps"] + elseif prop == 'font-variant-asian' + let values = ["normal", "ruby", "jis78", "jis83", "jis90", "jis04", "simplified", "traditional"] + elseif prop == 'font-variant-ligatures' + let values = ["normal", "none", "common-ligatures", "no-common-ligatures", "discretionary-ligatures", "no-discretionary-ligatures", "historical-ligatures", "no-historical-ligatures", "contextual", "no-contextual"] + elseif prop == 'font-variant-numeric' + let values = ["normal", "ordinal", "slashed-zero", "lining-nums", "oldstyle-nums", "proportional-nums", "tabular-nums", "diagonal-fractions", "stacked-fractions"] + elseif prop == 'font-variant-position' + let values = ["normal", "sub", "super"] + elseif prop == 'font-variant' + let values = ["normal", "historical-forms", "stylistic(", "styleset(", "character-variant(", "swash(", "ornaments(", "annotation("] + ["small-caps", "all-small-caps", "petite-caps", "all-petite-caps", "unicase", "titling-caps"] + ["ruby", "jis78", "jis83", "jis90", "jis04", "simplified", "traditional"] + ["none", "common-ligatures", "no-common-ligatures", "discretionary-ligatures", "no-discretionary-ligatures", "historical-ligatures", "no-historical-ligatures", "contextual", "no-contextual"] + ["ordinal", "slashed-zero", "lining-nums", "oldstyle-nums", "proportional-nums", "tabular-nums", "diagonal-fractions", "stacked-fractions"] + ["sub", "super"] + elseif prop == 'font-weight' + let values = ["normal", "bold", "bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900"] + elseif prop == 'font' + let values = ["normal", "italic", "oblique", "small-caps", "bold", "bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900", "xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "larger", "smaller", "sans-serif", "serif", "monospace", "cursive", "fantasy", "caption", "icon", "menu", "message-box", "small-caption", "status-bar"] + elseif prop =~ '^\%(height\|width\)$' + let values = ["auto", "border-box", "content-box", "max-content", "min-content", "available", "fit-content"] + elseif prop =~ '^\%(left\|rigth\)$' + let values = ["auto"] + elseif prop == 'image-rendering' + let values = ["auto", "crisp-edges", "pixelated"] + elseif prop == 'image-orientation' + let values = ["from-image", "flip"] + elseif prop == 'ime-mode' + let values = ["auto", "normal", "active", "inactive", "disabled"] + elseif prop == 'inline-size' + let values = ["auto", "border-box", "content-box", "max-content", "min-content", "available", "fit-content"] + elseif prop == 'isolation' + let values = ["auto", "isolate"] + elseif prop == 'justify-content' + let values = ["flex-start", "flex-end", "center", "space-between", "space-around"] + elseif prop == 'letter-spacing' + let values = ["normal"] + elseif prop == 'line-break' + let values = ["auto", "loose", "normal", "strict"] + elseif prop == 'line-height' + let values = ["normal"] + elseif prop == 'list-style-image' + let values = ["url(", "none"] + elseif prop == 'list-style-position' + let values = ["inside", "outside"] + elseif prop == 'list-style-type' + let values = list_style_type_values + elseif prop == 'list-style' + let values = list_style_type_values + ["inside", "outside"] + ["url(", "none"] + elseif prop == 'margin' + let values = ["auto"] + elseif prop =~ 'margin-\%(right\|left\|top\|bottom\|block-start\|block-end\|inline-start\|inline-end\)$' + let values = ["auto"] + elseif prop == 'marks' + let values = ["crop", "cross", "none"] + elseif prop == 'mask' + let values = ["url("] + elseif prop == 'mask-type' + let values = ["luminance", "alpha"] + elseif prop == '\%(max\|min\)-\%(block\|inline\)-size' + let values = ["auto", "border-box", "content-box", "max-content", "min-content", "available", "fit-content"] + elseif prop == '\%(max\|min\)-\%(height\|width\)' + let values = ["auto", "border-box", "content-box", "max-content", "min-content", "available", "fit-content"] + elseif prop == '\%(max\|min\)-zoom' + let values = ["auto"] + elseif prop == 'mix-blend-mode' + let values = ["normal", "multiply", "screen", "overlay", "darken", "lighten", "color-dodge", "color-burn", "hard-light", "soft-light", "difference", "exclusion", "hue", "saturation", "color", "luminosity"] + elseif prop == 'opacity' + let values = [] + elseif prop == 'orientation' + let values = ["auto", "portrait", "landscape"] + elseif prop == 'orphans' + let values = [] + elseif prop == 'outline-offset' + let values = [] + elseif prop == 'outline-color' + let values = color_values + elseif prop == 'outline-style' + let values = ["none", "hidden", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"] + elseif prop == 'outline-width' + let values = ["thin", "thick", "medium"] + elseif prop == 'outline' + let vals = matchstr(line, '.*:\s*\zs.*') + if vals =~ '^\%([a-zA-Z0-9,()#]\+\)\?$' + let values = color_values + elseif vals =~ '^[a-zA-Z0-9,()#]\+\s\+\%([a-zA-Z]\+\)\?$' + let values = ["none", "hidden", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"] + elseif vals =~ '^[a-zA-Z0-9,()#]\+\s\+[a-zA-Z]\+\s\+\%([a-zA-Z(]\+\)\?$' + let values = ["thin", "thick", "medium"] + else + return [] + endif + elseif prop == 'overflow-wrap' + let values = ["normal", "break-word"] + elseif prop =~ 'overflow\%(-x\|-y\)\=' + let values = ["visible", "hidden", "scroll", "auto"] + elseif prop == 'pad' + let values = [] + elseif prop == 'padding' + let values = [] + elseif prop =~ 'padding-\%(top\|right\|bottom\|left\|inline-start\|inline-end\|block-start\|block-end\)$' + let values = [] + elseif prop =~ 'page-break-\%(after\|before\)$' + let values = ["auto", "always", "avoid", "left", "right", "recto", "verso"] + elseif prop == 'page-break-inside' + let values = ["auto", "avoid"] + elseif prop =~ 'pause\%(-after\|-before\)\=$' + let values = ["none", "x-weak", "weak", "medium", "strong", "x-strong"] + elseif prop == 'perspective' + let values = ["none"] + elseif prop == 'perspective-origin' + let values = ["top", "bottom", "left", "center", " right"] + elseif prop == 'pointer-events' + let values = ["auto", "none", "visiblePainted", "visibleFill", "visibleStroke", "visible", "painted", "fill", "stroke", "all"] + elseif prop == 'position' + let values = ["static", "relative", "absolute", "fixed", "sticky"] + elseif prop == 'prefix' + let values = [] + elseif prop == 'quotes' + let values = ["none"] + elseif prop == 'range' + let values = ["auto", "infinite"] + elseif prop == 'resize' + let values = ["none", "both", "horizontal", "vertical"] + elseif prop =~ 'rest\%(-after\|-before\)\=$' + let values = ["none", "x-weak", "weak", "medium", "strong", "x-strong"] + elseif prop == 'ruby-align' + let values = ["start", "center", "space-between", "space-around"] + elseif prop == 'ruby-merge' + let values = ["separate", "collapse", "auto"] + elseif prop == 'ruby-position' + let values = ["over", "under", "inter-character"] + elseif prop == 'scroll-behavior' + let values = ["auto", "smooth"] + elseif prop == 'scroll-snap-coordinate' + let values = ["none"] + elseif prop == 'scroll-snap-destination' + return [] + elseif prop == 'scroll-snap-points-\%(x\|y\)$' + let values = ["none", "repeat("] + elseif prop == 'scroll-snap-type\%(-x\|-y\)\=$' + let values = ["none", "mandatory", "proximity"] + elseif prop == 'shape-image-threshold' + let values = [] + elseif prop == 'shape-margin' + let values = [] + elseif prop == 'shape-outside' + let values = ["margin-box", "border-box", "padding-box", "content-box", 'inset(', 'circle(', 'ellipse(', 'polygon(', 'url('] + elseif prop == 'speak' + let values = ["auto", "none", "normal"] + elseif prop == 'speak-as' + let values = ["auto", "normal", "spell-out", "digits"] + elseif prop == 'src' + let values = ["url("] + elseif prop == 'suffix' + let values = [] + elseif prop == 'symbols' + let values = [] + elseif prop == 'system' + let vals = matchstr(line, '.*:\s*\zs.*') + if vals =~ '^extends' + let values = list_style_type_values + else + let values = ["cyclic", "numeric", "alphabetic", "symbolic", "additive", "fixed", "extends"] + endif + elseif prop == 'table-layout' + let values = ["auto", "fixed"] + elseif prop == 'tab-size' + let values = [] + elseif prop == 'text-align' + let values = ["start", "end", "left", "right", "center", "justify", "match-parent"] + elseif prop == 'text-align-last' + let values = ["auto", "start", "end", "left", "right", "center", "justify"] + elseif prop == 'text-combine-upright' + let values = ["none", "all", "digits"] + elseif prop == 'text-decoration-line' + let values = ["none", "underline", "overline", "line-through", "blink"] + elseif prop == 'text-decoration-color' + let values = color_values + elseif prop == 'text-decoration-style' + let values = ["solid", "double", "dotted", "dashed", "wavy"] + elseif prop == 'text-decoration' + let values = ["none", "underline", "overline", "line-through", "blink"] + ["solid", "double", "dotted", "dashed", "wavy"] + color_values + elseif prop == 'text-emphasis-color' + let values = color_values + elseif prop == 'text-emphasis-position' + let values = ["over", "under", "left", "right"] + elseif prop == 'text-emphasis-style' + let values = ["none", "filled", "open", "dot", "circle", "double-circle", "triangle", "sesame"] + elseif prop == 'text-emphasis' + let values = color_values + ["over", "under", "left", "right"] + ["none", "filled", "open", "dot", "circle", "double-circle", "triangle", "sesame"] + elseif prop == 'text-indent' + let values = ["hanging", "each-line"] + elseif prop == 'text-orientation' + let values = ["mixed", "upright", "sideways", "sideways-right", "use-glyph-orientation"] + elseif prop == 'text-overflow' + let values = ["clip", "ellipsis"] + elseif prop == 'text-rendering' + let values = ["auto", "optimizeSpeed", "optimizeLegibility", "geometricPrecision"] + elseif prop == 'text-shadow' + let values = color_values + elseif prop == 'text-transform' + let values = ["capitalize", "uppercase", "lowercase", "full-width", "none"] + elseif prop == 'text-underline-position' + let values = ["auto", "under", "left", "right"] + elseif prop == 'touch-action' + let values = ["auto", "none", "pan-x", "pan-y", "manipulation", "pan-left", "pan-right", "pan-top", "pan-down"] + elseif prop == 'transform' + let values = ["matrix(", "translate(", "translateX(", "translateY(", "scale(", "scaleX(", "scaleY(", "rotate(", "skew(", "skewX(", "skewY(", "matrix3d(", "translate3d(", "translateZ(", "scale3d(", "scaleZ(", "rotate3d(", "rotateX(", "rotateY(", "rotateZ(", "perspective("] + elseif prop == 'transform-box' + let values = ["border-box", "fill-box", "view-box"] + elseif prop == 'transform-origin' + let values = ["left", "center", "right", "top", "bottom"] + elseif prop == 'transform-style' + let values = ["flat", "preserve-3d"] + elseif prop == 'top' + let values = ["auto"] + elseif prop == 'transition-property' + let values = ["all", "none"] + s:values + elseif prop == 'transition-duration' + let values = [] + elseif prop == 'transition-delay' + let values = [] + elseif prop == 'transition-timing-function' + let values = timing_functions + elseif prop == 'transition' + let values = ["all", "none"] + s:values + timing_functions + elseif prop == 'unicode-bidi' + let values = ["normal", "embed", "isolate", "bidi-override", "isolate-override", "plaintext"] + elseif prop == 'unicode-range' + let values = ["U+"] + elseif prop == 'user-zoom' + let values = ["zoom", "fixed"] + elseif prop == 'vertical-align' + let values = ["baseline", "sub", "super", "top", "text-top", "middle", "bottom", "text-bottom"] + elseif prop == 'visibility' + let values = ["visible", "hidden", "collapse"] + elseif prop == 'voice-volume' + let values = ["silent", "x-soft", "soft", "medium", "loud", "x-loud"] + elseif prop == 'voice-balance' + let values = ["left", "center", "right", "leftwards", "rightwards"] + elseif prop == 'voice-family' + let values = [] + elseif prop == 'voice-rate' + let values = ["normal", "x-slow", "slow", "medium", "fast", "x-fast"] + elseif prop == 'voice-pitch' + let values = ["absolute", "x-low", "low", "medium", "high", "x-high"] + elseif prop == 'voice-range' + let values = ["absolute", "x-low", "low", "medium", "high", "x-high"] + elseif prop == 'voice-stress' + let values = ["normal", "strong", "moderate", "none", "reduced "] + elseif prop == 'voice-duration' + let values = ["auto"] + elseif prop == 'white-space' + let values = ["normal", "pre", "nowrap", "pre-wrap", "pre-line"] + elseif prop == 'widows' + let values = [] + elseif prop == 'will-change' + let values = ["auto", "scroll-position", "contents"] + s:values + elseif prop == 'word-break' + let values = ["normal", "break-all", "keep-all"] + elseif prop == 'word-spacing' + let values = ["normal"] + elseif prop == 'word-wrap' + let values = ["normal", "break-word"] + elseif prop == 'writing-mode' + let values = ["horizontal-tb", "vertical-rl", "vertical-lr", "sideways-rl", "sideways-lr"] + elseif prop == 'z-index' + let values = ["auto"] + elseif prop == 'zoom' + let values = ["auto"] + else + " If no property match it is possible we are outside of {} and + " trying to complete pseudo-(class|element) + let element = tolower(matchstr(line, '\zs[a-zA-Z1-6]*\ze:[^:[:space:]]\{-}$')) + if stridx('a,abbr,address,area,article,aside,audio,b,base,bdi,bdo,bgsound,blockquote,body,br,button,canvas,caption,center,cite,code,col,colgroup,command,content,data,datalist,dd,del,details,dfn,dialog,div,dl,dt,element,em,embed,fieldset,figcaption,figure,font,footer,form,frame,frameset,head,header,hgroup,hr,html,i,iframe,image,img,input,ins,isindex,kbd,keygen,label,legend,li,link,main,map,mark,menu,menuitem,meta,meter,nav,nobr,noframes,noscript,object,ol,optgroup,option,output,p,param,picture,pre,progress,q,rp,rt,rtc,ruby,s,samp,script,section,select,shadow,small,source,span,strong,style,sub,summary,sup,table,tbody,td,template,textarea,tfoot,th,thead,time,title,tr,track,u,ul,var,video,wbr', ','.element.',') > -1 + let values = ["active", "any", "checked", "default", "dir(", "disabled", "empty", "enabled", "first", "first-child", "first-of-type", "fullscreen", "focus", "hover", "indeterminate", "in-range", "invalid", "lang(", "last-child", "last-of-type", "left", "link", "not(", "nth-child(", "nth-last-child(", "nth-last-of-type(", "nth-of-type(", "only-child", "only-of-type", "optional", "out-of-range", "read-only", "read-write", "required", "right", "root", "scope", "target", "valid", "visited", "first-line", "first-letter", "before", "after", "selection", "backdrop"] + else + return [] + endif + endif + + let values = wide_keywords + values + " Complete values + let entered_value = matchstr(line, '.\{-}\zs[a-zA-Z0-9#,.(_-]*$') + + for m in values + if m =~? '^'.entered_value + call add(res, m) + elseif m =~? entered_value + call add(res2, m) + endif + endfor + + return res + res2 + + elseif borders[max(keys(borders))] == 'closebrace' + + return [] + + elseif borders[max(keys(borders))] == 'exclam' + + " Complete values + let entered_imp = matchstr(line, '.\{-}!\s*\zs[a-zA-Z ]*$') + + let values = ["important"] + + for m in values + if m =~? '^'.entered_imp + call add(res, m) + endif + endfor + + return res + + elseif borders[max(keys(borders))] == 'atrule' + + let afterat = matchstr(line, '.*@\zs.*') + + if afterat =~ '\s' + + let atrulename = matchstr(line, '.*@\zs[a-zA-Z-]\+\ze') + + if atrulename == 'media' + let entered_atruleafter = matchstr(line, '.*@media\s\+\zs.*$') + + if entered_atruleafter =~ "([^)]*$" + let entered_atruleafter = matchstr(entered_atruleafter, '(\s*\zs[^)]*$') + let values = ["max-width", "min-width", "width", "max-height", "min-height", "height", "max-aspect-ration", "min-aspect-ration", "aspect-ratio", "orientation", "max-resolution", "min-resolution", "resolution", "scan", "grid", "update-frequency", "overflow-block", "overflow-inline", "max-color", "min-color", "color", "max-color-index", "min-color-index", "color-index", "monochrome", "inverted-colors", "pointer", "hover", "any-pointer", "any-hover", "light-level", "scripting"] + else + let values = ["screen", "print", "speech", "all", "not", "and", "("] + endif + + elseif atrulename == 'supports' + let entered_atruleafter = matchstr(line, '.*@supports\s\+\zs.*$') + + if entered_atruleafter =~ "([^)]*$" + let entered_atruleafter = matchstr(entered_atruleafter, '(\s*\zs.*$') + let values = s:values + else + let values = ["("] + endif + + elseif atrulename == 'charset' + let entered_atruleafter = matchstr(line, '.*@charset\s\+\zs.*$') + let values = [ + \ '"UTF-8";', '"ANSI_X3.4-1968";', '"ISO_8859-1:1987";', '"ISO_8859-2:1987";', '"ISO_8859-3:1988";', '"ISO_8859-4:1988";', '"ISO_8859-5:1988";', + \ '"ISO_8859-6:1987";', '"ISO_8859-7:1987";', '"ISO_8859-8:1988";', '"ISO_8859-9:1989";', '"ISO-8859-10";', '"ISO_6937-2-add";', '"JIS_X0201";', + \ '"JIS_Encoding";', '"Shift_JIS";', '"Extended_UNIX_Code_Packed_Format_for_Japanese";', '"Extended_UNIX_Code_Fixed_Width_for_Japanese";', + \ '"BS_4730";', '"SEN_850200_C";', '"IT";', '"ES";', '"DIN_66003";', '"NS_4551-1";', '"NF_Z_62-010";', '"ISO-10646-UTF-1";', '"ISO_646.basic:1983";', + \ '"INVARIANT";', '"ISO_646.irv:1983";', '"NATS-SEFI";', '"NATS-SEFI-ADD";', '"NATS-DANO";', '"NATS-DANO-ADD";', '"SEN_850200_B";', '"KS_C_5601-1987";', + \ '"ISO-2022-KR";', '"EUC-KR";', '"ISO-2022-JP";', '"ISO-2022-JP-2";', '"JIS_C6220-1969-jp";', '"JIS_C6220-1969-ro";', '"PT";', '"greek7-old";', + \ '"latin-greek";', '"NF_Z_62-010_(1973)";', '"Latin-greek-1";', '"ISO_5427";', '"JIS_C6226-1978";', '"BS_viewdata";', '"INIS";', '"INIS-8";', + \ '"INIS-cyrillic";', '"ISO_5427:1981";', '"ISO_5428:1980";', '"GB_1988-80";', '"GB_2312-80";', '"NS_4551-2";', '"videotex-suppl";', '"PT2";', + \ '"ES2";', '"MSZ_7795.3";', '"JIS_C6226-1983";', '"greek7";', '"ASMO_449";', '"iso-ir-90";', '"JIS_C6229-1984-a";', '"JIS_C6229-1984-b";', + \ '"JIS_C6229-1984-b-add";', '"JIS_C6229-1984-hand";', '"JIS_C6229-1984-hand-add";', '"JIS_C6229-1984-kana";', '"ISO_2033-1983";', + \ '"ANSI_X3.110-1983";', '"T.61-7bit";', '"T.61-8bit";', '"ECMA-cyrillic";', '"CSA_Z243.4-1985-1";', '"CSA_Z243.4-1985-2";', '"CSA_Z243.4-1985-gr";', + \ '"ISO_8859-6-E";', '"ISO_8859-6-I";', '"T.101-G2";', '"ISO_8859-8-E";', '"ISO_8859-8-I";', '"CSN_369103";', '"JUS_I.B1.002";', '"IEC_P27-1";', + \ '"JUS_I.B1.003-serb";', '"JUS_I.B1.003-mac";', '"greek-ccitt";', '"NC_NC00-10:81";', '"ISO_6937-2-25";', '"GOST_19768-74";', '"ISO_8859-supp";', + \ '"ISO_10367-box";', '"latin-lap";', '"JIS_X0212-1990";', '"DS_2089";', '"us-dk";', '"dk-us";', '"KSC5636";', '"UNICODE-1-1-UTF-7";', '"ISO-2022-CN";', + \ '"ISO-2022-CN-EXT";', '"ISO-8859-13";', '"ISO-8859-14";', '"ISO-8859-15";', '"ISO-8859-16";', '"GBK";', '"GB18030";', '"OSD_EBCDIC_DF04_15";', + \ '"OSD_EBCDIC_DF03_IRV";', '"OSD_EBCDIC_DF04_1";', '"ISO-11548-1";', '"KZ-1048";', '"ISO-10646-UCS-2";', '"ISO-10646-UCS-4";', '"ISO-10646-UCS-Basic";', + \ '"ISO-10646-Unicode-Latin1";', '"ISO-10646-J-1";', '"ISO-Unicode-IBM-1261";', '"ISO-Unicode-IBM-1268";', '"ISO-Unicode-IBM-1276";', + \ '"ISO-Unicode-IBM-1264";', '"ISO-Unicode-IBM-1265";', '"UNICODE-1-1";', '"SCSU";', '"UTF-7";', '"UTF-16BE";', '"UTF-16LE";', '"UTF-16";', '"CESU-8";', + \ '"UTF-32";', '"UTF-32BE";', '"UTF-32LE";', '"BOCU-1";', '"ISO-8859-1-Windows-3.0-Latin-1";', '"ISO-8859-1-Windows-3.1-Latin-1";', + \ '"ISO-8859-2-Windows-Latin-2";', '"ISO-8859-9-Windows-Latin-5";', '"hp-roman8";', '"Adobe-Standard-Encoding";', '"Ventura-US";', + \ '"Ventura-International";', '"DEC-MCS";', '"IBM850";', '"PC8-Danish-Norwegian";', '"IBM862";', '"PC8-Turkish";', '"IBM-Symbols";', '"IBM-Thai";', + \ '"HP-Legal";', '"HP-Pi-font";', '"HP-Math8";', '"Adobe-Symbol-Encoding";', '"HP-DeskTop";', '"Ventura-Math";', '"Microsoft-Publishing";', + \ '"Windows-31J";', '"GB2312";', '"Big5";', '"macintosh";', '"IBM037";', '"IBM038";', '"IBM273";', '"IBM274";', '"IBM275";', '"IBM277";', '"IBM278";', + \ '"IBM280";', '"IBM281";', '"IBM284";', '"IBM285";', '"IBM290";', '"IBM297";', '"IBM420";', '"IBM423";', '"IBM424";', '"IBM437";', '"IBM500";', '"IBM851";', + \ '"IBM852";', '"IBM855";', '"IBM857";', '"IBM860";', '"IBM861";', '"IBM863";', '"IBM864";', '"IBM865";', '"IBM868";', '"IBM869";', '"IBM870";', '"IBM871";', + \ '"IBM880";', '"IBM891";', '"IBM903";', '"IBM904";', '"IBM905";', '"IBM918";', '"IBM1026";', '"EBCDIC-AT-DE";', '"EBCDIC-AT-DE-A";', '"EBCDIC-CA-FR";', + \ '"EBCDIC-DK-NO";', '"EBCDIC-DK-NO-A";', '"EBCDIC-FI-SE";', '"EBCDIC-FI-SE-A";', '"EBCDIC-FR";', '"EBCDIC-IT";', '"EBCDIC-PT";', '"EBCDIC-ES";', + \ '"EBCDIC-ES-A";', '"EBCDIC-ES-S";', '"EBCDIC-UK";', '"EBCDIC-US";', '"UNKNOWN-8BIT";', '"MNEMONIC";', '"MNEM";', '"VISCII";', '"VIQR";', '"KOI8-R";', + \ '"HZ-GB-2312";', '"IBM866";', '"IBM775";', '"KOI8-U";', '"IBM00858";', '"IBM00924";', '"IBM01140";', '"IBM01141";', '"IBM01142";', '"IBM01143";', + \ '"IBM01144";', '"IBM01145";', '"IBM01146";', '"IBM01147";', '"IBM01148";', '"IBM01149";', '"Big5-HKSCS";', '"IBM1047";', '"PTCP154";', '"Amiga-1251";', + \ '"KOI7-switched";', '"BRF";', '"TSCII";', '"windows-1250";', '"windows-1251";', '"windows-1252";', '"windows-1253";', '"windows-1254";', '"windows-1255";', + \ '"windows-1256";', '"windows-1257";', '"windows-1258";', '"TIS-620";'] + + elseif atrulename == 'namespace' + let entered_atruleafter = matchstr(line, '.*@namespace\s\+\zs.*$') + let values = ["url("] + + elseif atrulename == 'document' + let entered_atruleafter = matchstr(line, '.*@document\s\+\zs.*$') + let values = ["url(", "url-prefix(", "domain(", "regexp("] + + elseif atrulename == 'import' + let entered_atruleafter = matchstr(line, '.*@import\s\+\zs.*$') + + if entered_atruleafter =~ "^[\"']" + let filestart = matchstr(entered_atruleafter, '^.\zs.*') + let files = split(glob(filestart.'*'), '\n') + let values = map(copy(files), '"\"".v:val') + + elseif entered_atruleafter =~ "^url(" + let filestart = matchstr(entered_atruleafter, "^url([\"']\\?\\zs.*") + let files = split(glob(filestart.'*'), '\n') + let values = map(copy(files), '"url(".v:val') + + else + let values = ['"', 'url('] + + endif + + else + return [] + + endif + + for m in values + if m =~? '^'.entered_atruleafter + if entered_atruleafter =~? '^"' && m =~? '^"' + let m = m[1:] + endif + if b:after =~? '"' && stridx(m, '"') > -1 + let m = m[0:stridx(m, '"')-1] + endif + call add(res, m) + elseif m =~? entered_atruleafter + if m =~? '^"' + let m = m[1:] + endif + call add(res2, m) + endif + endfor + + return res + res2 + + endif + + let values = ["charset", "page", "media", "import", "font-face", "namespace", "supports", "keyframes", "viewport", "document"] + + let entered_atrule = matchstr(line, '.*@\zs[a-zA-Z-]*$') + + for m in values + if m =~? '^'.entered_atrule + call add(res, m .' ') + elseif m =~? entered_atrule + call add(res2, m .' ') + endif + endfor + + return res + res2 + + endif + + return [] endfunction diff --git a/runtime/autoload/netrw.vim b/runtime/autoload/netrw.vim index 53668b15be..64c08e98fa 100644 --- a/runtime/autoload/netrw.vim +++ b/runtime/autoload/netrw.vim @@ -1,10 +1,10 @@ " netrw.vim: Handles file transfer and remote directory listing across " AUTOLOAD SECTION -" Date: Oct 23, 2015 -" Version: 154 +" Date: Feb 16, 2016 +" Version: 155 ASTRO-ONLY " Maintainer: Charles E Campbell <NdrOchip@ScampbellPfamily.AbizM-NOSPAM> " GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim -" Copyright: Copyright (C) 1999-2015 Charles E. Campbell {{{1 +" Copyright: Copyright (C) 2016 Charles E. Campbell {{{1 " Permission is hereby granted to use and distribute this code, " with or without modifications, provided that this copyright " notice is copied with it. Like anything else that's free, @@ -30,7 +30,7 @@ if v:version < 704 || !has("patch213") let s:needpatch213= 1 finish endif -let g:loaded_netrw = "v154" +let g:loaded_netrw = "v155" if !exists("s:NOTE") let s:NOTE = 0 let s:WARNING = 1 @@ -55,7 +55,7 @@ setl cpo&vim " Usage: netrw#ErrorMsg(s:NOTE | s:WARNING | s:ERROR,"some message",error-number) " netrw#ErrorMsg(s:NOTE | s:WARNING | s:ERROR,["message1","message2",...],error-number) " (this function can optionally take a list of messages) -" Oct 09, 2015 : max errnum currently is 102 +" Jan 19, 2016 : max errnum currently is 103 fun! netrw#ErrorMsg(level,msg,errnum) " call Dfunc("netrw#ErrorMsg(level=".a:level." msg<".a:msg."> errnum=".a:errnum.") g:netrw_use_errorwindow=".g:netrw_use_errorwindow) @@ -77,7 +77,7 @@ fun! netrw#ErrorMsg(level,msg,errnum) " (default) netrw creates a one-line window to show error/warning " messages (reliably displayed) - " record current window number for NetrwRestorePosn()'s benefit + " record current window number let s:winBeforeErr= winnr() " call Decho("s:winBeforeErr=".s:winBeforeErr,'~'.expand("<slnum>")) @@ -416,18 +416,20 @@ if !exists("g:netrw_localmovecmd") let g:netrw_localmovecmd= "" endif endif -if exists("g:netrw_local_rmdir") - let g:netrw_localrmdir= g:netrw_local_rmdir - call netrw#ErrorMsg(s:NOTE,"g:netrw_local_rmdir is deprecated in favor of g:netrw_localrmdir",86) -endif -if has("win32") || has("win95") || has("win64") || has("win16") - if g:netrw_cygwin - call s:NetrwInit("g:netrw_localrmdir","rmdir") - else - let g:netrw_localrmdir= expand("$COMSPEC")." /c rmdir" - endif -else - call s:NetrwInit("g:netrw_localrmdir","rmdir") +if v:version < 704 || !has("patch1109") + if exists("g:netrw_local_rmdir") + let g:netrw_localrmdir= g:netrw_local_rmdir + call netrw#ErrorMsg(s:NOTE,"g:netrw_local_rmdir is deprecated in favor of g:netrw_localrmdir",86) + endif + if has("win32") || has("win95") || has("win64") || has("win16") + if g:netrw_cygwin + call s:NetrwInit("g:netrw_localrmdir","rmdir") + else + let g:netrw_localrmdir= expand("$COMSPEC")." /c rmdir" + endif + else + call s:NetrwInit("g:netrw_localrmdir","rmdir") + endif endif call s:NetrwInit("g:netrw_liststyle" , s:THINLIST) " sanity checks @@ -489,6 +491,7 @@ endif call s:NetrwInit("g:netrw_special_syntax" , 0) call s:NetrwInit("g:netrw_ssh_browse_reject", '^total\s\+\d\+$') call s:NetrwInit("g:netrw_use_noswf" , 1) +call s:NetrwInit("g:netrw_sizestyle" ,"b") " Default values - t-w ---------- {{{3 call s:NetrwInit("g:netrw_timefmt","%c") if !exists("g:netrw_xstrlen") @@ -614,7 +617,7 @@ endif " == 4: Vexplore style == 5: Vexplore! " == 6: Texplore fun! netrw#Explore(indx,dosplit,style,...) -" call Dfunc("netrw#Explore(indx=".a:indx." dosplit=".a:dosplit." style=".a:style.",a:1<".a:1.">) &modified=".&modified." modifiable=".&modifiable." a:0=".a:0." win#".winnr()." buf#".bufnr("%")) +" call Dfunc("netrw#Explore(indx=".a:indx." dosplit=".a:dosplit." style=".a:style.",a:1<".a:1.">) &modified=".&modified." modifiable=".&modifiable." a:0=".a:0." win#".winnr()." buf#".bufnr("%")." ft=".&ft) " call Decho("tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("<slnum>")) if !exists("b:netrw_curdir") let b:netrw_curdir= getcwd() @@ -1165,7 +1168,8 @@ fun! netrw#Lexplore(count,rightside,...) " call Decho("t:netrw_lexbufnr#".t:netrw_lexbufnr.": close down netrw window",'~'.expand("<slnum>")) exe lexwinnr."wincmd w" let g:netrw_winsize = -winwidth(0) - let t:netrw_lexposn = netrw#SavePosn() + let t:netrw_lexposn = winsaveview() +" call Decho("saving posn to t:netrw_lexposn<".string(t:netrw_lexposn).">",'~'.expand("<slnum>")) " call Decho("saving t:netrw_lexposn",'~'.expand("<slnum>")) close if lexwinnr < curwin @@ -1205,7 +1209,8 @@ fun! netrw#Lexplore(count,rightside,...) let t:netrw_lexbufnr = bufnr("%") if exists("t:netrw_lexposn") " call Decho("restoring to t:netrw_lexposn",'~'.expand("<slnum>")) - call netrw#RestorePosn(t:netrw_lexposn) +" call Decho("restoring posn to t:netrw_lexposn<".string(t:netrw_lexposn).">",'~'.expand("<slnum>")) + call winrestview(t:netrw_lexposn) unlet t:netrw_lexposn endif endif @@ -1273,7 +1278,8 @@ endfun fun! netrw#MakeTgt(dname) " call Dfunc("netrw#MakeTgt(dname<".a:dname.">)") " simplify the target (eg. /abc/def/../ghi -> /abc/ghi) - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let s:netrwmftgt_islocal= (a:dname !~ '^\a\{3,}://') " call Decho("s:netrwmftgt_islocal=".s:netrwmftgt_islocal,'~'.expand("<slnum>")) if s:netrwmftgt_islocal @@ -1290,7 +1296,8 @@ fun! netrw#MakeTgt(dname) if g:netrw_fastbrowse <= 1 call s:NetrwRefresh((b:netrw_curdir !~ '\a\{3,}://'),b:netrw_curdir) endif - call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>"))" + call winrestview(svpos) " call Dret("netrw#MakeTgt") endfun @@ -1532,9 +1539,11 @@ endfun " netrw#Nread: save position, call netrw#NetRead(), and restore position {{{2 fun! netrw#Nread(mode,fname) " call Dfunc("netrw#Nread(mode=".a:mode." fname<".a:fname.">)") - call netrw#SavePosn() + let svpos= winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) call netrw#NetRead(a:mode,a:fname) - call netrw#RestorePosn() +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + call winrestview(svpos) if exists("w:netrw_liststyle") && w:netrw_liststyle != s:TREELIST if exists("w:netrw_bannercnt") @@ -1552,8 +1561,8 @@ fun! s:NetrwOptionRestore(vt) " call Decho("settings buf#".bufnr("%")."<".bufname("%").">: ".((&l:ma == 0)? "no" : "")."ma ".((&l:mod == 0)? "no" : "")."mod ".((&l:bl == 0)? "no" : "")."bl ".((&l:ro == 0)? "no" : "")."ro fo=".&l:fo." a:vt=".a:vt,'~'.expand("<slnum>")) if !exists("{a:vt}netrw_optionsave") if exists("s:nbcd_curpos_{bufnr('%')}") -" call Decho("restoring previous position (s:nbcd_curpos_".bufnr('%')." exists)",'~'.expand("<slnum>")) - NetrwKeepj call netrw#RestorePosn(s:nbcd_curpos_{bufnr('%')}) +" call Decho("restoring posn to s:nbcd_curpos_".bufnr('%')."<".string(s:nbcd_curpos_{bufnr('%')}).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(s:nbcd_curpos_{bufnr('%')}) " call Decho("win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> winnr($)=".winnr("$"),'~'.expand("<slnum>")) " call Decho("unlet s:nbcd_curpos_".bufnr('%'),'~'.expand("<slnum>")) unlet s:nbcd_curpos_{bufnr('%')} @@ -1629,8 +1638,10 @@ fun! s:NetrwOptionRestore(vt) setl directory= unlet {a:vt}netrw_swfkeep elseif &l:swf != {a:vt}netrw_swfkeep - " following line causes a Press ENTER in windows -- can't seem to work around it!!! - sil! let &l:swf= {a:vt}netrw_swfkeep + if !g:netrw_use_noswf + " following line causes a Press ENTER in windows -- can't seem to work around it!!! + sil! let &l:swf= {a:vt}netrw_swfkeep + endif unlet {a:vt}netrw_swfkeep endif endif @@ -1646,8 +1657,8 @@ fun! s:NetrwOptionRestore(vt) endif if exists("{a:vt}netrw_regslash")|sil! let @/= {a:vt}netrw_regslash|unlet {a:vt}netrw_regslash|endif if exists("s:nbcd_curpos_{bufnr('%')}") -" call Decho("restoring previous position (s:nbcd_curpos_".bufnr('%')." exists)",'~'.expand("<slnum>")) - NetrwKeepj call netrw#RestorePosn(s:nbcd_curpos_{bufnr('%')}) +" call Decho("restoring posn to s:nbcd_curpos_".bufnr('%')."<".string(s:nbcd_curpos_{bufnr('%')}).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(s:nbcd_curpos_{bufnr('%')}) " call Decho("unlet s:nbcd_curpos_".bufnr('%'),'~'.expand("<slnum>")) if exists("s:nbcd_curpos_".bufnr('%')) unlet s:nbcd_curpos_{bufnr('%')} @@ -1729,11 +1740,11 @@ fun! s:NetrwOptionSave(vt) let {a:vt}netrw_rokeep = &l:ro let {a:vt}netrw_selkeep = &l:sel let {a:vt}netrw_spellkeep = &l:spell - if g:netrw_use_noswf - let {a:vt}netrw_swfkeep = &l:swf + if !g:netrw_use_noswf + let {a:vt}netrw_swfkeep = &l:swf endif if has("clipboard") - let {a:vt}netrw_starkeep = @* + let {a:vt}netrw_starkeep = @* endif let {a:vt}netrw_tskeep = &l:ts let {a:vt}netrw_twkeep = &l:tw " textwidth @@ -2664,7 +2675,9 @@ fun! netrw#NetSource(...) " call Decho("exe so ".fnameescape(s:netrw_tmpfile),'~'.expand("<slnum>")) exe "so ".fnameescape(s:netrw_tmpfile) " call Decho("delete(".s:netrw_tmpfile.")",'~'.expand("<slnum>")) - call delete(s:netrw_tmpfile) + if delete(s:netrw_tmpfile) + call netrw#ErrorMsg(s:ERROR,"unable to delete directory <".s:netrw_tmpfile.">!",103) + endif unlet s:netrw_tmpfile else call netrw#ErrorMsg(s:ERROR,"unable to source <".a:{i}.">!",48) @@ -3504,7 +3517,11 @@ fun! s:NetrwBookHistSave() let savefile= s:NetrwHome()."/.netrwhist" 1split call s:NetrwEnew() - setl cino= com= cpo-=a cpo-=A fo=nroql2 tw=0 report=10000 noswf + if g:netrw_use_noswf + setl cino= com= cpo-=a cpo-=A fo=nroql2 tw=0 report=10000 noswf + else + setl cino= com= cpo-=a cpo-=A fo=nroql2 tw=0 report=10000 + endif setl nocin noai noci magic nospell nohid wig= noaw setl ma noro write if exists("+acd") | setl noacd | endif @@ -3566,6 +3583,7 @@ fun! s:NetrwBrowse(islocal,dirname) " This is useful when one edits a local file, then :e ., then :Rex if a:islocal && !exists("w:netrw_rexfile") && bufname("#") != "" let w:netrw_rexfile= bufname("#") +" call Decho("setting w:netrw_rexfile<".w:netrw_rexfile."> win#".winnr()) endif " s:NetrwBrowse : initialize history {{{3 @@ -3683,7 +3701,8 @@ fun! s:NetrwBrowse(islocal,dirname) " get/set-up buffer {{{3 " call Decho("saving position across a buffer refresh",'~'.expand("<slnum>")) - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let reusing= s:NetrwGetBuffer(a:islocal,dirname) " maintain markfile highlighting @@ -3792,10 +3811,18 @@ fun! s:NetrwBrowse(islocal,dirname) NetrwKeepj call s:NetrwCommands(a:islocal) NetrwKeepj call s:PerformListing(a:islocal) + " restore option(s) + call s:NetrwOptionRestore("w:") +" call Decho("tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("<slnum>")) + " If there is a rexposn: restore position with rexposn " Otherwise : set rexposn if exists("s:rexposn_".bufnr("%")) - NetrwKeepj call netrw#RestorePosn(s:rexposn_{bufnr('%')}) +" call Decho("restoring posn to s:rexposn_".bufnr('%')."<".string(s:rexposn_{bufnr('%')}).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(s:rexposn_{bufnr('%')}) + if exists("w:netrw_bannercnt") && line(".") < w:netrw_bannercnt + NetrwKeepj exe w:netrw_bannercnt + endif else NetrwKeepj call s:SetRexDir(a:islocal,b:netrw_curdir) endif @@ -3804,13 +3831,11 @@ fun! s:NetrwBrowse(islocal,dirname) " call Decho("set up balloon help: l:bexpr=".&l:bexpr,'~'.expand("<slnum>")) setl beval endif - call s:NetrwOptionRestore("w:") -" call Decho("tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("<slnum>")) " restore position if reusing -" call Decho("reusing=".reusing.": restoring position across buffer refresh",'~'.expand("<slnum>")) - call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + call winrestview(svpos) endif " The s:LocalBrowseRefresh() function is called by an autocmd @@ -3828,7 +3853,19 @@ endfun " differ from vim's. This function insures that netrw's idea of the current " directory is used. fun! s:NetrwFile(fname) -" call Dfunc("s:NetrwFile(fname<".a:fname.">)") +" call Dfunc("s:NetrwFile(fname<".a:fname.">) win#".winnr()) +" call Decho("g:netrw_keepdir =".(exists("g:netrw_keepdir")? g:netrw_keepdir : 'n/a')) +" call Decho("g:netrw_cygwin =".(exists("g:netrw_cygwin")? g:netrw_cygwin : 'n/a')) +" call Decho("g:netrw_liststyle=".(exists("g:netrw_liststyle")? g:netrw_liststyle : 'n/a')) +" call Decho("w:netrw_liststyle=".(exists("w:netrw_liststyle")? w:netrw_liststyle : 'n/a')) + + " clean up any leading treedepthstring + if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST + let fname= substitute(a:fname,'^'.s:treedepthstring.'\+','','') +" call Decho("clean up any leading treedepthstring: fname<".fname.">") + else + let fname= a:fname + endif if g:netrw_keepdir " vim's idea of the current directory possibly may differ from netrw's @@ -3837,28 +3874,28 @@ fun! s:NetrwFile(fname) endif if !exists("g:netrw_cygwin") && (has("win32") || has("win95") || has("win64") || has("win16")) - if a:fname =~ '^\' || a:fname =~ '^\a:\' + if fname =~ '^\' || fname =~ '^\a:\' " windows, but full path given - let ret= a:fname -" call Decho("windows+full path: isdirectory(".a:fname.")",'~'.expand("<slnum>")) + let ret= fname +" call Decho("windows+full path: isdirectory(".fname.")",'~'.expand("<slnum>")) else " windows, relative path given - let ret= s:ComposePath(b:netrw_curdir,a:fname) -" call Decho("windows+rltv path: isdirectory(".a:fname.")",'~'.expand("<slnum>")) + let ret= s:ComposePath(b:netrw_curdir,fname) +" call Decho("windows+rltv path: isdirectory(".fname.")",'~'.expand("<slnum>")) endif - elseif a:fname =~ '^/' + elseif fname =~ '^/' " not windows, full path given - let ret= a:fname -" call Decho("unix+full path: isdirectory(".a:fname.")",'~'.expand("<slnum>")) + let ret= fname +" call Decho("unix+full path: isdirectory(".fname.")",'~'.expand("<slnum>")) else " not windows, relative path given - let ret= s:ComposePath(b:netrw_curdir,a:fname) -" call Decho("unix+rltv path: isdirectory(".a:fname.")",'~'.expand("<slnum>")) + let ret= s:ComposePath(b:netrw_curdir,fname) +" call Decho("unix+rltv path: isdirectory(".fname.")",'~'.expand("<slnum>")) endif else " vim and netrw agree on the current directory - let ret= a:fname + let ret= fname " call Decho("vim and netrw agree on current directory (g:netrw_keepdir=".g:netrw_keepdir.")",'~'.expand("<slnum>")) endif @@ -3872,23 +3909,29 @@ fun! s:NetrwFileInfo(islocal,fname) " call Dfunc("s:NetrwFileInfo(islocal=".a:islocal." fname<".a:fname.">) b:netrw_curdir<".b:netrw_curdir.">") let ykeep= @@ if a:islocal + let lsopt= "-lsad" + if g:netrw_sizestyle =~ 'H' + let lsopt= "-lsadh" + elseif g:netrw_sizestyle =~ 'h' + let lsopt= "-lsadh --si" + endif if (has("unix") || has("macunix")) && executable("/bin/ls") if getline(".") == "../" - echo system("/bin/ls -lsad ".s:ShellEscape("..")) + echo system("/bin/ls ".lsopt." ".s:ShellEscape("..")) " call Decho("#1: echo system(/bin/ls -lsad ".s:ShellEscape(..).")",'~'.expand("<slnum>")) elseif w:netrw_liststyle == s:TREELIST && getline(".") !~ '^'.s:treedepthstring - echo system("/bin/ls -lsad ".s:ShellEscape(b:netrw_curdir)) + echo system("/bin/ls ".lsopt." ".s:ShellEscape(b:netrw_curdir)) " call Decho("#2: echo system(/bin/ls -lsad ".s:ShellEscape(b:netrw_curdir).")",'~'.expand("<slnum>")) elseif exists("b:netrw_curdir") - echo system("/bin/ls -lsad ".s:ShellEscape(s:ComposePath(b:netrw_curdir,a:fname))) + echo system("/bin/ls ".lsopt." ".s:ShellEscape(s:ComposePath(b:netrw_curdir,a:fname))) " call Decho("#3: echo system(/bin/ls -lsad ".s:ShellEscape(b:netrw_curdir.a:fname).")",'~'.expand("<slnum>")) else " call Decho('using ls '.a:fname." using cwd<".getcwd().">",'~'.expand("<slnum>")) - echo system("/bin/ls -lsad ".s:ShellEscape(s:NetrwFile(a:fname))) + echo system("/bin/ls ".lsopt." ".s:ShellEscape(s:NetrwFile(a:fname))) " call Decho("#5: echo system(/bin/ls -lsad ".s:ShellEscape(a:fname).")",'~'.expand("<slnum>")) endif else @@ -3901,6 +3944,9 @@ fun! s:NetrwFileInfo(islocal,fname) endif let t = getftime(s:NetrwFile(fname)) let sz = getfsize(s:NetrwFile(fname)) + if g:netrw_sizestyle =~ "[hH]" + let sz= s:NetrwHumanReadable(sz) + endif echo a:fname.": ".sz." ".strftime(g:netrw_timefmt,getftime(s:NetrwFile(fname))) " call Decho("fname.": ".sz." ".strftime(g:netrw_timefmt,getftime(fname)),'~'.expand("<slnum>")) endif @@ -4029,11 +4075,15 @@ fun! s:NetrwGetBuffer(islocal,dirname) let w:netrw_treebufnr= bufnr("%") " call Decho(" exe sil! keepalt file NetrwTreeListing ".fnameescape(s:netrw_treelistnum),'~'.expand("<slnum>")) exe 'sil! keepalt file NetrwTreeListing\ '.fnameescape(s:netrw_treelistnum) - setl bt=nofile noswf - nnoremap <silent> <buffer> [ :sil call <SID>TreeListMove('[')<cr> - nnoremap <silent> <buffer> ] :sil call <SID>TreeListMove(']')<cr> - nnoremap <silent> <buffer> [[ :sil call <SID>TreeListMove('[')<cr> - nnoremap <silent> <buffer> ]] :sil call <SID>TreeListMove(']')<cr> + if g:netrw_use_noswf + setl nobl bt=nofile noswf + else + setl nobl bt=nofile + endif + nnoremap <silent> <buffer> [[ :sil call <SID>TreeListMove('[[')<cr> + nnoremap <silent> <buffer> ]] :sil call <SID>TreeListMove(']]')<cr> + nnoremap <silent> <buffer> [] :sil call <SID>TreeListMove('[]')<cr> + nnoremap <silent> <buffer> ][ :sil call <SID>TreeListMove('][')<cr> " call Decho(" tree listing#".s:netrw_treelistnum." bufnr=".w:netrw_treebufnr,'~'.expand("<slnum>")) else " let v:errmsg = "" " Decho @@ -4197,7 +4247,7 @@ fun! s:NetrwGetWord() NetrwKeepj norm! 0 let dirname= substitute(getline('.'),'^\(\%(\S\+ \)*\S\+\).\{-}$','\1','e') - elseif w:netrw_liststyle == s:TREELIST + elseif exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST " call Decho("treelist handling",'~'.expand("<slnum>")) let dirname= substitute(getline('.'),'^\('.s:treedepthstring.'\)*','','e') let dirname= substitute(dirname,'\t -->.*$','','') @@ -4286,7 +4336,8 @@ fun! s:NetrwListStyle(islocal) let ykeep = @@ let fname = s:NetrwGetWord() if !exists("w:netrw_liststyle")|let w:netrw_liststyle= g:netrw_liststyle|endif - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let w:netrw_liststyle = (w:netrw_liststyle + 1) % s:MAXLIST " call Decho("fname<".fname.">",'~'.expand("<slnum>")) " call Decho("chgd w:netrw_liststyle to ".w:netrw_liststyle,'~'.expand("<slnum>")) @@ -4307,7 +4358,7 @@ fun! s:NetrwListStyle(islocal) " call Decho("use wide list",'~'.expand("<slnum>")) let g:netrw_list_cmd = substitute(g:netrw_list_cmd,' -l','','ge') - elseif w:netrw_liststyle == s:TREELIST + elseif exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST " call Decho("use tree list",'~'.expand("<slnum>")) let g:netrw_list_cmd = substitute(g:netrw_list_cmd,' -l','','ge') @@ -4334,7 +4385,8 @@ fun! s:NetrwListStyle(islocal) NetrwKeepj call s:NetrwCursor() " restore position; keep cursor on the filename - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) let @@= ykeep " call Dret("NetrwListStyle".(exists("w:netrw_liststyle")? ' : w:netrw_liststyle='.w:netrw_liststyle : "")) @@ -4350,7 +4402,8 @@ fun! s:NetrwBannerCtrl(islocal) let g:netrw_banner= !g:netrw_banner " refresh the listing - let svpos= netrw#SavePosn() + let svpos= winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) " keep cursor on the filename @@ -4385,7 +4438,8 @@ fun! s:NetrwBookmark(del,...) if exists("s:netrwmarkfilelist_{curbufnr}") " for every filename in the marked list " call Decho("bookmark every filename in marked list",'~'.expand("<slnum>")) - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let islocal= expand("%") !~ '^\a\{3,}://' for fname in s:netrwmarkfilelist_{curbufnr} if a:del|call s:DeleteBookmark(fname)|else|call s:MakeBookmark(fname)|endif @@ -4393,7 +4447,8 @@ fun! s:NetrwBookmark(del,...) let curdir = exists("b:netrw_curdir")? b:netrw_curdir : getcwd() call s:NetrwUnmarkList(curbufnr,curdir) NetrwKeepj call s:NetrwRefresh(islocal,s:NetrwBrowseChgDir(islocal,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) else let fname= s:NetrwGetWord() if a:del|call s:DeleteBookmark(fname)|else|call s:MakeBookmark(fname)|endif @@ -4528,9 +4583,9 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " call Decho("saving options",'~'.expand("<slnum>")) NetrwKeepj call s:NetrwOptionSave("s:") NetrwKeepj call s:NetrwSafeOptions() - let nbcd_curpos = netrw#SavePosn() + let nbcd_curpos = winsaveview() +" call Decho("saving posn to nbcd_curpos<".string(nbcd_curpos).">",'~'.expand("<slnum>")) let s:nbcd_curpos_{bufnr('%')} = nbcd_curpos -" call Decho("setting s:nbcd_curpos_".bufnr('%')." to SavePosn",'~'.expand("<slnum>")) if (has("win32") || has("win95") || has("win64") || has("win16")) let dirname = substitute(b:netrw_curdir,'\\','/','ge') else @@ -4553,7 +4608,8 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) setl ma noro nowrap NetrwKeepj call setline(line('.'),'" Quick Help: <F1>:help '.s:QuickHelp[g:netrw_quickhelp]) setl noma nomod nowrap - NetrwKeepj call netrw#RestorePosn(nbcd_curpos) +" call Decho("restoring posn to nbcd_curpos<".string(nbcd_curpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(nbcd_curpos) NetrwKeepj call s:NetrwOptionRestore("s:") " call Decho("ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("<slnum>")) endif @@ -4585,8 +4641,8 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " call Decho('edit-a-file: case "handling a file": newdir<'.newdir.'> !~ dirpat<'.dirpat.">",'~'.expand("<slnum>")) " save position for benefit of Rexplore - let s:rexposn_{bufnr("%")}= netrw#SavePosn() -" call Decho("edit-a-file: setting s:rexposn_".bufnr("%")."<".bufname("%")."> to SavePosn",'~'.expand("<slnum>")) + let s:rexposn_{bufnr("%")}= winsaveview() +" call Decho("edit-a-file: saving posn to s:rexposn_".bufnr("%")."<".string(s:rexposn_{bufnr("%")}).">",'~'.expand("<slnum>")) " call Decho("edit-a-file: win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> ft=".&ft,'~'.expand("<slnum>")) " call Decho("edit-a-file: w:netrw_liststyle=".(exists("w:netrw_liststyle")? w:netrw_liststyle : 'n/a')." w:netrw_treedict:".(exists("w:netrw_treedict")? "exists" : 'n/a')." newdir<".newdir.">",'~'.expand("<slnum>")) @@ -4602,6 +4658,7 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " call Decho("edit-a-file: dirname<".dirname.">",'~'.expand("<slnum>")) " call Decho("edit-a-file: tree listing",'~'.expand("<slnum>")) elseif newdir =~ '^\(/\|\a:\)' +" call Decho("edit-a-file: handle an url or path starting with /: <".newdir.">") let dirname= newdir else let dirname= s:ComposePath(dirname,newdir) @@ -4609,8 +4666,9 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " call Decho("edit-a-file: handling a file: dirname<".dirname."> (a:0=".a:0.")",'~'.expand("<slnum>")) " this lets netrw#BrowseX avoid the edit if a:0 < 1 -" call Decho("edit-a-file: set up windows for editing<".fnameescape(dirname)."> didsplit=".(exists("s:didsplit")? s:didsplit : "doesn't exist"),'~'.expand("<slnum>")) +" call Decho("edit-a-file: (a:0=".a:0."<1) set up windows for editing<".fnameescape(dirname)."> didsplit=".(exists("s:didsplit")? s:didsplit : "doesn't exist"),'~'.expand("<slnum>")) NetrwKeepj call s:NetrwOptionRestore("s:") + let curdir= b:netrw_curdir if !exists("s:didsplit") " call Decho("edit-a-file: s:didsplit does not exist; g:netrw_browse_split=".string(g:netrw_browse_split)." win#".winnr(),'~'.expand("<slnum>")) if type(g:netrw_browse_split) == 3 @@ -4627,6 +4685,7 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) if !&ea keepalt wincmd _ endif + call s:SetRexDir(a:islocal,b:netrw_curdir) elseif g:netrw_browse_split == 2 " vertically splitting the window first " call Decho("edit-a-file: vertically splitting window prior to edit",'~'.expand("<slnum>")) @@ -4634,10 +4693,12 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) if !&ea keepalt wincmd | endif + call s:SetRexDir(a:islocal,b:netrw_curdir) elseif g:netrw_browse_split == 3 " open file in new tab " call Decho("edit-a-file: opening new tab prior to edit",'~'.expand("<slnum>")) keepalt tabnew + call s:SetRexDir(a:islocal,b:netrw_curdir) elseif g:netrw_browse_split == 4 " act like "P" (ie. open previous window) " call Decho("edit-a-file: use previous window for edit",'~'.expand("<slnum>")) @@ -4646,6 +4707,7 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " call Dret("s:NetrwBrowseChgDir") return endif + call s:SetRexDir(a:islocal,b:netrw_curdir) else " handling a file, didn't split, so remove menu " call Decho("edit-a-file: handling a file+didn't split, so remove menu",'~'.expand("<slnum>")) @@ -4663,6 +4725,7 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) endif exe "NetrwKeepj keepalt ".g:netrw_chgwin."wincmd w" endif + call s:SetRexDir(a:islocal,curdir) endif endif @@ -4802,7 +4865,7 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " call Decho("tree-list: w:netrw_treedict<".string(w:netrw_treedict).">",'~'.expand("<slnum>")) " search treedict for tree dir as-is -" call Decho("search treedict for tree dir as-is",'~'.expand("<slnum>")) +" call Decho("tree-list: search treedict for tree dir as-is",'~'.expand("<slnum>")) if has_key(w:netrw_treedict,treedir) " call Decho('tree-list: ....searched for treedir<'.treedir.'> : found it!','~'.expand("<slnum>")) let haskey= 1 @@ -4811,7 +4874,7 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) endif " search treedict for treedir with a [/@] appended -" call Decho("search treedict for treedir with a [/@] appended",'~'.expand("<slnum>")) +" call Decho("tree-list: search treedict for treedir with a [/@] appended",'~'.expand("<slnum>")) if !haskey && treedir !~ '[/@]$' if has_key(w:netrw_treedict,treedir."/") let treedir= treedir."/" @@ -4823,7 +4886,7 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) endif " search treedict for treedir with any trailing / elided -" call Decho("search treedict for treedir with any trailing / elided",'~'.expand("<slnum>")) +" call Decho("tree-list: search treedict for treedir with any trailing / elided",'~'.expand("<slnum>")) if !haskey && treedir =~ '/$' let treedir= substitute(treedir,'/$','','') if has_key(w:netrw_treedict,treedir) @@ -4967,14 +5030,15 @@ fun! netrw#BrowseX(fname,remote) " call Dfunc("netrw#BrowseX(fname<".a:fname."> remote=".a:remote.")") " if its really just a directory, then do a "gf" instead - if a:fname =~ '/$' + if (a:remote == 0 && isdirectory(a:fname)) || (a:remote == 1 && fname =~ '/$' && fname !~ '^https\=:') norm! gf " call Dret("netrw#BrowseX : did gf instead") endif let ykeep = @@ - let screenposn = netrw#SavePosn() + let screenposn = winsaveview() +" call Decho("saving posn to screenposn<".string(screenposn).">",'~'.expand("<slnum>")) " need to save and restore aw setting as gx can invoke this function from non-netrw buffers let awkeep = &aw @@ -4996,7 +5060,8 @@ fun! netrw#BrowseX(fname,remote) endif endfor endif - call netrw#RestorePosn(screenposn) +" call Decho("restoring posn to screenposn<".string(screenposn).">,'~'.expand("<slnum>"))" + call winrestview(screenposn) let @@= ykeep let &aw= awkeep " call Dret("netrw#BrowseX : coredump handler invoked") @@ -5167,7 +5232,8 @@ fun! netrw#BrowseX(fname,remote) exe "sil! NetrwKeepj norm! \<c-o>" " redraw! endif - call netrw#RestorePosn(screenposn) +" call Decho("restoring posn to screenposn<".string(screenposn).">",'~'.expand("<slnum>")) + call winrestview(screenposn) let @@ = ykeep let &aw= awkeep @@ -5310,6 +5376,32 @@ fun! s:NetrwForceChgDir(islocal,newdir) endfun " --------------------------------------------------------------------- +" s:NetrwGlob: does glob() if local, remote listing otherwise {{{2 +fun! s:NetrwGlob(direntry,expr) +" call Dfunc("s:NetrwGlob(direntry<".a:direntry."> expr<".a:expr.">)") + if netrw#CheckIfRemote() + keepalt 1sp + keepalt enew + let keep_liststyle = w:netrw_liststyle + let w:netrw_liststyle = s:THINLIST + if s:NetrwRemoteListing() == 0 + keepj keepalt %s@/@@ + let filelist= getline(1,$) + q! + else + " remote listing error -- leave treedict unchanged + let filelist= w:netrw_treedict[a:direntry] + endif + let w:netrw_liststyle= keep_liststyle + else + let filelist= glob(s:ComposePath(a:direntry,a:expr),0,1,1) + let filelist= map(filelist,'substitute(v:val, "^.*/", "", "")') + endif +" call Dret("s:NetrwGlob ".string(filelist)) + return filelist +endfun + +" --------------------------------------------------------------------- " s:NetrwForceFile: (gf support) Force treatment as a file {{{2 fun! s:NetrwForceFile(islocal,newfile) " call Dfunc("s:NetrwForceFile(islocal=".a:islocal." newdir<".a:newfile.">)") @@ -5336,7 +5428,8 @@ endfun fun! s:NetrwHide(islocal) " call Dfunc("NetrwHide(islocal=".a:islocal.") g:netrw_hide=".g:netrw_hide) let ykeep= @@ - let svpos= netrw#SavePosn() + let svpos= winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) if exists("s:netrwmarkfilelist_{bufnr('%')}") " call Decho("((g:netrw_hide == 1)? "unhide" : "hide")." files in markfilelist<".string(s:netrwmarkfilelist_{bufnr("%")}).">",'~'.expand("<slnum>")) @@ -5378,7 +5471,8 @@ fun! s:NetrwHide(islocal) endif NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) let @@= ykeep " call Dret("NetrwHide") endfun @@ -5390,7 +5484,8 @@ fun! s:NetrwHideEdit(islocal) let ykeep= @@ " save current cursor position - let svpos= netrw#SavePosn() + let svpos= winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) " get new hiding list from user call inputsave() @@ -5403,7 +5498,8 @@ fun! s:NetrwHideEdit(islocal) sil NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,"./")) " restore cursor position - call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + call winrestview(svpos) let @@= ykeep " call Dret("NetrwHideEdit") @@ -5415,7 +5511,8 @@ fun! s:NetrwHidden(islocal) " call Dfunc("s:NetrwHidden()") let ykeep= @@ " save current position - let svpos= netrw#SavePosn() + let svpos= winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) if g:netrw_list_hide =~ '\(^\|,\)\\(^\\|\\s\\s\\)\\zs\\.\\S\\+' " remove pattern from hiding list @@ -5428,7 +5525,8 @@ fun! s:NetrwHidden(islocal) " refresh screen and return to saved position NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) let @@= ykeep " call Dret("s:NetrwHidden") endfun @@ -5540,10 +5638,10 @@ fun! s:NetrwServerEdit(islocal,fname) if (islocal && isdirectory(s:NetrwFile(a:fname))) || (!islocal && a:fname =~ '/$') " handle directories in the local window -- not in the remote vim server - " user must have closed the NETRWSERVER window. Treat as a normal editing from netrw. + " user must have closed the NETRWSERVER window. Treat as normal editing from netrw. " call Decho("handling directory in client window",'~'.expand("<slnum>")) let g:netrw_browse_split= 0 - if exists("s:netrw_browse_split_".winnr()) + if exists("s:netrw_browse_split") && exists("s:netrw_browse_split_".winnr()) let g:netrw_browse_split= s:netrw_browse_split_{winnr()} unlet s:netrw_browse_split_{winnr()} endif @@ -5820,9 +5918,11 @@ fun! s:NetrwMakeDir(usrhost) if v:shell_error == 0 " refresh listing " call Decho("refresh listing",'~'.expand("<slnum>")) - let svpos= netrw#SavePosn() + let svpos= winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./')) - call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + call winrestview(svpos) elseif !exists("g:netrw_quiet") call netrw#ErrorMsg(s:ERROR,"unable to make directory<".newdirname.">",26) endif @@ -5836,9 +5936,11 @@ fun! s:NetrwMakeDir(usrhost) call s:NetrwExe("sil! !".mkdircmd." ".s:ShellEscape(newdirname,1)) if v:shell_error == 0 " refresh listing - let svpos= netrw#SavePosn() + let svpos= winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) elseif !exists("g:netrw_quiet") NetrwKeepj call netrw#ErrorMsg(s:ERROR,"unable to make directory<".newdirname.">",27) endif @@ -5846,7 +5948,8 @@ fun! s:NetrwMakeDir(usrhost) elseif b:netrw_method == 2 " Remote mkdir: using ftp+.netrc - let svpos= netrw#SavePosn() + let svpos= winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) " call Decho("b:netrw_curdir<".b:netrw_curdir.">",'~'.expand("<slnum>")) if exists("b:netrw_fname") " call Decho("b:netrw_fname<".b:netrw_fname.">",'~'.expand("<slnum>")) @@ -5856,11 +5959,13 @@ fun! s:NetrwMakeDir(usrhost) endif call s:NetrwRemoteFtpCmd(remotepath,g:netrw_remote_mkdir.' "'.newdirname.'"') NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) elseif b:netrw_method == 3 " Remote mkdir: using ftp + machine, id, passwd, and fname (ie. no .netrc) - let svpos= netrw#SavePosn() + let svpos= winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) " call Decho("b:netrw_curdir<".b:netrw_curdir.">",'~'.expand("<slnum>")) if exists("b:netrw_fname") " call Decho("b:netrw_fname<".b:netrw_fname.">",'~'.expand("<slnum>")) @@ -5870,7 +5975,8 @@ fun! s:NetrwMakeDir(usrhost) endif call s:NetrwRemoteFtpCmd(remotepath,g:netrw_remote_mkdir.' "'.newdirname.'"') NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) endif let @@= ykeep @@ -5884,22 +5990,30 @@ fun! s:TreeSqueezeDir(islocal) if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treedict") " its a tree-listing style let curdepth = substitute(getline('.'),'^\(\%('.s:treedepthstring.'\)*\)[^'.s:treedepthstring.'].\{-}$','\1','e') - let iline = line(".") - 1 let stopline = (exists("w:netrw_bannercnt")? (w:netrw_bannercnt + 1) : 1) -" call Decho("curdepth=".curdepth,'~'.expand("<slnum>")) + let depth = strchars(substitute(curdepth,' ','','g')) + let srch = -1 +" call Decho("curdepth<".curdepth.'>','~'.expand("<slnum>")) +" call Decho("depth =".depth,'~'.expand("<slnum>")) " call Decho("stopline#".stopline,'~'.expand("<slnum>")) -" call Decho("starting with line#".line(".").": ".getline('.'),'~'.expand("<slnum>")) - while iline > stopline - " find a line that has less depth - let depth = substitute(getline('.'),'^\(\%('.s:treedepthstring.'\)*\)[^'.s:treedepthstring.'].\{-}$','\1','e') -" call Decho("considering line#".line(".").": ".getline('.'),'~'.expand("<slnum>")) - if depth < curdepth - break - endif - norm! k - endwhile -" call Decho("squeezing at line#".line(".").": ".getline('.'),'~'.expand("<slnum>")) - call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,s:NetrwGetWord())) +" call Decho("curline#".line(".")."<".getline('.').'>','~'.expand("<slnum>")) + if depth >= 2 + NetrwKeepj norm! 0 + let curdepthm1= substitute(curdepth,'^'.s:treedepthstring,'','') + let srch = search('^'.curdepthm1.'\%('.s:treedepthstring.'\)\@!','bW',stopline) +" call Decho("curdepthm1<".curdepthm1.'>','~'.expand("<slnum>")) +" call Decho("case depth>=2: srch<".srch.'>','~'.expand("<slnum>")) + elseif depth == 1 + NetrwKeepj norm! 0 + let treedepthchr= substitute(s:treedepthstring,' ','','') + let srch = search('^[^'.treedepthchr.']','bW',stopline) +" call Decho("case depth==1: srch<".srch.'>','~'.expand("<slnum>")) + endif + if srch > 0 +" call Decho("squeezing at line#".line(".").": ".getline('.'),'~'.expand("<slnum>")) + call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,s:NetrwGetWord())) + exe srch + endif endif " call Dret("s:TreeSqueezeDir") endfun @@ -5927,23 +6041,24 @@ fun! s:NetrwMaps(islocal) if a:islocal " call Decho("make local maps",'~'.expand("<slnum>")) " local normal-mode maps - nnoremap <buffer> <silent> <nowait> a :call <SID>NetrwHide(1)<cr> - nnoremap <buffer> <silent> <nowait> % :call <SID>NetrwOpenFile(1)<cr> - nnoremap <buffer> <silent> <nowait> c :call <SID>NetrwLcd(b:netrw_curdir)<cr> + nnoremap <buffer> <silent> <nowait> a :<c-u>call <SID>NetrwHide(1)<cr> + nnoremap <buffer> <silent> <nowait> - :<c-u>call <SID>NetrwBrowseUpDir(1)<cr> + nnoremap <buffer> <silent> <nowait> % :<c-u>call <SID>NetrwOpenFile(1)<cr> + nnoremap <buffer> <silent> <nowait> c :<c-u>call <SID>NetrwLcd(b:netrw_curdir)<cr> nnoremap <buffer> <silent> <nowait> C :<c-u>call <SID>NetrwSetChgwin()<cr> - nnoremap <buffer> <silent> <nowait> <cr> :call netrw#LocalBrowseCheck(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord()))<cr> - nnoremap <buffer> <silent> <nowait> <s-cr> :call <SID>TreeSqueezeDir(1)<cr> - nnoremap <buffer> <silent> <nowait> <c-r> :call <SID>NetrwServerEdit(3,<SID>NetrwGetWord())<cr> - nnoremap <buffer> <silent> <nowait> d :call <SID>NetrwMakeDir("")<cr> - nnoremap <buffer> <silent> <nowait> - :call <SID>NetrwBrowseUpDir(1)<cr> + nnoremap <buffer> <silent> <nowait> <cr> :<c-u>call netrw#LocalBrowseCheck(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord()))<cr> + nnoremap <buffer> <silent> <nowait> <c-r> :<c-u>call <SID>NetrwServerEdit(3,<SID>NetrwGetWord())<cr> + nnoremap <buffer> <silent> <nowait> d :<c-u>call <SID>NetrwMakeDir("")<cr> nnoremap <buffer> <silent> <nowait> gb :<c-u>call <SID>NetrwBookHistHandler(1,b:netrw_curdir)<cr> nnoremap <buffer> <silent> <nowait> gd :<c-u>call <SID>NetrwForceChgDir(1,<SID>NetrwGetWord())<cr> nnoremap <buffer> <silent> <nowait> gf :<c-u>call <SID>NetrwForceFile(1,<SID>NetrwGetWord())<cr> nnoremap <buffer> <silent> <nowait> gh :<c-u>call <SID>NetrwHidden(1)<cr> nnoremap <buffer> <silent> <nowait> gn :<c-u>call netrw#SetTreetop(<SID>NetrwGetWord())<cr> nnoremap <buffer> <silent> <nowait> gp :<c-u>call <SID>NetrwChgPerm(1,b:netrw_curdir)<cr> - nnoremap <buffer> <silent> <nowait> I :call <SID>NetrwBannerCtrl(1)<cr> - nnoremap <buffer> <silent> <nowait> i :call <SID>NetrwListStyle(1)<cr> + nnoremap <buffer> <silent> <nowait> I :<c-u>call <SID>NetrwBannerCtrl(1)<cr> + nnoremap <buffer> <silent> <nowait> i :<c-u>call <SID>NetrwListStyle(1)<cr> + nnoremap <buffer> <silent> <nowait> ma :<c-u>call <SID>NetrwMarkFileArgList(1,0)<cr> + nnoremap <buffer> <silent> <nowait> mA :<c-u>call <SID>NetrwMarkFileArgList(1,1)<cr> nnoremap <buffer> <silent> <nowait> mb :<c-u>call <SID>NetrwBookHistHandler(0,b:netrw_curdir)<cr> nnoremap <buffer> <silent> <nowait> mB :<c-u>call <SID>NetrwBookHistHandler(6,b:netrw_curdir)<cr> nnoremap <buffer> <silent> <nowait> mc :<c-u>call <SID>NetrwMarkFileCopy(1)<cr> @@ -5957,104 +6072,110 @@ fun! s:NetrwMaps(islocal) nnoremap <buffer> <silent> <nowait> mp :<c-u>call <SID>NetrwMarkFilePrint(1)<cr> nnoremap <buffer> <silent> <nowait> mr :<c-u>call <SID>NetrwMarkFileRegexp(1)<cr> nnoremap <buffer> <silent> <nowait> ms :<c-u>call <SID>NetrwMarkFileSource(1)<cr> - nnoremap <buffer> <silent> <nowait> mt :<c-u>call <SID>NetrwMarkFileTgt(1)<cr> nnoremap <buffer> <silent> <nowait> mT :<c-u>call <SID>NetrwMarkFileTag(1)<cr> + nnoremap <buffer> <silent> <nowait> mt :<c-u>call <SID>NetrwMarkFileTgt(1)<cr> nnoremap <buffer> <silent> <nowait> mu :<c-u>call <SID>NetrwUnMarkFile(1)<cr> nnoremap <buffer> <silent> <nowait> mv :<c-u>call <SID>NetrwMarkFileVimCmd(1)<cr> nnoremap <buffer> <silent> <nowait> mx :<c-u>call <SID>NetrwMarkFileExe(1,0)<cr> nnoremap <buffer> <silent> <nowait> mX :<c-u>call <SID>NetrwMarkFileExe(1,1)<cr> nnoremap <buffer> <silent> <nowait> mz :<c-u>call <SID>NetrwMarkFileCompress(1)<cr> - nnoremap <buffer> <silent> <nowait> O :call <SID>NetrwObtain(1)<cr> + nnoremap <buffer> <silent> <nowait> O :<c-u>call <SID>NetrwObtain(1)<cr> nnoremap <buffer> <silent> <nowait> o :call <SID>NetrwSplit(3)<cr> - nnoremap <buffer> <silent> <nowait> p :call <SID>NetrwPreview(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1))<cr> - nnoremap <buffer> <silent> <nowait> P :call <SID>NetrwPrevWinOpen(1)<cr> + nnoremap <buffer> <silent> <nowait> p :<c-u>call <SID>NetrwPreview(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1))<cr> + nnoremap <buffer> <silent> <nowait> P :<c-u>call <SID>NetrwPrevWinOpen(1)<cr> nnoremap <buffer> <silent> <nowait> qb :<c-u>call <SID>NetrwBookHistHandler(2,b:netrw_curdir)<cr> nnoremap <buffer> <silent> <nowait> qf :<c-u>call <SID>NetrwFileInfo(1,<SID>NetrwGetWord())<cr> nnoremap <buffer> <silent> <nowait> qF :<c-u>call <SID>NetrwMarkFileQFEL(1,getqflist())<cr> - nnoremap <buffer> <silent> <nowait> r :let g:netrw_sort_direction= (g:netrw_sort_direction =~ 'n')? 'r' : 'n'<bar>exe "norm! 0"<bar>call <SID>NetrwRefresh(1,<SID>NetrwBrowseChgDir(1,'./'))<cr> + nnoremap <buffer> <silent> <nowait> qL :<c-u>call <SID>NetrwMarkFileQFEL(1,getloclist(v:count))<cr> + nnoremap <buffer> <silent> <nowait> r :<c-u>let g:netrw_sort_direction= (g:netrw_sort_direction =~ 'n')? 'r' : 'n'<bar>exe "norm! 0"<bar>call <SID>NetrwRefresh(1,<SID>NetrwBrowseChgDir(1,'./'))<cr> nnoremap <buffer> <silent> <nowait> s :call <SID>NetrwSortStyle(1)<cr> - nnoremap <buffer> <silent> <nowait> S :call <SID>NetSortSequence(1)<cr> + nnoremap <buffer> <silent> <nowait> S :<c-u>call <SID>NetSortSequence(1)<cr> + nnoremap <buffer> <silent> <nowait> Tb :<c-u>call <SID>NetrwSetTgt(1,'b',v:count1)<cr> nnoremap <buffer> <silent> <nowait> t :call <SID>NetrwSplit(4)<cr> - nnoremap <buffer> <silent> <nowait> Tb :<c-u>call <SID>NetrwSetTgt('b',v:count1)<cr> - nnoremap <buffer> <silent> <nowait> Th :<c-u>call <SID>NetrwSetTgt('h',v:count)<cr> + nnoremap <buffer> <silent> <nowait> Th :<c-u>call <SID>NetrwSetTgt(1,'h',v:count)<cr> nnoremap <buffer> <silent> <nowait> u :<c-u>call <SID>NetrwBookHistHandler(4,expand("%"))<cr> nnoremap <buffer> <silent> <nowait> U :<c-u>call <SID>NetrwBookHistHandler(5,expand("%"))<cr> nnoremap <buffer> <silent> <nowait> v :call <SID>NetrwSplit(5)<cr> - nnoremap <buffer> <silent> <nowait> x :call netrw#BrowseX(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),0),0)"<cr> - nnoremap <buffer> <silent> <nowait> X :call <SID>NetrwLocalExecute(expand("<cword>"))"<cr> - " local insert-mode maps - inoremap <buffer> <silent> <nowait> a <c-o>:call <SID>NetrwHide(1)<cr> - inoremap <buffer> <silent> <nowait> c <c-o>:exe "NetrwKeepj lcd ".fnameescape(b:netrw_curdir)<cr> - inoremap <buffer> <silent> <nowait> c <c-o>:call <SID>NetrwLcd(b:netrw_curdir)<cr> - inoremap <buffer> <silent> <nowait> C <c-o>:call <SID>NetrwSetChgwin()<cr> - inoremap <buffer> <silent> <nowait> % <c-o>:call <SID>NetrwOpenFile(1)<cr> - inoremap <buffer> <silent> <nowait> - <c-o>:call <SID>NetrwBrowseUpDir(1)<cr> - inoremap <buffer> <silent> <nowait> <cr> <c-o>:call netrw#LocalBrowseCheck(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord()))<cr> - inoremap <buffer> <silent> <nowait> <s-cr> <c-o>:call <SID>TreeSqueezeDir(1)<cr> - inoremap <buffer> <silent> <nowait> d <c-o>:call <SID>NetrwMakeDir("")<cr> - inoremap <buffer> <silent> <nowait> gb <c-o>:<c-u>call <SID>NetrwBookHistHandler(1,b:netrw_curdir)<cr> - inoremap <buffer> <silent> <nowait> gh <c-o>:<c-u>call <SID>NetrwHidden(1)<cr> - nnoremap <buffer> <silent> <nowait> gn :<c-u>call netrw#SetTreetop(<SID>NetrwGetWord())<cr> - inoremap <buffer> <silent> <nowait> gp <c-o>:<c-u>call <SID>NetrwChgPerm(1,b:netrw_curdir)<cr> - inoremap <buffer> <silent> <nowait> I <c-o>:call <SID>NetrwBannerCtrl(1)<cr> - inoremap <buffer> <silent> <nowait> i <c-o>:call <SID>NetrwListStyle(1)<cr> - inoremap <buffer> <silent> <nowait> mb <c-o>:<c-u>call <SID>NetrwBookHistHandler(0,b:netrw_curdir)<cr> - inoremap <buffer> <silent> <nowait> mB <c-o>:<c-u>call <SID>NetrwBookHistHandler(6,b:netrw_curdir)<cr> - inoremap <buffer> <silent> <nowait> mc <c-o>:<c-u>call <SID>NetrwMarkFileCopy(1)<cr> - inoremap <buffer> <silent> <nowait> md <c-o>:<c-u>call <SID>NetrwMarkFileDiff(1)<cr> - inoremap <buffer> <silent> <nowait> me <c-o>:<c-u>call <SID>NetrwMarkFileEdit(1)<cr> - inoremap <buffer> <silent> <nowait> mf <c-o>:<c-u>call <SID>NetrwMarkFile(1,<SID>NetrwGetWord())<cr> - inoremap <buffer> <silent> <nowait> mg <c-o>:<c-u>call <SID>NetrwMarkFileGrep(1)<cr> - inoremap <buffer> <silent> <nowait> mh <c-o>:<c-u>call <SID>NetrwMarkHideSfx(1)<cr> - inoremap <buffer> <silent> <nowait> mm <c-o>:<c-u>call <SID>NetrwMarkFileMove(1)<cr> - inoremap <buffer> <silent> <nowait> mp <c-o>:<c-u>call <SID>NetrwMarkFilePrint(1)<cr> - inoremap <buffer> <silent> <nowait> mr <c-o>:<c-u>call <SID>NetrwMarkFileRegexp(1)<cr> - inoremap <buffer> <silent> <nowait> ms <c-o>:<c-u>call <SID>NetrwMarkFileSource(1)<cr> - inoremap <buffer> <silent> <nowait> mT <c-o>:<c-u>call <SID>NetrwMarkFileTag(1)<cr> - inoremap <buffer> <silent> <nowait> mt <c-o>:<c-u>call <SID>NetrwMarkFileTgt(1)<cr> - inoremap <buffer> <silent> <nowait> mu <c-o>:<c-u>call <SID>NetrwUnMarkFile(1)<cr> - inoremap <buffer> <silent> <nowait> mv <c-o>:<c-u>call <SID>NetrwMarkFileVimCmd(1)<cr> - inoremap <buffer> <silent> <nowait> mx <c-o>:<c-u>call <SID>NetrwMarkFileExe(1,0)<cr> - inoremap <buffer> <silent> <nowait> mX <c-o>:<c-u>call <SID>NetrwMarkFileExe(1,1)<cr> - inoremap <buffer> <silent> <nowait> mz <c-o>:<c-u>call <SID>NetrwMarkFileCompress(1)<cr> - inoremap <buffer> <silent> <nowait> O <c-o>:call <SID>NetrwObtain(1)<cr> - inoremap <buffer> <silent> <nowait> o <c-o>:call <SID>NetrwSplit(3)<cr> - inoremap <buffer> <silent> <nowait> p <c-o>:call <SID>NetrwPreview(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1))<cr> - inoremap <buffer> <silent> <nowait> P <c-o>:call <SID>NetrwPrevWinOpen(1)<cr> - inoremap <buffer> <silent> <nowait> qb <c-o>:<c-u>call <SID>NetrwBookHistHandler(2,b:netrw_curdir)<cr> - inoremap <buffer> <silent> <nowait> qf <c-o>:<c-u>call <SID>NetrwFileInfo(1,<SID>NetrwGetWord())<cr> - inoremap <buffer> <silent> <nowait> qF :<c-u>call <SID>NetrwMarkFileQFEL(1,getqflist())<cr> - inoremap <buffer> <silent> <nowait> r <c-o>:let g:netrw_sort_direction= (g:netrw_sort_direction =~ 'n')? 'r' : 'n'<bar>exe "norm! 0"<bar>call <SID>NetrwRefresh(1,<SID>NetrwBrowseChgDir(1,'./'))<cr> - inoremap <buffer> <silent> <nowait> s <c-o>:call <SID>NetrwSortStyle(1)<cr> - inoremap <buffer> <silent> <nowait> S <c-o>:call <SID>NetSortSequence(1)<cr> - inoremap <buffer> <silent> <nowait> t <c-o>:call <SID>NetrwSplit(4)<cr> - inoremap <buffer> <silent> <nowait> Tb <c-o>:<c-u>call <SID>NetrwSetTgt('b',v:count1)<cr> - inoremap <buffer> <silent> <nowait> Th <c-o>:<c-u>call <SID>NetrwSetTgt('h',v:count)<cr> - inoremap <buffer> <silent> <nowait> u <c-o>:<c-u>call <SID>NetrwBookHistHandler(4,expand("%"))<cr> - inoremap <buffer> <silent> <nowait> U <c-o>:<c-u>call <SID>NetrwBookHistHandler(5,expand("%"))<cr> - inoremap <buffer> <silent> <nowait> v <c-o>:call <SID>NetrwSplit(5)<cr> - inoremap <buffer> <silent> <nowait> x <c-o>:call netrw#BrowseX(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),0),0)"<cr> + nnoremap <buffer> <silent> <nowait> x :<c-u>call netrw#BrowseX(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),0),0)"<cr> + nnoremap <buffer> <silent> <nowait> X :<c-u>call <SID>NetrwLocalExecute(expand("<cword>"))"<cr> +" " local insert-mode maps +" inoremap <buffer> <silent> <nowait> a <c-o>:call <SID>NetrwHide(1)<cr> +" inoremap <buffer> <silent> <nowait> c <c-o>:exe "NetrwKeepj lcd ".fnameescape(b:netrw_curdir)<cr> +" inoremap <buffer> <silent> <nowait> c <c-o>:call <SID>NetrwLcd(b:netrw_curdir)<cr> +" inoremap <buffer> <silent> <nowait> C <c-o>:call <SID>NetrwSetChgwin()<cr> +" inoremap <buffer> <silent> <nowait> % <c-o>:call <SID>NetrwOpenFile(1)<cr> +" inoremap <buffer> <silent> <nowait> - <c-o>:call <SID>NetrwBrowseUpDir(1)<cr> +" inoremap <buffer> <silent> <nowait> <cr> <c-o>:call netrw#LocalBrowseCheck(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord()))<cr> +" inoremap <buffer> <silent> <nowait> d <c-o>:call <SID>NetrwMakeDir("")<cr> +" inoremap <buffer> <silent> <nowait> gb <c-o>:<c-u>call <SID>NetrwBookHistHandler(1,b:netrw_curdir)<cr> +" inoremap <buffer> <silent> <nowait> gh <c-o>:<c-u>call <SID>NetrwHidden(1)<cr> +" nnoremap <buffer> <silent> <nowait> gn :<c-u>call netrw#SetTreetop(<SID>NetrwGetWord())<cr> +" inoremap <buffer> <silent> <nowait> gp <c-o>:<c-u>call <SID>NetrwChgPerm(1,b:netrw_curdir)<cr> +" inoremap <buffer> <silent> <nowait> I <c-o>:call <SID>NetrwBannerCtrl(1)<cr> +" inoremap <buffer> <silent> <nowait> i <c-o>:call <SID>NetrwListStyle(1)<cr> +" inoremap <buffer> <silent> <nowait> mb <c-o>:<c-u>call <SID>NetrwBookHistHandler(0,b:netrw_curdir)<cr> +" inoremap <buffer> <silent> <nowait> mB <c-o>:<c-u>call <SID>NetrwBookHistHandler(6,b:netrw_curdir)<cr> +" inoremap <buffer> <silent> <nowait> mc <c-o>:<c-u>call <SID>NetrwMarkFileCopy(1)<cr> +" inoremap <buffer> <silent> <nowait> md <c-o>:<c-u>call <SID>NetrwMarkFileDiff(1)<cr> +" inoremap <buffer> <silent> <nowait> me <c-o>:<c-u>call <SID>NetrwMarkFileEdit(1)<cr> +" inoremap <buffer> <silent> <nowait> mf <c-o>:<c-u>call <SID>NetrwMarkFile(1,<SID>NetrwGetWord())<cr> +" inoremap <buffer> <silent> <nowait> mg <c-o>:<c-u>call <SID>NetrwMarkFileGrep(1)<cr> +" inoremap <buffer> <silent> <nowait> mh <c-o>:<c-u>call <SID>NetrwMarkHideSfx(1)<cr> +" inoremap <buffer> <silent> <nowait> mm <c-o>:<c-u>call <SID>NetrwMarkFileMove(1)<cr> +" inoremap <buffer> <silent> <nowait> mp <c-o>:<c-u>call <SID>NetrwMarkFilePrint(1)<cr> +" inoremap <buffer> <silent> <nowait> mr <c-o>:<c-u>call <SID>NetrwMarkFileRegexp(1)<cr> +" inoremap <buffer> <silent> <nowait> ms <c-o>:<c-u>call <SID>NetrwMarkFileSource(1)<cr> +" inoremap <buffer> <silent> <nowait> mT <c-o>:<c-u>call <SID>NetrwMarkFileTag(1)<cr> +" inoremap <buffer> <silent> <nowait> mt <c-o>:<c-u>call <SID>NetrwMarkFileTgt(1)<cr> +" inoremap <buffer> <silent> <nowait> mu <c-o>:<c-u>call <SID>NetrwUnMarkFile(1)<cr> +" inoremap <buffer> <silent> <nowait> mv <c-o>:<c-u>call <SID>NetrwMarkFileVimCmd(1)<cr> +" inoremap <buffer> <silent> <nowait> mx <c-o>:<c-u>call <SID>NetrwMarkFileExe(1,0)<cr> +" inoremap <buffer> <silent> <nowait> mX <c-o>:<c-u>call <SID>NetrwMarkFileExe(1,1)<cr> +" inoremap <buffer> <silent> <nowait> mz <c-o>:<c-u>call <SID>NetrwMarkFileCompress(1)<cr> +" inoremap <buffer> <silent> <nowait> O <c-o>:call <SID>NetrwObtain(1)<cr> +" inoremap <buffer> <silent> <nowait> o <c-o>:call <SID>NetrwSplit(3)<cr> +" inoremap <buffer> <silent> <nowait> p <c-o>:call <SID>NetrwPreview(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1))<cr> +" inoremap <buffer> <silent> <nowait> P <c-o>:call <SID>NetrwPrevWinOpen(1)<cr> +" inoremap <buffer> <silent> <nowait> qb <c-o>:<c-u>call <SID>NetrwBookHistHandler(2,b:netrw_curdir)<cr> +" inoremap <buffer> <silent> <nowait> qf <c-o>:<c-u>call <SID>NetrwFileInfo(1,<SID>NetrwGetWord())<cr> +" inoremap <buffer> <silent> <nowait> qF :<c-u>call <SID>NetrwMarkFileQFEL(1,getqflist())<cr> +" inoremap <buffer> <silent> <nowait> qL :<c-u>call <SID>NetrwMarkFileQFEL(1,getloclist(v:count))<cr> +" inoremap <buffer> <silent> <nowait> r <c-o>:let g:netrw_sort_direction= (g:netrw_sort_direction =~ 'n')? 'r' : 'n'<bar>exe "norm! 0"<bar>call <SID>NetrwRefresh(1,<SID>NetrwBrowseChgDir(1,'./'))<cr> +" inoremap <buffer> <silent> <nowait> s <c-o>:call <SID>NetrwSortStyle(1)<cr> +" inoremap <buffer> <silent> <nowait> S <c-o>:call <SID>NetSortSequence(1)<cr> +" inoremap <buffer> <silent> <nowait> t <c-o>:call <SID>NetrwSplit(4)<cr> +" inoremap <buffer> <silent> <nowait> Tb <c-o>:<c-u>call <SID>NetrwSetTgt(1,'b',v:count1)<cr> +" inoremap <buffer> <silent> <nowait> Th <c-o>:<c-u>call <SID>NetrwSetTgt(1,'h',v:count)<cr> +" inoremap <buffer> <silent> <nowait> u <c-o>:<c-u>call <SID>NetrwBookHistHandler(4,expand("%"))<cr> +" inoremap <buffer> <silent> <nowait> U <c-o>:<c-u>call <SID>NetrwBookHistHandler(5,expand("%"))<cr> +" inoremap <buffer> <silent> <nowait> v <c-o>:call <SID>NetrwSplit(5)<cr> +" inoremap <buffer> <silent> <nowait> x <c-o>:call netrw#BrowseX(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),0),0)"<cr> if !hasmapto('<Plug>NetrwHideEdit') nmap <buffer> <unique> <c-h> <Plug>NetrwHideEdit - imap <buffer> <unique> <c-h> <Plug>NetrwHideEdit +" imap <buffer> <unique> <c-h> <c-o><Plug>NetrwHideEdit endif - nnoremap <buffer> <silent> <Plug>NetrwHideEdit :call <SID>NetrwHideEdit(1)<cr> + nnoremap <buffer> <silent> <Plug>NetrwHideEdit :call <SID>NetrwHideEdit(1)<cr> if !hasmapto('<Plug>NetrwRefresh') nmap <buffer> <unique> <c-l> <Plug>NetrwRefresh - imap <buffer> <unique> <c-l> <Plug>NetrwRefresh +" imap <buffer> <unique> <c-l> <c-o><Plug>NetrwRefresh endif - nnoremap <buffer> <silent> <Plug>NetrwRefresh :call <SID>NetrwRefresh(1,<SID>NetrwBrowseChgDir(1,(w:netrw_liststyle == 3)? w:netrw_treetop : './'))<cr> + nnoremap <buffer> <silent> <Plug>NetrwRefresh <c-l>:call <SID>NetrwRefresh(1,<SID>NetrwBrowseChgDir(1,(w:netrw_liststyle == 3)? w:netrw_treetop : './'))<cr> if s:didstarstar || !mapcheck("<s-down>","n") nnoremap <buffer> <silent> <s-down> :Nexplore<cr> - inoremap <buffer> <silent> <s-down> :Nexplore<cr> +" inoremap <buffer> <silent> <s-down> <c-o>:Nexplore<cr> endif if s:didstarstar || !mapcheck("<s-up>","n") nnoremap <buffer> <silent> <s-up> :Pexplore<cr> - inoremap <buffer> <silent> <s-up> :Pexplore<cr> +" inoremap <buffer> <silent> <s-up> <c-o>:Pexplore<cr> + endif + if !hasmapto('<Plug>NetrwTreeSqueeze') + nmap <buffer> <silent> <nowait> <s-cr> <Plug>NetrwTreeSqueeze +" imap <buffer> <silent> <nowait> <s-cr> <c-o><Plug>NetrwTreeSqueeze endif + nnoremap <buffer> <silent> <Plug>NetrwTreeSqueeze :call <SID>TreeSqueezeDir(1)<cr> let mapsafecurdir = escape(b:netrw_curdir, s:netrw_map_escape) if g:netrw_mousemaps == 1 - nmap <buffer> <leftmouse> <Plug>NetrwLeftmouse + nmap <buffer> <leftmouse> <Plug>NetrwLeftmouse nno <buffer> <silent> <Plug>NetrwLeftmouse <leftmouse>:call <SID>NetrwLeftmouse(1)<cr> nmap <buffer> <c-leftmouse> <Plug>NetrwCLeftmouse nno <buffer> <silent> <Plug>NetrwCLeftmouse <leftmouse>:call <SID>NetrwCLeftmouse(1)<cr> @@ -6067,14 +6188,14 @@ fun! s:NetrwMaps(islocal) nmap <buffer> <2-leftmouse> <Plug>Netrw2Leftmouse nmap <buffer> <silent> <Plug>Netrw2Leftmouse - imap <buffer> <leftmouse> <Plug>ILeftmouse - ino <buffer> <silent> <Plug>ILeftmouse <c-o><leftmouse><c-o>:call <SID>NetrwLeftmouse(1)<cr> +" ino <buffer> <silent> <Plug>ILeftmouse <c-o><leftmouse><c-o>:call <SID>NetrwLeftmouse(1)<cr> imap <buffer> <middlemouse> <Plug>IMiddlemouse - ino <buffer> <silent> <Plug>IMiddlemouse <c-o><leftmouse><c-o>:call <SID>NetrwPrevWinOpen(1)<cr> - imap <buffer> <s-leftmouse> <Plug>ISLeftmouse - ino <buffer> <silent> <Plug>ISLeftmouse <c-o><leftmouse><c-o>:call <SID>NetrwMarkFile(1,<SID>NetrwGetWord())<cr> +" ino <buffer> <silent> <Plug>IMiddlemouse <c-o><leftmouse><c-o>:call <SID>NetrwPrevWinOpen(1)<cr> +" imap <buffer> <s-leftmouse> <Plug>ISLeftmouse +" ino <buffer> <silent> <Plug>ISLeftmouse <c-o><leftmouse><c-o>:call <SID>NetrwMarkFile(1,<SID>NetrwGetWord())<cr> exe 'nnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>' exe 'vnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>' - exe 'inoremap <buffer> <silent> <rightmouse> <c-o><leftmouse><c-o>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>' +" exe 'inoremap <buffer> <silent> <rightmouse> <c-o><leftmouse><c-o>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>' endif exe 'nnoremap <buffer> <silent> <nowait> <del> :call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>' exe 'nnoremap <buffer> <silent> <nowait> D :call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>' @@ -6083,10 +6204,10 @@ fun! s:NetrwMaps(islocal) exe 'vnoremap <buffer> <silent> <nowait> <del> :call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>' exe 'vnoremap <buffer> <silent> <nowait> D :call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>' exe 'vnoremap <buffer> <silent> <nowait> R :call <SID>NetrwLocalRename("'.mapsafecurdir.'")<cr>' - exe 'inoremap <buffer> <silent> <nowait> <del> <c-o>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>' - exe 'inoremap <buffer> <silent> <nowait> D <c-o>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>' - exe 'inoremap <buffer> <silent> <nowait> R <c-o>:call <SID>NetrwLocalRename("'.mapsafecurdir.'")<cr>' - exe 'inoremap <buffer> <silent> <nowait> d <c-o>:call <SID>NetrwMakeDir("")<cr>' +" exe 'inoremap <buffer> <silent> <nowait> <del> <c-o>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>' +" exe 'inoremap <buffer> <silent> <nowait> D <c-o>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>' +" exe 'inoremap <buffer> <silent> <nowait> R <c-o>:call <SID>NetrwLocalRename("'.mapsafecurdir.'")<cr>' +" exe 'inoremap <buffer> <silent> <nowait> d <c-o>:call <SID>NetrwMakeDir("")<cr>' nnoremap <buffer> <F1> :he netrw-quickhelp<cr> " support user-specified maps @@ -6096,13 +6217,24 @@ fun! s:NetrwMaps(islocal) " call Decho("make remote maps",'~'.expand("<slnum>")) call s:RemotePathAnalysis(b:netrw_curdir) " remote normal-mode maps - nnoremap <buffer> <silent> <nowait> <cr> :call <SID>NetrwBrowse(0,<SID>NetrwBrowseChgDir(0,<SID>NetrwGetWord()))<cr> - nnoremap <buffer> <silent> <nowait> <s-cr> :call <SID>TreeSqueezeDir(0)<cr> - nnoremap <buffer> <silent> <nowait> <c-l> :call <SID>NetrwRefresh(0,<SID>NetrwBrowseChgDir(0,'./'))<cr> - nnoremap <buffer> <silent> <nowait> <c-r> :call <SID>NetrwServerEdit(2,<SID>NetrwGetWord())<cr> - nnoremap <buffer> <silent> <nowait> - :call <SID>NetrwBrowseUpDir(0)<cr> - nnoremap <buffer> <silent> <nowait> a :call <SID>NetrwHide(0)<cr> + nnoremap <buffer> <silent> <nowait> a :<c-u>call <SID>NetrwHide(0)<cr> + nnoremap <buffer> <silent> <nowait> - :<c-u>call <SID>NetrwBrowseUpDir(0)<cr> + nnoremap <buffer> <silent> <nowait> % :<c-u>call <SID>NetrwOpenFile(0)<cr> + nnoremap <buffer> <silent> <nowait> C :<c-u>call <SID>NetrwSetChgwin()<cr> + nnoremap <buffer> <silent> <nowait> <c-l> :<c-u>call <SID>NetrwRefresh(0,<SID>NetrwBrowseChgDir(0,'./'))<cr> + nnoremap <buffer> <silent> <nowait> <cr> :<c-u>call <SID>NetrwBrowse(0,<SID>NetrwBrowseChgDir(0,<SID>NetrwGetWord()))<cr> + nnoremap <buffer> <silent> <nowait> <c-r> :<c-u>call <SID>NetrwServerEdit(2,<SID>NetrwGetWord())<cr> + nnoremap <buffer> <silent> <nowait> gb :<c-u>call <SID>NetrwBookHistHandler(1,b:netrw_curdir)<cr> + nnoremap <buffer> <silent> <nowait> gd :<c-u>call <SID>NetrwForceChgDir(0,<SID>NetrwGetWord())<cr> + nnoremap <buffer> <silent> <nowait> gf :<c-u>call <SID>NetrwForceFile(0,<SID>NetrwGetWord())<cr> + nnoremap <buffer> <silent> <nowait> gh :<c-u>call <SID>NetrwHidden(0)<cr> + nnoremap <buffer> <silent> <nowait> gp :<c-u>call <SID>NetrwChgPerm(0,b:netrw_curdir)<cr> + nnoremap <buffer> <silent> <nowait> I :<c-u>call <SID>NetrwBannerCtrl(1)<cr> + nnoremap <buffer> <silent> <nowait> i :<c-u>call <SID>NetrwListStyle(0)<cr> + nnoremap <buffer> <silent> <nowait> ma :<c-u>call <SID>NetrwMarkFileArgList(0,0)<cr> + nnoremap <buffer> <silent> <nowait> mA :<c-u>call <SID>NetrwMarkFileArgList(0,1)<cr> nnoremap <buffer> <silent> <nowait> mb :<c-u>call <SID>NetrwBookHistHandler(0,b:netrw_curdir)<cr> + nnoremap <buffer> <silent> <nowait> mB :<c-u>call <SID>NetrwBookHistHandler(6,b:netrw_curdir)<cr> nnoremap <buffer> <silent> <nowait> mc :<c-u>call <SID>NetrwMarkFileCopy(0)<cr> nnoremap <buffer> <silent> <nowait> md :<c-u>call <SID>NetrwMarkFileDiff(0)<cr> nnoremap <buffer> <silent> <nowait> me :<c-u>call <SID>NetrwMarkFileEdit(0)<cr> @@ -6114,99 +6246,96 @@ fun! s:NetrwMaps(islocal) nnoremap <buffer> <silent> <nowait> mp :<c-u>call <SID>NetrwMarkFilePrint(0)<cr> nnoremap <buffer> <silent> <nowait> mr :<c-u>call <SID>NetrwMarkFileRegexp(0)<cr> nnoremap <buffer> <silent> <nowait> ms :<c-u>call <SID>NetrwMarkFileSource(0)<cr> - nnoremap <buffer> <silent> <nowait> mt :<c-u>call <SID>NetrwMarkFileTgt(0)<cr> nnoremap <buffer> <silent> <nowait> mT :<c-u>call <SID>NetrwMarkFileTag(0)<cr> + nnoremap <buffer> <silent> <nowait> mt :<c-u>call <SID>NetrwMarkFileTgt(0)<cr> nnoremap <buffer> <silent> <nowait> mu :<c-u>call <SID>NetrwUnMarkFile(0)<cr> nnoremap <buffer> <silent> <nowait> mv :<c-u>call <SID>NetrwMarkFileVimCmd(0)<cr> nnoremap <buffer> <silent> <nowait> mx :<c-u>call <SID>NetrwMarkFileExe(0,0)<cr> nnoremap <buffer> <silent> <nowait> mX :<c-u>call <SID>NetrwMarkFileExe(0,1)<cr> nnoremap <buffer> <silent> <nowait> mz :<c-u>call <SID>NetrwMarkFileCompress(0)<cr> - nnoremap <buffer> <silent> <nowait> gb :<c-u>call <SID>NetrwBookHistHandler(1,b:netrw_curdir)<cr> - nnoremap <buffer> <silent> <nowait> gd :<c-u>call <SID>NetrwForceChgDir(0,<SID>NetrwGetWord())<cr> - nnoremap <buffer> <silent> <nowait> gf :<c-u>call <SID>NetrwForceFile(0,<SID>NetrwGetWord())<cr> - nnoremap <buffer> <silent> <nowait> gh :<c-u>call <SID>NetrwHidden(0)<cr> - nnoremap <buffer> <silent> <nowait> gp :<c-u>call <SID>NetrwChgPerm(0,b:netrw_curdir)<cr> - nnoremap <buffer> <silent> <nowait> C :<c-u>call <SID>NetrwSetChgwin()<cr> - nnoremap <buffer> <silent> <nowait> i :call <SID>NetrwListStyle(0)<cr> - nnoremap <buffer> <silent> <nowait> I :call <SID>NetrwBannerCtrl(1)<cr> - nnoremap <buffer> <silent> <nowait> o :call <SID>NetrwSplit(0)<cr> - nnoremap <buffer> <silent> <nowait> O :call <SID>NetrwObtain(0)<cr> - nnoremap <buffer> <silent> <nowait> p :call <SID>NetrwPreview(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1))<cr> - nnoremap <buffer> <silent> <nowait> P :call <SID>NetrwPrevWinOpen(0)<cr> + nnoremap <buffer> <silent> <nowait> O :<c-u>call <SID>NetrwObtain(0)<cr> + nnoremap <buffer> <silent> <nowait> o :call <SID>NetrwSplit(0)<cr> + nnoremap <buffer> <silent> <nowait> p :<c-u>call <SID>NetrwPreview(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1))<cr> + nnoremap <buffer> <silent> <nowait> P :<c-u>call <SID>NetrwPrevWinOpen(0)<cr> nnoremap <buffer> <silent> <nowait> qb :<c-u>call <SID>NetrwBookHistHandler(2,b:netrw_curdir)<cr> - nnoremap <buffer> <silent> <nowait> mB :<c-u>call <SID>NetrwBookHistHandler(6,b:netrw_curdir)<cr> nnoremap <buffer> <silent> <nowait> qf :<c-u>call <SID>NetrwFileInfo(0,<SID>NetrwGetWord())<cr> nnoremap <buffer> <silent> <nowait> qF :<c-u>call <SID>NetrwMarkFileQFEL(0,getqflist())<cr> - nnoremap <buffer> <silent> <nowait> r :let g:netrw_sort_direction= (g:netrw_sort_direction =~ 'n')? 'r' : 'n'<bar>exe "norm! 0"<bar>call <SID>NetrwBrowse(0,<SID>NetrwBrowseChgDir(0,'./'))<cr> - nnoremap <buffer> <silent> <nowait> s :call <SID>NetrwSortStyle(0)<cr> - nnoremap <buffer> <silent> <nowait> S :call <SID>NetSortSequence(0)<cr> - nnoremap <buffer> <silent> <nowait> t :call <SID>NetrwSplit(1)<cr> - nnoremap <buffer> <silent> <nowait> Tb :<c-u>call <SID>NetrwSetTgt('b',v:count1)<cr> - nnoremap <buffer> <silent> <nowait> Th :<c-u>call <SID>NetrwSetTgt('h',v:count)<cr> - nnoremap <buffer> <silent> <nowait> u :<c-u>call <SID>NetrwBookHistHandler(4,b:netrw_curdir)<cr> - nnoremap <buffer> <silent> <nowait> U :<c-u>call <SID>NetrwBookHistHandler(5,b:netrw_curdir)<cr> - nnoremap <buffer> <silent> <nowait> v :call <SID>NetrwSplit(2)<cr> - nnoremap <buffer> <silent> <nowait> x :call netrw#BrowseX(<SID>NetrwBrowseChgDir(0,<SID>NetrwGetWord()),1)<cr> - nnoremap <buffer> <silent> <nowait> % :call <SID>NetrwOpenFile(0)<cr> - " remote insert-mode maps - inoremap <buffer> <silent> <nowait> <cr> <c-o>:call <SID>NetrwBrowse(0,<SID>NetrwBrowseChgDir(0,<SID>NetrwGetWord()))<cr> - inoremap <buffer> <silent> <nowait> <c-l> <c-o>:call <SID>NetrwRefresh(0,<SID>NetrwBrowseChgDir(0,'./'))<cr> - inoremap <buffer> <silent> <nowait> <s-cr> <c-o>:call <SID>TreeSqueezeDir(0)<cr> - inoremap <buffer> <silent> <nowait> - <c-o>:call <SID>NetrwBrowseUpDir(0)<cr> - inoremap <buffer> <silent> <nowait> a <c-o>:call <SID>NetrwHide(0)<cr> - inoremap <buffer> <silent> <nowait> mb <c-o>:<c-u>call <SID>NetrwBookHistHandler(0,b:netrw_curdir)<cr> - inoremap <buffer> <silent> <nowait> mc <c-o>:<c-u>call <SID>NetrwMarkFileCopy(0)<cr> - inoremap <buffer> <silent> <nowait> md <c-o>:<c-u>call <SID>NetrwMarkFileDiff(0)<cr> - inoremap <buffer> <silent> <nowait> me <c-o>:<c-u>call <SID>NetrwMarkFileEdit(0)<cr> - inoremap <buffer> <silent> <nowait> mf <c-o>:<c-u>call <SID>NetrwMarkFile(0,<SID>NetrwGetWord())<cr> - inoremap <buffer> <silent> <nowait> mg <c-o>:<c-u>call <SID>NetrwMarkFileGrep(0)<cr> - inoremap <buffer> <silent> <nowait> mh <c-o>:<c-u>call <SID>NetrwMarkHideSfx(0)<cr> - inoremap <buffer> <silent> <nowait> mm <c-o>:<c-u>call <SID>NetrwMarkFileMove(0)<cr> - inoremap <buffer> <silent> <nowait> mp <c-o>:<c-u>call <SID>NetrwMarkFilePrint(0)<cr> - inoremap <buffer> <silent> <nowait> mr <c-o>:<c-u>call <SID>NetrwMarkFileRegexp(0)<cr> - inoremap <buffer> <silent> <nowait> ms <c-o>:<c-u>call <SID>NetrwMarkFileSource(0)<cr> - inoremap <buffer> <silent> <nowait> mt <c-o>:<c-u>call <SID>NetrwMarkFileTgt(0)<cr> - inoremap <buffer> <silent> <nowait> mT <c-o>:<c-u>call <SID>NetrwMarkFileTag(0)<cr> - inoremap <buffer> <silent> <nowait> mu <c-o>:<c-u>call <SID>NetrwUnMarkFile(0)<cr> - nnoremap <buffer> <silent> <nowait> mv :<c-u>call <SID>NetrwMarkFileVimCmd(1)<cr> - inoremap <buffer> <silent> <nowait> mx <c-o>:<c-u>call <SID>NetrwMarkFileExe(0,0)<cr> - inoremap <buffer> <silent> <nowait> mX <c-o>:<c-u>call <SID>NetrwMarkFileExe(0,1)<cr> - inoremap <buffer> <silent> <nowait> mv <c-o>:<c-u>call <SID>NetrwMarkFileVimCmd(0)<cr> - inoremap <buffer> <silent> <nowait> mz <c-o>:<c-u>call <SID>NetrwMarkFileCompress(0)<cr> - inoremap <buffer> <silent> <nowait> gb <c-o>:<c-u>call <SID>NetrwBookHistHandler(1,b:netrw_curdir)<cr> - inoremap <buffer> <silent> <nowait> gh <c-o>:<c-u>call <SID>NetrwHidden(0)<cr> - inoremap <buffer> <silent> <nowait> gp <c-o>:<c-u>call <SID>NetrwChgPerm(0,b:netrw_curdir)<cr> - inoremap <buffer> <silent> <nowait> C <c-o>:call <SID>NetrwSetChgwin()<cr> - inoremap <buffer> <silent> <nowait> i <c-o>:call <SID>NetrwListStyle(0)<cr> - inoremap <buffer> <silent> <nowait> I <c-o>:call <SID>NetrwBannerCtrl(1)<cr> - inoremap <buffer> <silent> <nowait> o <c-o>:call <SID>NetrwSplit(0)<cr> - inoremap <buffer> <silent> <nowait> O <c-o>:call <SID>NetrwObtain(0)<cr> - inoremap <buffer> <silent> <nowait> p <c-o>:call <SID>NetrwPreview(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1))<cr> - inoremap <buffer> <silent> <nowait> P <c-o>:call <SID>NetrwPrevWinOpen(0)<cr> - inoremap <buffer> <silent> <nowait> qb <c-o>:<c-u>call <SID>NetrwBookHistHandler(2,b:netrw_curdir)<cr> - inoremap <buffer> <silent> <nowait> mB <c-o>:<c-u>call <SID>NetrwBookHistHandler(6,b:netrw_curdir)<cr> - inoremap <buffer> <silent> <nowait> qf <c-o>:<c-u>call <SID>NetrwFileInfo(0,<SID>NetrwGetWord())<cr> - inoremap <buffer> <silent> <nowait> qF :<c-u>call <SID>NetrwMarkFileQFEL(0,getqflist())<cr> - inoremap <buffer> <silent> <nowait> r <c-o>:let g:netrw_sort_direction= (g:netrw_sort_direction =~ 'n')? 'r' : 'n'<bar>exe "norm! 0"<bar>call <SID>NetrwBrowse(0,<SID>NetrwBrowseChgDir(0,'./'))<cr> - inoremap <buffer> <silent> <nowait> s <c-o>:call <SID>NetrwSortStyle(0)<cr> - inoremap <buffer> <silent> <nowait> S <c-o>:call <SID>NetSortSequence(0)<cr> - inoremap <buffer> <silent> <nowait> t <c-o>:call <SID>NetrwSplit(1)<cr> - inoremap <buffer> <silent> <nowait> Tb <c-o>:<c-u>call <SID>NetrwSetTgt('b',v:count1)<cr> - inoremap <buffer> <silent> <nowait> Th <c-o>:<c-u>call <SID>NetrwSetTgt('h',v:count)<cr> - inoremap <buffer> <silent> <nowait> u <c-o>:<c-u>call <SID>NetrwBookHistHandler(4,b:netrw_curdir)<cr> - inoremap <buffer> <silent> <nowait> U <c-o>:<c-u>call <SID>NetrwBookHistHandler(5,b:netrw_curdir)<cr> - inoremap <buffer> <silent> <nowait> v <c-o>:call <SID>NetrwSplit(2)<cr> - inoremap <buffer> <silent> <nowait> x <c-o>:call netrw#BrowseX(<SID>NetrwBrowseChgDir(0,<SID>NetrwGetWord()),1)<cr> - inoremap <buffer> <silent> <nowait> % <c-o>:call <SID>NetrwOpenFile(0)<cr> + nnoremap <buffer> <silent> <nowait> qL :<c-u>call <SID>NetrwMarkFileQFEL(0,getloclist(v:count))<cr> + nnoremap <buffer> <silent> <nowait> r :<c-u>let g:netrw_sort_direction= (g:netrw_sort_direction =~ 'n')? 'r' : 'n'<bar>exe "norm! 0"<bar>call <SID>NetrwBrowse(0,<SID>NetrwBrowseChgDir(0,'./'))<cr> + nnoremap <buffer> <silent> <nowait> s :call <SID>NetrwSortStyle(0)<cr> + nnoremap <buffer> <silent> <nowait> S :<c-u>call <SID>NetSortSequence(0)<cr> + nnoremap <buffer> <silent> <nowait> Tb :<c-u>call <SID>NetrwSetTgt(0,'b',v:count1)<cr> + nnoremap <buffer> <silent> <nowait> t :call <SID>NetrwSplit(1)<cr> + nnoremap <buffer> <silent> <nowait> Th :<c-u>call <SID>NetrwSetTgt(0,'h',v:count)<cr> + nnoremap <buffer> <silent> <nowait> u :<c-u>call <SID>NetrwBookHistHandler(4,b:netrw_curdir)<cr> + nnoremap <buffer> <silent> <nowait> U :<c-u>call <SID>NetrwBookHistHandler(5,b:netrw_curdir)<cr> + nnoremap <buffer> <silent> <nowait> v :call <SID>NetrwSplit(2)<cr> + nnoremap <buffer> <silent> <nowait> x :<c-u>call netrw#BrowseX(<SID>NetrwBrowseChgDir(0,<SID>NetrwGetWord()),1)<cr> +" " remote insert-mode maps +" inoremap <buffer> <silent> <nowait> <cr> <c-o>:call <SID>NetrwBrowse(0,<SID>NetrwBrowseChgDir(0,<SID>NetrwGetWord()))<cr> +" inoremap <buffer> <silent> <nowait> <c-l> <c-o>:call <SID>NetrwRefresh(0,<SID>NetrwBrowseChgDir(0,'./'))<cr> +" inoremap <buffer> <silent> <nowait> <s-cr> <c-o>:call <SID>TreeSqueezeDir(0)<cr> +" inoremap <buffer> <silent> <nowait> - <c-o>:call <SID>NetrwBrowseUpDir(0)<cr> +" inoremap <buffer> <silent> <nowait> a <c-o>:call <SID>NetrwHide(0)<cr> +" inoremap <buffer> <silent> <nowait> mb <c-o>:<c-u>call <SID>NetrwBookHistHandler(0,b:netrw_curdir)<cr> +" inoremap <buffer> <silent> <nowait> mc <c-o>:<c-u>call <SID>NetrwMarkFileCopy(0)<cr> +" inoremap <buffer> <silent> <nowait> md <c-o>:<c-u>call <SID>NetrwMarkFileDiff(0)<cr> +" inoremap <buffer> <silent> <nowait> me <c-o>:<c-u>call <SID>NetrwMarkFileEdit(0)<cr> +" inoremap <buffer> <silent> <nowait> mf <c-o>:<c-u>call <SID>NetrwMarkFile(0,<SID>NetrwGetWord())<cr> +" inoremap <buffer> <silent> <nowait> mg <c-o>:<c-u>call <SID>NetrwMarkFileGrep(0)<cr> +" inoremap <buffer> <silent> <nowait> mh <c-o>:<c-u>call <SID>NetrwMarkHideSfx(0)<cr> +" inoremap <buffer> <silent> <nowait> mm <c-o>:<c-u>call <SID>NetrwMarkFileMove(0)<cr> +" inoremap <buffer> <silent> <nowait> mp <c-o>:<c-u>call <SID>NetrwMarkFilePrint(0)<cr> +" inoremap <buffer> <silent> <nowait> mr <c-o>:<c-u>call <SID>NetrwMarkFileRegexp(0)<cr> +" inoremap <buffer> <silent> <nowait> ms <c-o>:<c-u>call <SID>NetrwMarkFileSource(0)<cr> +" inoremap <buffer> <silent> <nowait> mt <c-o>:<c-u>call <SID>NetrwMarkFileTgt(0)<cr> +" inoremap <buffer> <silent> <nowait> mT <c-o>:<c-u>call <SID>NetrwMarkFileTag(0)<cr> +" inoremap <buffer> <silent> <nowait> mu <c-o>:<c-u>call <SID>NetrwUnMarkFile(0)<cr> +" nnoremap <buffer> <silent> <nowait> mv :<c-u>call <SID>NetrwMarkFileVimCmd(1)<cr> +" inoremap <buffer> <silent> <nowait> mx <c-o>:<c-u>call <SID>NetrwMarkFileExe(0,0)<cr> +" inoremap <buffer> <silent> <nowait> mX <c-o>:<c-u>call <SID>NetrwMarkFileExe(0,1)<cr> +" inoremap <buffer> <silent> <nowait> mv <c-o>:<c-u>call <SID>NetrwMarkFileVimCmd(0)<cr> +" inoremap <buffer> <silent> <nowait> mz <c-o>:<c-u>call <SID>NetrwMarkFileCompress(0)<cr> +" inoremap <buffer> <silent> <nowait> gb <c-o>:<c-u>call <SID>NetrwBookHistHandler(1,b:netrw_curdir)<cr> +" inoremap <buffer> <silent> <nowait> gh <c-o>:<c-u>call <SID>NetrwHidden(0)<cr> +" inoremap <buffer> <silent> <nowait> gp <c-o>:<c-u>call <SID>NetrwChgPerm(0,b:netrw_curdir)<cr> +" inoremap <buffer> <silent> <nowait> C <c-o>:call <SID>NetrwSetChgwin()<cr> +" inoremap <buffer> <silent> <nowait> i <c-o>:call <SID>NetrwListStyle(0)<cr> +" inoremap <buffer> <silent> <nowait> I <c-o>:call <SID>NetrwBannerCtrl(1)<cr> +" inoremap <buffer> <silent> <nowait> o <c-o>:call <SID>NetrwSplit(0)<cr> +" inoremap <buffer> <silent> <nowait> O <c-o>:call <SID>NetrwObtain(0)<cr> +" inoremap <buffer> <silent> <nowait> p <c-o>:call <SID>NetrwPreview(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1))<cr> +" inoremap <buffer> <silent> <nowait> P <c-o>:call <SID>NetrwPrevWinOpen(0)<cr> +" inoremap <buffer> <silent> <nowait> qb <c-o>:<c-u>call <SID>NetrwBookHistHandler(2,b:netrw_curdir)<cr> +" inoremap <buffer> <silent> <nowait> mB <c-o>:<c-u>call <SID>NetrwBookHistHandler(6,b:netrw_curdir)<cr> +" inoremap <buffer> <silent> <nowait> qf <c-o>:<c-u>call <SID>NetrwFileInfo(0,<SID>NetrwGetWord())<cr> +" inoremap <buffer> <silent> <nowait> qF :<c-u>call <SID>NetrwMarkFileQFEL(0,getqflist())<cr> +" inoremap <buffer> <silent> <nowait> qL :<c-u>call <SID>NetrwMarkFileQFEL(0,getloclist(v:count))<cr> +" inoremap <buffer> <silent> <nowait> r <c-o>:let g:netrw_sort_direction= (g:netrw_sort_direction =~ 'n')? 'r' : 'n'<bar>exe "norm! 0"<bar>call <SID>NetrwBrowse(0,<SID>NetrwBrowseChgDir(0,'./'))<cr> +" inoremap <buffer> <silent> <nowait> s <c-o>:call <SID>NetrwSortStyle(0)<cr> +" inoremap <buffer> <silent> <nowait> S <c-o>:call <SID>NetSortSequence(0)<cr> +" inoremap <buffer> <silent> <nowait> t <c-o>:call <SID>NetrwSplit(1)<cr> +" inoremap <buffer> <silent> <nowait> Tb <c-o>:<c-u>call <SID>NetrwSetTgt('b',v:count1)<cr> +" inoremap <buffer> <silent> <nowait> Th <c-o>:<c-u>call <SID>NetrwSetTgt('h',v:count)<cr> +" inoremap <buffer> <silent> <nowait> u <c-o>:<c-u>call <SID>NetrwBookHistHandler(4,b:netrw_curdir)<cr> +" inoremap <buffer> <silent> <nowait> U <c-o>:<c-u>call <SID>NetrwBookHistHandler(5,b:netrw_curdir)<cr> +" inoremap <buffer> <silent> <nowait> v <c-o>:call <SID>NetrwSplit(2)<cr> +" inoremap <buffer> <silent> <nowait> x <c-o>:call netrw#BrowseX(<SID>NetrwBrowseChgDir(0,<SID>NetrwGetWord()),1)<cr> +" inoremap <buffer> <silent> <nowait> % <c-o>:call <SID>NetrwOpenFile(0)<cr> if !hasmapto('<Plug>NetrwHideEdit') nmap <buffer> <c-h> <Plug>NetrwHideEdit - imap <buffer> <c-h> <Plug>NetrwHideEdit +" imap <buffer> <c-h> <Plug>NetrwHideEdit endif nnoremap <buffer> <silent> <Plug>NetrwHideEdit :call <SID>NetrwHideEdit(0)<cr> if !hasmapto('<Plug>NetrwRefresh') nmap <buffer> <c-l> <Plug>NetrwRefresh - imap <buffer> <c-l> <Plug>NetrwRefresh +" imap <buffer> <c-l> <Plug>NetrwRefresh endif + if !hasmapto('<Plug>NetrwTreeSqueeze') + nmap <buffer> <silent> <nowait> <s-cr> <Plug>NetrwTreeSqueeze +" imap <buffer> <silent> <nowait> <s-cr> <c-o><Plug>NetrwTreeSqueeze + endif + nnoremap <buffer> <silent> <Plug>NetrwTreeSqueeze :call <SID>TreeSqueezeDir(0)<cr> let mapsafepath = escape(s:path, s:netrw_map_escape) let mapsafeusermach = escape(((s:user == "")? "" : s:user."@").s:machine, s:netrw_map_escape) @@ -6226,14 +6355,14 @@ fun! s:NetrwMaps(islocal) nmap <buffer> <2-leftmouse> <Plug>Netrw2Leftmouse nmap <buffer> <silent> <Plug>Netrw2Leftmouse - imap <buffer> <leftmouse> <Plug>ILeftmouse - ino <buffer> <silent> <Plug>ILeftmouse <c-o><leftmouse><c-o>:call <SID>NetrwLeftmouse(0)<cr> +" ino <buffer> <silent> <Plug>ILeftmouse <c-o><leftmouse><c-o>:call <SID>NetrwLeftmouse(0)<cr> imap <buffer> <middlemouse> <Plug>IMiddlemouse - ino <buffer> <silent> <Plug>IMiddlemouse <c-o><leftmouse><c-o>:call <SID>NetrwPrevWinOpen(0)<cr> +" ino <buffer> <silent> <Plug>IMiddlemouse <c-o><leftmouse><c-o>:call <SID>NetrwPrevWinOpen(0)<cr> imap <buffer> <s-leftmouse> <Plug>ISLeftmouse - ino <buffer> <silent> <Plug>ISLeftmouse <c-o><leftmouse><c-o>:call <SID>NetrwMarkFile(0,<SID>NetrwGetWord())<cr> +" ino <buffer> <silent> <Plug>ISLeftmouse <c-o><leftmouse><c-o>:call <SID>NetrwMarkFile(0,<SID>NetrwGetWord())<cr> exe 'nnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>' exe 'vnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>' - exe 'inoremap <buffer> <silent> <rightmouse> <c-o><leftmouse><c-o>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>' +" exe 'inoremap <buffer> <silent> <rightmouse> <c-o><leftmouse><c-o>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>' endif exe 'nnoremap <buffer> <silent> <nowait> <del> :call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>' exe 'nnoremap <buffer> <silent> <nowait> d :call <SID>NetrwMakeDir("'.mapsafeusermach.'")<cr>' @@ -6242,12 +6371,12 @@ fun! s:NetrwMaps(islocal) exe 'vnoremap <buffer> <silent> <nowait> <del> :call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>' exe 'vnoremap <buffer> <silent> <nowait> D :call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>' exe 'vnoremap <buffer> <silent> <nowait> R :call <SID>NetrwRemoteRename("'.mapsafeusermach.'","'.mapsafepath.'")<cr>' - exe 'inoremap <buffer> <silent> <nowait> <del> <c-o>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>' - exe 'inoremap <buffer> <silent> <nowait> d <c-o>:call <SID>NetrwMakeDir("'.mapsafeusermach.'")<cr>' - exe 'inoremap <buffer> <silent> <nowait> D <c-o>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>' - exe 'inoremap <buffer> <silent> <nowait> R <c-o>:call <SID>NetrwRemoteRename("'.mapsafeusermach.'","'.mapsafepath.'")<cr>' +" exe 'inoremap <buffer> <silent> <nowait> <del> <c-o>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>' +" exe 'inoremap <buffer> <silent> <nowait> d <c-o>:call <SID>NetrwMakeDir("'.mapsafeusermach.'")<cr>' +" exe 'inoremap <buffer> <silent> <nowait> D <c-o>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>' +" exe 'inoremap <buffer> <silent> <nowait> R <c-o>:call <SID>NetrwRemoteRename("'.mapsafeusermach.'","'.mapsafepath.'")<cr>' nnoremap <buffer> <F1> :he netrw-quickhelp<cr> - inoremap <buffer> <F1> <c-o>:he netrw-quickhelp<cr> +" inoremap <buffer> <F1> <c-o>:he netrw-quickhelp<cr> " support user-specified maps call netrw#UserMaps(0) @@ -6257,7 +6386,7 @@ fun! s:NetrwMaps(islocal) endfun " --------------------------------------------------------------------- -" s:NetrwCommands: sets up commands {{{2 +" s:NetrwCommands: set up commands {{{2 " If -buffer, the command is only available from within netrw buffers " Otherwise, the command is available from any window, so long as netrw " has been used at least once in the session. @@ -6266,7 +6395,7 @@ fun! s:NetrwCommands(islocal) com! -nargs=* -complete=file -bang NetrwMB call s:NetrwBookmark(<bang>0,<f-args>) com! -nargs=* NetrwC call s:NetrwSetChgwin(<q-args>) - com! Rexplore if exists("w:netrw_rexlocal")|call s:NetrwRexplore(w:netrw_rexlocal,exists("w:netrw_rexdir")? w:netrw_rexdir : ".")|else|call netrw#ErrorMsg(s:WARNING,"not a former netrw window",79)|endif + com! Rexplore if exists("w:netrw_rexlocal")|call s:NetrwRexplore(w:netrw_rexlocal,exists("w:netrw_rexdir")? w:netrw_rexdir : ".")|else|call netrw#ErrorMsg(s:WARNING,"win#".winnr()." not a former netrw window",79)|endif if a:islocal com! -buffer -nargs=+ -complete=file MF call s:NetrwMarkFiles(1,<f-args>) else @@ -6319,9 +6448,11 @@ fun! s:NetrwMarkTarget(...) let s:netrwmftgt = tgt let s:netrwmftgt_islocal = tgt !~ '^\a\{3,}://' let curislocal = b:netrw_curdir !~ '^\a\{3,}://' - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) call s:NetrwRefresh(curislocal,s:NetrwBrowseChgDir(curislocal,'./')) - call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + call winrestview(svpos) " call Dret("s:NetrwMarkTarget") endfun @@ -6460,6 +6591,48 @@ fun! s:NetrwMarkFile(islocal,fname) endfun " --------------------------------------------------------------------- +" s:NetrwMarkFileArgList: ma: move the marked file list to the argument list (tomflist=0) {{{2 +" mA: move the argument list to marked file list (tomflist=1) +" Uses the global marked file list +fun! s:NetrwMarkFileArgList(islocal,tomflist) +" call Dfunc("s:NetrwMarkFileArgList(islocal=".a:islocal.",tomflist=".a:tomflist.")") + + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + let curdir = s:NetrwGetCurdir(a:islocal) + let curbufnr = bufnr("%") + + if a:tomflist + " mA: move argument list to marked file list + while argc() + let fname= argv(0) +" call Decho("exe argdel ".fname,'~'.expand("<slnum>")) + exe "argdel ".fnameescape(fname) + call s:NetrwMarkFile(a:islocal,fname) + endwhile + + else + " ma: move marked file list to argument list + if exists("s:netrwmarkfilelist") + + " for every filename in the marked list + for fname in s:netrwmarkfilelist +" call Decho("exe argadd ".fname,'~'.expand("<slnum>")) + exe "argadd ".fnameescape(fname) + endfor " for every file in the marked list + + " unmark list and refresh + call s:NetrwUnmarkList(curbufnr,curdir) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) + endif + endif + +" call Dret("s:NetrwMarkFileArgList") +endfun + +" --------------------------------------------------------------------- " s:NetrwMarkFileCompress: (invoked by mz) This function is used to {{{2 " compress/decompress files using the programs " in g:netrw_compress and g:netrw_uncompress, @@ -6469,7 +6642,8 @@ endfun " g:netrw_decompress = { ".gz" : "gunzip" , ".bz2" : "bunzip2" , ".zip" : "unzip" , ".tar" : "tar -xf", ".xz" : "unxz"} fun! s:NetrwMarkFileCompress(islocal) " call Dfunc("s:NetrwMarkFileCompress(islocal=".a:islocal.")") - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curdir = s:NetrwGetCurdir(a:islocal) let curbufnr = bufnr("%") @@ -6524,7 +6698,8 @@ fun! s:NetrwMarkFileCompress(islocal) call s:NetrwUnmarkList(curbufnr,curdir) NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) endif " call Dret("s:NetrwMarkFileCompress") endfun @@ -6541,6 +6716,12 @@ fun! s:NetrwMarkFileCopy(islocal,...) let curdir = s:NetrwGetCurdir(a:islocal) let curbufnr = bufnr("%") + if b:netrw_curdir !~ '/$' + if !exists("b:netrw_curdir") + let b:netrw_curdir= curdir + endif + let b:netrw_curdir= b:netrw_curdir."/" + endif " sanity check if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr}) @@ -6557,7 +6738,7 @@ fun! s:NetrwMarkFileCopy(islocal,...) endif " call Decho("sanity chk passed: s:netrwmftgt<".s:netrwmftgt.">",'~'.expand("<slnum>")) - if a:islocal && s:netrwmftgt_islocal + if a:islocal && s:netrwmftgt_islocal " Copy marked files, local directory to local directory " call Decho("copy from local to local",'~'.expand("<slnum>")) if !executable(g:netrw_localcopycmd) && g:netrw_localcopycmd !~ '^'.expand("$COMSPEC").'\s' @@ -6571,12 +6752,12 @@ fun! s:NetrwMarkFileCopy(islocal,...) if len(s:netrwmarkfilelist_{bufnr('%')}) == 1 " only one marked file " call Decho("case: only one marked file",'~'.expand("<slnum>")) - let args = s:ShellEscape(b:netrw_curdir."/".s:netrwmarkfilelist_{bufnr('%')}[0]) + let args = s:ShellEscape(b:netrw_curdir.s:netrwmarkfilelist_{bufnr('%')}[0]) let oldname = s:netrwmarkfilelist_{bufnr('%')}[0] elseif a:0 == 1 " call Decho("case: handling one input argument",'~'.expand("<slnum>")) " this happens when the next case was used to recursively call s:NetrwMarkFileCopy() - let args = s:ShellEscape(b:netrw_curdir."/".a:1) + let args = s:ShellEscape(b:netrw_curdir.a:1) let oldname = a:1 else " copy multiple marked files inside the same directory @@ -6611,9 +6792,12 @@ fun! s:NetrwMarkFileCopy(islocal,...) let args= substitute(args,'/','\\','g') let tgt = substitute(tgt, '/','\\','g') endif - if args =~ "'"|let args= substitute(args,"'\\(.*\\)'",'\1','')|endif - if tgt =~ "'"|let tgt = substitute(tgt,"'\\(.*\\)'",'\1','') |endif - if args =~ '//$'|let args= substitute(args,'//$','/','')|endif + if args =~ "'" |let args= substitute(args,"'\\(.*\\)'",'\1','')|endif + if tgt =~ "'" |let tgt = substitute(tgt ,"'\\(.*\\)'",'\1','')|endif + if args =~ '//'|let args= substitute(args,'//','/','g')|endif + if tgt =~ '//'|let tgt = substitute(tgt ,'//','/','g')|endif +" call Decho("args <".args.">",'~'.expand("<slnum>")) +" call Decho("tgt <".tgt.">",'~'.expand("<slnum>")) if isdirectory(s:NetrwFile(args)) " call Decho("args<".args."> is a directory",'~'.expand("<slnum>")) let copycmd= g:netrw_localcopydircmd @@ -6688,11 +6872,17 @@ fun! s:NetrwMarkFileCopy(islocal,...) NetrwKeepj call s:NetrwDelete(fname) endfor call s:NetrwLcd(curdir) - call s:NetrwExe("sil !".g:netrw_localrmdir." ".s:ShellEscape(tmpdir,1)) - if v:shell_error != 0 - call netrw#ErrorMsg(s:WARNING,"consider setting g:netrw_localrmdir<".g:netrw_localrmdir."> to something that works",80) -" call Dret("s:NetrwMarkFileCopy : failed: sil !".g:netrw_localrmdir." ".s:ShellEscape(tmpdir,1) ) - return + if v:version < 704 || !has("patch1109") + call s:NetrwExe("sil !".g:netrw_localrmdir." ".s:ShellEscape(tmpdir,1)) + if v:shell_error != 0 + call netrw#ErrorMsg(s:WARNING,"consider setting g:netrw_localrmdir<".g:netrw_localrmdir."> to something that works",80) +" " call Dret("s:NetrwMarkFileCopy : failed: sil !".g:netrw_localrmdir." ".s:ShellEscape(tmpdir,1) ) + return + endif + else + if delete(tmpdir,"d") + call netrw#ErrorMsg(s:ERROR,"unable to delete directory <".tmpdir.">!",103) + endif endif else call s:NetrwLcd(curdir) @@ -6703,21 +6893,38 @@ fun! s:NetrwMarkFileCopy(islocal,...) " ------- " cleanup " ------- -" call Decho("cleanup",'~'.expand("<slnum>")) - if !exists("s:recursive") - " remove markings from local buffer - call s:NetrwUnmarkList(curbufnr,curdir) - endif - - " refresh buffers - if !s:netrwmftgt_islocal - call s:NetrwRefreshDir(s:netrwmftgt_islocal,s:netrwmftgt) - endif - if a:islocal - NetrwKeepj call s:NetrwRefreshDir(a:islocal,curdir) +" call Decho("cleanup",'~'.expand("<slnum>")) +" call Decho(" g:netrw_fastbrowse =".g:netrw_fastbrowse,'~'.expand("<slnum>")) +" call Decho(" s:netrwmftgt =".s:netrwmftgt,'~'.expand("<slnum>")) +" call Decho(" s:netrwmftgt_islocal=".s:netrwmftgt_islocal,'~'.expand("<slnum>")) +" call Decho(" curdir =".curdir,'~'.expand("<slnum>")) +" call Decho(" a:islocal =".a:islocal,'~'.expand("<slnum>")) +" call Decho(" curbufnr =".curbufnr,'~'.expand("<slnum>")) + if exists("s:recursive") +" call Decho(" s:recursive =".s:recursive,'~'.expand("<slnum>")) + else +" call Decho(" s:recursive =n/a",'~'.expand("<slnum>")) endif + " see s:LocalFastBrowser() for g:netrw_fastbrowse interpretation (refreshing done for both slow and medium) if g:netrw_fastbrowse <= 1 NetrwKeepj call s:LocalBrowseRefresh() + else + " refresh local and targets for fast browsing + if !exists("s:recursive") + " remove markings from local buffer +" call Decho(" remove markings from local buffer",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwUnmarkList(curbufnr,curdir) + endif + + " refresh buffers + if s:netrwmftgt_islocal +" call Decho(" refresh s:netrwmftgt=".s:netrwmftgt,'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefreshDir(s:netrwmftgt_islocal,s:netrwmftgt) + endif + if a:islocal && s:netrwmftgt != curdir +" call Decho(" refresh curdir=".curdir,'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefreshDir(a:islocal,curdir) + endif endif " call Dret("s:NetrwMarkFileCopy 1") @@ -6798,7 +7005,7 @@ fun! s:NetrwMarkFileEdit(islocal) endfun " --------------------------------------------------------------------- -" s:NetrwMarkFileQFEL: convert a quickfix-error list into a marked file list {{{2 +" s:NetrwMarkFileQFEL: convert a quickfix-error or location list into a marked file list {{{2 fun! s:NetrwMarkFileQFEL(islocal,qfel) " call Dfunc("s:NetrwMarkFileQFEL(islocal=".a:islocal.",qfel)") call s:NetrwUnmarkAll() @@ -6834,7 +7041,8 @@ endfun " mX enbloc=1: Uses the global marked-file list, applies command to entire list fun! s:NetrwMarkFileExe(islocal,enbloc) " call Dfunc("s:NetrwMarkFileExe(islocal=".a:islocal.",enbloc=".a:enbloc.")") - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curdir = s:NetrwGetCurdir(a:islocal) let curbufnr = bufnr("%") @@ -6894,7 +7102,8 @@ fun! s:NetrwMarkFileExe(islocal,enbloc) " refresh the listing NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) else NetrwKeepj call netrw#ErrorMsg(s:ERROR,"no files marked!",59) endif @@ -6926,7 +7135,8 @@ fun! s:NetrwMarkFileExe(islocal,enbloc) " refresh the listing NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) endif @@ -6939,7 +7149,8 @@ endfun " Uses the local marked file list. fun! s:NetrwMarkHideSfx(islocal) " call Dfunc("s:NetrwMarkHideSfx(islocal=".a:islocal.")") - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curbufnr = bufnr("%") " s:netrwmarkfilelist_{curbufnr}: the List of marked files @@ -6982,7 +7193,8 @@ fun! s:NetrwMarkHideSfx(islocal) " refresh the listing NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) else NetrwKeepj call netrw#ErrorMsg(s:ERROR,"no files marked!",59) endif @@ -6995,7 +7207,8 @@ endfun " Uses the local marked-file list. fun! s:NetrwMarkFileVimCmd(islocal) " call Dfunc("s:NetrwMarkFileVimCmd(islocal=".a:islocal.")") - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curdir = s:NetrwGetCurdir(a:islocal) let curbufnr = bufnr("%") @@ -7039,7 +7252,8 @@ fun! s:NetrwMarkFileVimCmd(islocal) " refresh the listing NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) else NetrwKeepj call netrw#ErrorMsg(s:ERROR,"no files marked!",59) endif @@ -7053,7 +7267,8 @@ endfun " Uses the local marked file list. fun! s:NetrwMarkHideSfx(islocal) " call Dfunc("s:NetrwMarkHideSfx(islocal=".a:islocal.")") - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curbufnr = bufnr("%") " s:netrwmarkfilelist_{curbufnr}: the List of marked files @@ -7096,7 +7311,8 @@ fun! s:NetrwMarkHideSfx(islocal) " refresh the listing NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) else NetrwKeepj call netrw#ErrorMsg(s:ERROR,"no files marked!",59) endif @@ -7109,7 +7325,8 @@ endfun " Uses the global markfilelist fun! s:NetrwMarkFileGrep(islocal) " call Dfunc("s:NetrwMarkFileGrep(islocal=".a:islocal.")") - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curbufnr = bufnr("%") let curdir = s:NetrwGetCurdir(a:islocal) @@ -7150,7 +7367,8 @@ fun! s:NetrwMarkFileGrep(islocal) echo "(use :cn, :cp to navigate, :Rex to return)" 2match none - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) if exists("nonisi") " original, user-supplied pattern did not begin with a character from isident @@ -7456,7 +7674,8 @@ endfun " Uses the global markfilelist fun! s:NetrwMarkFileTag(islocal) " call Dfunc("s:NetrwMarkFileTag(islocal=".a:islocal.")") - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curdir = s:NetrwGetCurdir(a:islocal) let curbufnr = bufnr("%") @@ -7494,7 +7713,8 @@ fun! s:NetrwMarkFileTag(islocal) endif 2match none call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) - call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + call winrestview(svpos) endif " call Dret("s:NetrwMarkFileTag") @@ -7507,8 +7727,9 @@ endfun " s:netrwmftgt_islocal : 0=target directory is remote " 1=target directory is local fun! s:NetrwMarkFileTgt(islocal) -" call Dfunc("s:NetrwMarkFileTgt(islocal=".a:islocal.")") - let svpos = netrw#SavePosn() +" call Dfunc("s:NetrwMarkFileTgt(islocal=".a:islocal.")") + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curdir = s:NetrwGetCurdir(a:islocal) let hadtgt = exists("s:netrwmftgt") if !exists("w:netrw_bannercnt") @@ -7526,7 +7747,8 @@ fun! s:NetrwMarkFileTgt(islocal) call s:LocalBrowseRefresh() endif call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) - call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + call winrestview(svpos) " call Dret("s:NetrwMarkFileTgt : removed target") return else @@ -7570,12 +7792,13 @@ fun! s:NetrwMarkFileTgt(islocal) call s:LocalBrowseRefresh() endif " call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) - if w:netrw_liststyle == s:TREELIST + if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,w:netrw_treetop)) else call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) endif - call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + call winrestview(svpos) if !hadtgt sil! NetrwKeepj norm! j endif @@ -7590,7 +7813,7 @@ endfun fun! s:NetrwGetCurdir(islocal) " call Dfunc("s:NetrwGetCurdir(islocal=".a:islocal.")") - if w:netrw_liststyle == s:TREELIST + if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST let b:netrw_curdir = s:NetrwTreePath(w:netrw_treetop) " call Decho("set b:netrw_curdir<".b:netrw_curdir."> (used s:NetrwTreeDir)",'~'.expand("<slnum>")) elseif !exists("b:netrw_curdir") @@ -7626,8 +7849,8 @@ fun! s:NetrwOpenFile(islocal) endif let g:netrw_quiet = 1 " save position for benefit of Rexplore - let s:rexposn_{bufnr("%")}= netrw#SavePosn() -" call Decho("setting s:rexposn_".bufnr("%")."<".bufname("%")."> to SavePosn",'~'.expand("<slnum>")) + let s:rexposn_{bufnr("%")}= winsaveview() +" call Decho("saving posn to s:rexposn_".bufnr("%")."<".string(s:rexposn_{bufnr("%")}).">",'~'.expand("<slnum>")) if b:netrw_curdir =~ '/$' exe "NetrwKeepj e ".fnameescape(b:netrw_curdir.fname) else @@ -7702,7 +7925,8 @@ fun! s:NetSortSequence(islocal) " call Dfunc("NetSortSequence(islocal=".a:islocal.")") let ykeep= @@ - let svpos= netrw#SavePosn() + let svpos= winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) call inputsave() let newsortseq= input("Edit Sorting Sequence: ",g:netrw_sort_sequence) call inputrestore() @@ -7710,7 +7934,8 @@ fun! s:NetSortSequence(islocal) " refresh the listing let g:netrw_sort_sequence= newsortseq NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) let @@= ykeep " call Dret("NetSortSequence") @@ -7785,7 +8010,8 @@ endfun " s:netrwmarkfilemtch_# -- used with 2match to display marked files fun! s:NetrwUnMarkFile(islocal) " call Dfunc("s:NetrwUnMarkFile(islocal=".a:islocal.")") - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curbufnr = bufnr("%") " unmark marked file list @@ -7806,7 +8032,8 @@ fun! s:NetrwUnMarkFile(islocal) 2match none " call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) - call netrw#RestorePosn(svpos) +"call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) +call winrestview(svpos) " call Dret("s:NetrwUnMarkFile") endfun @@ -8276,7 +8503,8 @@ fun! s:NetrwRefresh(islocal,dirname) let ykeep = @@ " save the cursor position before refresh. - let screenposn = netrw#SavePosn() + let screenposn = winsaveview() +" call Decho("saving posn to screenposn<".string(screenposn).">",'~'.expand("<slnum>")) " call Decho("win#".winnr().": ".winheight(0)."x".winwidth(0)." curfile<".expand("%").">",'~'.expand("<slnum>")) " call Decho("clearing buffer prior to refresh",'~'.expand("<slnum>")) @@ -8288,7 +8516,8 @@ fun! s:NetrwRefresh(islocal,dirname) endif " restore position - NetrwKeepj call netrw#RestorePosn(screenposn) +" call Decho("restoring posn to screenposn<".string(screenposn).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(screenposn) " restore file marks if exists("s:netrwmarkfilemtch_{bufnr('%')}") && s:netrwmarkfilemtch_{bufnr("%")} != "" @@ -8439,8 +8668,8 @@ endfun " Implements [count]Tb (bookhist<b>) " [count]Th (bookhist<h>) " See :help netrw-qb for how to make the choice. -fun! s:NetrwSetTgt(bookhist,choice) -" call Dfunc("s:NetrwSetTgt(bookhist<".a:bookhist."> choice#".a:choice.")") +fun! s:NetrwSetTgt(islocal,bookhist,choice) +" call Dfunc("s:NetrwSetTgt(islocal=".a:islocal." bookhist<".a:bookhist."> choice#".a:choice.")") if a:bookhist == 'b' " supports choosing a bookmark as a target using a qb-generated list @@ -8462,6 +8691,12 @@ fun! s:NetrwSetTgt(bookhist,choice) endif endif + " refresh the display + if !exists("b:netrw_curdir") + let b:netrw_curdir= getcwd() + endif + call s:NetrwRefresh(a:islocal,b:netrw_curdir) + " call Dret("s:NetrwSetTgt") endfun @@ -8470,12 +8705,14 @@ endfun fun! s:NetrwSortStyle(islocal) " call Dfunc("s:NetrwSortStyle(islocal=".a:islocal.") netrw_sort_by<".g:netrw_sort_by.">") NetrwKeepj call s:NetrwSaveWordPosn() - let svpos= netrw#SavePosn() + let svpos= winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let g:netrw_sort_by= (g:netrw_sort_by =~ '^n')? 'time' : (g:netrw_sort_by =~ '^t')? 'size' : (g:netrw_sort_by =~ '^siz')? 'exten' : 'name' NetrwKeepj norm! 0 NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) " call Dret("s:NetrwSortStyle : netrw_sort_by<".g:netrw_sort_by.">") endfun @@ -8653,6 +8890,9 @@ endfun " (full path directory with trailing slash returned) fun! s:NetrwTreeDir(islocal) " call Dfunc("s:NetrwTreeDir(islocal=".a:islocal.") getline(".line(".").")"."<".getline('.')."> b:netrw_curdir<".b:netrw_curdir."> tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> ft=".&ft) +" call Decho("g:netrw_keepdir =".(exists("g:netrw_keepdir")? g:netrw_keepdir : 'n/a')) +" call Decho("w:netrw_liststyle=".(exists("w:netrw_liststyle")? w:netrw_liststyle : 'n/a')) +" call Decho("w:netrw_treetop =".(exists("w:netrw_treetop")? w:netrw_treetop : 'n/a')) if exists("s:treedir") " s:NetrwPrevWinOpen opens a "previous" window -- and thus needs to and does call s:NetrwTreeDir early @@ -8665,12 +8905,13 @@ fun! s:NetrwTreeDir(islocal) if !exists("b:netrw_curdir") || b:netrw_curdir == "" let b:netrw_curdir= getcwd() endif - let treedir = b:netrw_curdir " call Decho("set initial treedir<".treedir.">",'~'.expand("<slnum>")) - let s:treecurpos= netrw#SavePosn() - if w:netrw_liststyle == s:TREELIST + let s:treecurpos= winsaveview() +" call Decho("saving posn to s:treecurpos<".string(s:treecurpos).">",'~'.expand("<slnum>")) + + if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST " call Decho("w:netrw_liststyle is TREELIST:",'~'.expand("<slnum>")) " call Decho("line#".line(".")." getline(.)<".getline('.')."> treecurpos<".string(s:treecurpos).">",'~'.expand("<slnum>")) @@ -8701,13 +8942,12 @@ fun! s:NetrwTreeDir(islocal) " call Dret("s:NetrwTreeDir <".treedir."> : (side effect) s:treecurpos<".(exists("s:treecurpos")? string(s:treecurpos) : 'n/a').">") return b:netrw_curdir " else " Decho -" call Decho(".user did not attempt to close treeroot",'~'.expand("<slnum>")) +" call Decho(".user not attempting to close treeroot",'~'.expand("<slnum>")) endif " call Decho("islocal=".a:islocal." curline<".curline.">",'~'.expand("<slnum>")) -" call Decho("after subst<".substitute(curline,'^'.s:treedepthstring.'\+ \(.*\)$','\1','').">",'~'.expand("<slnum>")) - let potentialdir= substitute(curline,'^'.s:treedepthstring.'* \(.*\)@$','\1','') -" call Decho("potentialdir<".potentialdir."> isdir=".isdirectory(s:NetrwFile(potentialdir)),'~'.expand("<slnum>")) + let potentialdir= s:NetrwFile(substitute(curline,'^'.s:treedepthstring.'\+ \(.*\)@$','\1','')) +" call Decho("potentialdir<".potentialdir."> isdir=".isdirectory(potentialdir),'~'.expand("<slnum>")) " COMBAK: a symbolic link may point anywhere -- so it will be used to start a new treetop " if a:islocal && curline =~ '@$' && isdirectory(s:NetrwFile(potentialdir)) @@ -8763,9 +9003,13 @@ fun! s:NetrwTreeDisplay(dir,depth) let depth= s:treedepthstring.a:depth " call Decho("display subtrees with depth<".depth."> and current leaves",'~'.expand("<slnum>")) -" call Decho("w:netrw_treedict[".dir."]=".string(w:netrw_treedict[dir]),'~'.expand("<slnum>")) +" call Decho("for every entry in w:netrw_treedict[".dir."]=".string(w:netrw_treedict[dir]),'~'.expand("<slnum>")) for entry in w:netrw_treedict[dir] - let direntry= substitute(dir.'/'.entry,'[@/]$','','e') + if dir =~ '/$' + let direntry= substitute(dir.entry,'[@/]$','','e') + else + let direntry= substitute(dir.'/'.entry,'[@/]$','','e') + endif " call Decho("dir<".dir."> entry<".entry."> direntry<".direntry.">",'~'.expand("<slnum>")) if entry =~ '/$' && has_key(w:netrw_treedict,direntry) " call Decho("<".direntry."> is a key in treedict - display subtree for it",'~'.expand("<slnum>")) @@ -8786,10 +9030,48 @@ fun! s:NetrwTreeDisplay(dir,depth) endfun " --------------------------------------------------------------------- +" s:NetrwRefreshTreeDict: updates the contents information for a tree (w:netrw_treedict) {{{2 +fun! s:NetrwRefreshTreeDict(dir) +" call Dfunc("s:NetrwRefreshTreeDict(dir<".a:dir.">)") + for entry in w:netrw_treedict[a:dir] + let direntry= substitute(a:dir.'/'.entry,'[@/]$','','e') +" call Decho("a:dir<".a:dir."> entry<".entry."> direntry<".direntry.">",'~'.expand("<slnum>")) + + if entry =~ '/$' && has_key(w:netrw_treedict,direntry) +" call Decho("<".direntry."> is a key in treedict - display subtree for it",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefreshTreeDict(direntry) + let liststar = s:NetrwGlob(direntry,'*') + let listdotstar = s:NetrwGlob(direntry,'.*') + let w:netrw_treedict[direntry] = liststar + listdotstar +" call Decho("updating w:netrw_treedict[".direntry.']='.string(w:netrw_treedict[direntry]),'~'.expand("<slnum>")) + + elseif entry =~ '/$' && has_key(w:netrw_treedict,direntry.'/') +" call Decho("<".direntry."/> is a key in treedict - display subtree for it",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefreshTreeDict(direntry.'/') + let liststar = s:NetrwGlob(direntry.'/','*') + let listdotstar= s:NetrwGlob(direntry.'/','.*') + let w:netrw_treedict[direntry]= liststar + listdotstar +" call Decho("updating w:netrw_treedict[".direntry.']='.string(w:netrw_treedict[direntry]),'~'.expand("<slnum>")) + + elseif entry =~ '@$' && has_key(w:netrw_treedict,direntry.'@') +" call Decho("<".direntry."/> is a key in treedict - display subtree for it",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefreshTreeDict(direntry.'/') + let liststar = s:NetrwGlob(direntry.'/','*') + let listdotstar= s:NetrwGlob(direntry.'/','.*') +" call Decho("updating w:netrw_treedict[".direntry.']='.string(w:netrw_treedict[direntry]),'~'.expand("<slnum>")) + + else +" call Decho('not updating w:netrw_treedict['.direntry.'] with entry<'.entry.'> (no subtree)',,'~'.expand("<slnum>")) + endif + endfor +" call Dret("s:NetrwRefreshTreeDict") +endfun + +" --------------------------------------------------------------------- " s:NetrwTreeListing: displays tree listing from treetop on down, using NetrwTreeDisplay() {{{2 " Called by s:PerformListing() fun! s:NetrwTreeListing(dirname) - if w:netrw_liststyle == s:TREELIST + if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST " call Dfunc("NetrwTreeListing() bufname<".expand("%").">") " call Decho("curdir<".a:dirname.">",'~'.expand("<slnum>")) " call Decho("win#".winnr().": w:netrw_treetop ".(exists("w:netrw_treetop")? "exists" : "doesn't exist")." w:netrw_treedict ".(exists("w:netrw_treedict")? "exists" : "doesn't exit"),'~'.expand("<slnum>")) @@ -8811,13 +9093,13 @@ fun! s:NetrwTreeListing(dirname) let w:netrw_treedict= {} endif - " update the directory listing for the current directory -" call Decho("updating dictionary with ".a:dirname.":[..directory listing..]",'~'.expand("<slnum>")) + " update the dictionary for the current directory +" call Decho("updating: w:netrw_treedict[".a:dirname.'] -> [directory listing]','~'.expand("<slnum>")) " call Decho("w:netrw_bannercnt=".w:netrw_bannercnt." line($)=".line("$"),'~'.expand("<slnum>")) - exe "sil! NetrwKeepj ".w:netrw_bannercnt.',$g@^\.\.\=/$@d' + exe "sil! NetrwKeepj ".w:netrw_bannercnt.',$g@^\.\.\=/$@d _' let w:netrw_treedict[a:dirname]= getline(w:netrw_bannercnt,line("$")) " call Decho("w:treedict[".a:dirname."]= ".string(w:netrw_treedict[a:dirname]),'~'.expand("<slnum>")) - exe "sil! NetrwKeepj ".w:netrw_bannercnt.",$d" + exe "sil! NetrwKeepj ".w:netrw_bannercnt.",$d _" " if past banner, record word if exists("w:netrw_bannercnt") && line(".") > w:netrw_bannercnt @@ -8852,6 +9134,8 @@ endfun " wipes that out prior to calling this function fun! s:NetrwTreePath(treetop) " call Dfunc("s:NetrwTreePath() line#".line(".")."<".getline(".").">") + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let depth = substitute(getline('.'),'^\(\%('.s:treedepthstring.'\)*\)[^'.s:treedepthstring.'].\{-}$','\1','e') " call Decho("depth<".depth."> 1st subst",'~'.expand("<slnum>")) let depth = substitute(depth,'^'.s:treedepthstring,'','') @@ -8886,6 +9170,8 @@ fun! s:NetrwTreePath(treetop) let treedir= a:treetop.'/'.treedir endif let treedir= substitute(treedir,'//$','/','') +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>"))" + call winrestview(svpos) " call Dret("s:NetrwTreePath <".treedir.">") return treedir endfun @@ -8930,6 +9216,7 @@ fun! s:NetrwWideListing() " call Decho("bannercnt=".w:netrw_bannercnt." fpl=".w:netrw_fpl." fpc=".fpc." newcol[".newcolstart.",".newcolend."]",'~'.expand("<slnum>")) if has("clipboard") sil! let keepregstar = @* + sil! let keepregplus = @+ endif while line("$") >= newcolstart if newcolend > line("$") | let newcolend= line("$") | endif @@ -8940,11 +9227,12 @@ fun! s:NetrwWideListing() else exe "sil! NetrwKeepj norm! 0\<c-v>".newcolqty.'j$hx'.w:netrw_bannercnt.'G$p' endif - exe "sil! NetrwKeepj ".newcolstart.','.newcolend.'d' + exe "sil! NetrwKeepj ".newcolstart.','.newcolend.'d _' exe 'sil! NetrwKeepj '.w:netrw_bannercnt endwhile if has("clipboard") sil! let @*= keepregstar + sil! let @+= keepregplus endif exe "sil! NetrwKeepj ".w:netrw_bannercnt.',$s/\s\+$//e' NetrwKeepj call histdel("/",-1) @@ -9205,7 +9493,7 @@ fun! s:PerformListing(islocal) " call Decho("settings buf#".bufnr("%")."<".bufname("%").">: ".((&l:ma == 0)? "no" : "")."ma ".((&l:mod == 0)? "no" : "")."mod ".((&l:bl == 0)? "no" : "")."bl ".((&l:ro == 0)? "no" : "")."ro fo=".&l:fo. " (internal#3)",'~'.expand("<slnum>")) " resolve symbolic links if local and (thin or tree) - if a:islocal && (w:netrw_liststyle == s:THINLIST || w:netrw_liststyle == s:TREELIST) + if a:islocal && (w:netrw_liststyle == s:THINLIST || (exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST)) " call Decho("--resolve symbolic links if local and thin|tree",'~'.expand("<slnum>")) g/@$/call s:ShowLink() endif @@ -9247,7 +9535,8 @@ fun! s:PerformListing(islocal) if exists("s:treecurpos") " call Decho("s:treecurpos exists; restore posn",'~'.expand("<slnum>")) " call Decho("settings buf#".bufnr("%")."<".bufname("%").">: ".((&l:ma == 0)? "no" : "")."ma ".((&l:mod == 0)? "no" : "")."mod ".((&l:bl == 0)? "no" : "")."bl ".((&l:ro == 0)? "no" : "")."ro fo=".&l:fo. " (internal#8)",'~'.expand("<slnum>")) - NetrwKeepj call netrw#RestorePosn(s:treecurpos) +" call Decho("restoring posn to s:treecurpos<".string(s:treecurpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(s:treecurpos) unlet s:treecurpos endif @@ -9310,7 +9599,7 @@ endfun " enforced here. fun! s:NetrwRemoteFtpCmd(path,listcmd) " call Dfunc("NetrwRemoteFtpCmd(path<".a:path."> listcmd<".a:listcmd.">) w:netrw_method=".(exists("w:netrw_method")? w:netrw_method : (exists("b:netrw_method")? b:netrw_method : "???"))) -" call Decho("line($)=".line("$")." w:netrw_bannercnt=".w:netrw_bannercnt,'~'.expand("<slnum>")) +" call Decho("line($)=".line("$")." win#".winnr()." w:netrw_bannercnt=".w:netrw_bannercnt,'~'.expand("<slnum>")) " sanity check: {{{3 if !exists("w:netrw_method") if exists("b:netrw_method") @@ -9329,8 +9618,8 @@ fun! s:NetrwRemoteFtpCmd(path,listcmd) " clear off any older non-banner lines " {{{3 " note that w:netrw_bannercnt indexes the line after the banner -" call Decho('exe sil! NetrwKeepj '.w:netrw_bannercnt.",$d (clear off old non-banner lines)",'~'.expand("<slnum>")) - exe "sil! NetrwKeepj ".w:netrw_bannercnt.",$d" +" call Decho('exe sil! NetrwKeepj '.w:netrw_bannercnt.",$d _ (clear off old non-banner lines)",'~'.expand("<slnum>")) + exe "sil! NetrwKeepj ".w:netrw_bannercnt.",$d _" "......................................... if w:netrw_method == 2 || w:netrw_method == 5 " {{{3 @@ -9427,7 +9716,7 @@ fun! s:NetrwRemoteFtpCmd(path,listcmd) sil! NetrwKeepj g/l\%([-r][-w][-x]\)\{3}/NetrwKeepj s/$/@/e NetrwKeepj call histdel("/",-1) NetrwKeepj call histdel("/",-1) - if w:netrw_liststyle == s:THINLIST || w:netrw_liststyle == s:WIDELIST || w:netrw_liststyle == s:TREELIST + if w:netrw_liststyle == s:THINLIST || w:netrw_liststyle == s:WIDELIST || (exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST) exe "sil! NetrwKeepj ".w:netrw_bannercnt.',$s/^\%(\S\+\s\+\)\{8}//e' NetrwKeepj call histdel("/",-1) endif @@ -9451,7 +9740,7 @@ endfun " --------------------------------------------------------------------- " s:NetrwRemoteListing: {{{2 fun! s:NetrwRemoteListing() -" call Dfunc("s:NetrwRemoteListing() b:netrw_curdir<".b:netrw_curdir.">)") +" call Dfunc("s:NetrwRemoteListing() b:netrw_curdir<".b:netrw_curdir.">) win#".winnr()) if !exists("w:netrw_bannercnt") && exists("s:bannercnt") let w:netrw_bannercnt= s:bannercnt @@ -9515,7 +9804,7 @@ fun! s:NetrwRemoteListing() let mesg= getline(".") if exists("w:netrw_bannercnt") setl ma - exe w:netrw_bannercnt.",$d" + exe w:netrw_bannercnt.",$d _" setl noma endif NetrwKeepj call s:NetrwOptionRestore("w:") @@ -9524,7 +9813,7 @@ fun! s:NetrwRemoteListing() return -1 endif - if w:netrw_liststyle == s:THINLIST || w:netrw_liststyle == s:WIDELIST || w:netrw_liststyle == s:TREELIST + if w:netrw_liststyle == s:THINLIST || w:netrw_liststyle == s:WIDELIST || (exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST) " shorten the listing " call Decho("generate short listing",'~'.expand("<slnum>")) exe "sil! keepalt NetrwKeepj ".w:netrw_bannercnt @@ -9654,7 +9943,8 @@ endfun fun! s:NetrwRemoteRm(usrhost,path) range " call Dfunc("s:NetrwRemoteRm(usrhost<".a:usrhost."> path<".a:path.">) virtcol=".virtcol(".")) " call Decho("firstline=".a:firstline." lastline=".a:lastline,'~'.expand("<slnum>")) - let svpos= netrw#SavePosn() + let svpos= winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let all= 0 if exists("s:netrwmarkfilelist_{bufnr('%')}") @@ -9696,7 +9986,8 @@ fun! s:NetrwRemoteRm(usrhost,path) range " refresh the (remote) directory listing " call Decho("refresh remote directory listing",'~'.expand("<slnum>")) NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) " call Dret("s:NetrwRemoteRm") endfun @@ -9736,7 +10027,7 @@ fun! s:NetrwRemoteRmFile(path,rmfile,all) if path =~ '^\a\{3,}://' let path= substitute(path,'^\a\{3,}://[^/]\+/','','') endif - sil! NetrwKeepj .,$d + sil! NetrwKeepj .,$d _ call s:NetrwRemoteFtpCmd(path,"delete ".'"'.a:rmfile.'"') else " call Decho("case ssh: g:netrw_rm_cmd<".g:netrw_rm_cmd.">",'~'.expand("<slnum>")) @@ -9827,7 +10118,8 @@ fun! s:NetrwRemoteRename(usrhost,path) range " call Dfunc("NetrwRemoteRename(usrhost<".a:usrhost."> path<".a:path.">)") " preparation for removing multiple files/directories - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let ctr = a:firstline let rename_cmd = s:MakeSshCmd(g:netrw_rename_cmd) @@ -9893,7 +10185,8 @@ fun! s:NetrwRemoteRename(usrhost,path) range " refresh the directory NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) " call Dret("NetrwRemoteRename") endfun @@ -9955,7 +10248,7 @@ endfun " --------------------------------------------------------------------- " netrw#LocalBrowseCheck: {{{2 fun! netrw#LocalBrowseCheck(dirname) - " This function is called by netrwPlugin.vim's s:LocalBrowse() and by s:NetrwRexplore() + " This function is called by netrwPlugin.vim's s:LocalBrowse(), s:NetrwRexplore(), and by <cr> when atop listed file/directory " unfortunate interaction -- split window debugging can't be " used here, must use D-echoRemOn or D-echoTabOn -- the BufEnter " event triggers another call to LocalBrowseCheck() when attempts @@ -10074,6 +10367,9 @@ fun! s:LocalBrowseRefresh() let g:netrw_quickhelp= g:netrw_quickhelp - 1 endif " call Decho("#3: quickhelp=".g:netrw_quickhelp,'~'.expand("<slnum>")) + if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST + NetrwKeepj call s:NetrwRefreshTreeDict(w:netrw_treetop) + endif NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./')) endif let ibl= ibl + 1 @@ -10263,6 +10559,9 @@ fun! s:LocalListing() if w:netrw_liststyle == s:LONGLIST let sz = getfsize(filename) + if g:netrw_sizestyle =~ "[hH]" + let sz= s:NetrwHumanReadable(sz) + endif let fsz = strpart(" ",1,15-strlen(sz)).sz let pfile= pfile."\t".fsz." ".strftime(g:netrw_timefmt,getftime(filename)) " call Decho("sz=".sz." fsz=".fsz,'~'.expand("<slnum>")) @@ -10281,6 +10580,9 @@ fun! s:LocalListing() " sort by size (handles file sizes up to 1 quintillion bytes, US) " call Decho("getfsize(".filename.")=".getfsize(filename),'~'.expand("<slnum>")) let sz = getfsize(filename) + if g:netrw_sizestyle =~ "[hH]" + let sz= s:NetrwHumanReadable(sz) + endif let fsz = strpart("000000000000000000",1,18-strlen(sz)).sz " call Decho("exe NetrwKeepj put ='".fsz.'/'.filename."'",'~'.expand("<slnum>")) let fszpfile= fsz.'/'.pfile @@ -10339,7 +10641,8 @@ fun! s:NetrwLocalRename(path) range " preparation for removing multiple files/directories let ykeep = @@ let ctr = a:firstline - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) " rename files given by the markfilelist if exists("s:netrwmarkfilelist_{bufnr('%')}") @@ -10405,7 +10708,8 @@ fun! s:NetrwLocalRename(path) range " refresh the directory " call Decho("refresh the directory listing",'~'.expand("<slnum>")) NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) let @@= ykeep " call Dret("NetrwLocalRename") @@ -10421,7 +10725,8 @@ fun! s:NetrwLocalRm(path) range let ykeep = @@ let ret = 0 let all = 0 - let svpos = netrw#SavePosn() + let svpos = winsaveview() +" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) if exists("s:netrwmarkfilelist_{bufnr('%')}") " remove all marked files @@ -10471,7 +10776,8 @@ fun! s:NetrwLocalRm(path) range " call Decho("bufname<".bufname("%").">",'~'.expand("<slnum>")) if bufname("%") != "NetrwMessage" NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./')) - NetrwKeepj call netrw#RestorePosn(svpos) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(svpos) endif let @@= ykeep @@ -10533,28 +10839,34 @@ fun! s:NetrwLocalRmFile(path,fname,all) let rmfile= substitute(rmfile,'[\/]$','','e') if all || ok =~ 'y\%[es]' || ok == "" -" call Decho("1st attempt: system(netrw#WinPath(".g:netrw_localrmdir.') '.s:ShellEscape(rmfile).')','~'.expand("<slnum>")) - call system(netrw#WinPath(g:netrw_localrmdir).' '.s:ShellEscape(rmfile)) -" call Decho("v:shell_error=".v:shell_error,'~'.expand("<slnum>")) + if v:version < 704 || !has("patch1109") +" " call Decho("1st attempt: system(netrw#WinPath(".g:netrw_localrmdir.') '.s:ShellEscape(rmfile).')','~'.expand("<slnum>")) + call system(netrw#WinPath(g:netrw_localrmdir).' '.s:ShellEscape(rmfile)) +" " call Decho("v:shell_error=".v:shell_error,'~'.expand("<slnum>")) - if v:shell_error != 0 -" call Decho("2nd attempt to remove directory<".rmfile.">",'~'.expand("<slnum>")) - let errcode= s:NetrwDelete(rmfile) -" call Decho("errcode=".errcode,'~'.expand("<slnum>")) - - if errcode != 0 - if has("unix") -" call Decho("3rd attempt to remove directory<".rmfile.">",'~'.expand("<slnum>")) - call system("rm ".s:ShellEscape(rmfile)) - if v:shell_error != 0 && !exists("g:netrw_quiet") - call netrw#ErrorMsg(s:ERROR,"unable to remove directory<".rmfile."> -- is it empty?",34) + if v:shell_error != 0 +" " call Decho("2nd attempt to remove directory<".rmfile.">",'~'.expand("<slnum>")) + let errcode= s:NetrwDelete(rmfile) +" " call Decho("errcode=".errcode,'~'.expand("<slnum>")) + + if errcode != 0 + if has("unix") +" " call Decho("3rd attempt to remove directory<".rmfile.">",'~'.expand("<slnum>")) + call system("rm ".s:ShellEscape(rmfile)) + if v:shell_error != 0 && !exists("g:netrw_quiet") + call netrw#ErrorMsg(s:ERROR,"unable to remove directory<".rmfile."> -- is it empty?",34) + let ok="no" + endif + elseif !exists("g:netrw_quiet") + call netrw#ErrorMsg(s:ERROR,"unable to remove directory<".rmfile."> -- is it empty?",35) let ok="no" endif - elseif !exists("g:netrw_quiet") - call netrw#ErrorMsg(s:ERROR,"unable to remove directory<".rmfile."> -- is it empty?",35) - let ok="no" endif endif + else + if delete(rmfile,"d") + call netrw#ErrorMsg(s:ERROR,"unable to delete directory <".rmfile.">!",103) + endif endif endif endif @@ -10594,81 +10906,6 @@ fun! netrw#Call(funcname,...) endfun " ------------------------------------------------------------------------ -" netrw#RestorePosn: restores the cursor and file position as saved by netrw#SavePosn() {{{2 -fun! netrw#RestorePosn(...) -" call Dfunc("netrw#RestorePosn() a:0=".a:0." winnr=".(exists("w:netrw_winnr")? w:netrw_winnr : -1)." line=".(exists("w:netrw_line")? w:netrw_line : -1)." col=".(exists("w:netrw_col")? w:netrw_col : -1)." hline=".(exists("w:netrw_hline")? w:netrw_hline : -1)) - let eikeep= &ei - setl ei=all - if expand("%") == "NetrwMessage" - if exists("s:winBeforeErr") - exe s:winBeforeErr."wincmd w" - endif - endif - - if a:0 > 0 - exe "keepj ".a:1 - endif -" "call Decho("a:1 = ".((a:0 > 0)? a:1 : 'n/a'),'~'.expand("<slnum>")) -" "call Decho("liststyle = ".(exists("liststyle")? liststyle : 'n/a'). " w:netrw_liststyle=".(exists("w:netrw_liststyle")? w:netrw_liststyle : 'n/a'),'~'.expand("<slnum>")) - if exists("liststyle") && exists("w:netrw_liststyle") && liststyle != w:netrw_liststyle - let usesrch= 1 - else - let usesrch= 0 - endif - -" "call Decho("winh = ".(exists("w:netrw_winh")? w:netrw_winh : -1),'~'.expand("<slnum>")) -" "call Decho("winw = ".(exists("w:netrw_winw")? w:netrw_winw : -1),'~'.expand("<slnum>")) -" "call Decho("cur winheight=".winheight(0)." winwidth=".winwidth(0),'~'.expand("<slnum>")) -" "call Decho("w:netrw_winfile = ".(exists("w:netrw_winfile")? w:netrw_winfile : 'n/a'),'~'.expand("<slnum>")) - - " restore window - if exists("w:netrw_winnr") -" "call Decho("restore window: exe sil! ".w:netrw_winnr."wincmd w",'~'.expand("<slnum>")) - exe "sil! ".w:netrw_winnr."wincmd w" - endif -" if v:shell_error == 0 - " as suggested by Bram M: redraw on no error - " allows protocol error messages to remain visible -" redraw! -" endif - - " restore top-of-screen line - if exists("w:netrw_hline") -" "call Decho("restore topofscreen: exe keepj norm! ".w:netrw_hline."G0z",'~'.expand("<slnum>")) - exe "keepj norm! ".w:netrw_hline."G0z\<CR>" - endif - - " restore position - " when the window's height x width has changed, the line,col is no longer useful - if w:netrw_winh == winheight(0) && w:netrw_winw == winwidth(0) && exists("w:netrw_line") && exists("w:netrw_col") && !usesrch -" "call Decho("using posn: exe keepj norm! ".w:netrw_line."G0".w:netrw_col."|",'~'.expand("<slnum>")) - exe "keepj norm! ".w:netrw_line."G0".w:netrw_col."\<bar>" - - elseif exists("w:netrw_winfile") - if !search('\<'.escape(w:netrw_winfile,g:netrw_fname_escape),'cw') - if exists("w:netrw_bannercnt") -" "call Decho("using bannercnt: win#".winnr()." ".winheight(0)."x".winwidth(0)." w:netrw_winfile<".w:netrw_winfile.">",'~'.expand("<slnum>")) - exe "keepj ".w:netrw_bannercnt - norm! 0 - else - " go to upper left corner -" "call Decho("goto ulc: win#".winnr()." ".winheight(0)."x".winwidth(0)." w:netrw_winfile<".w:netrw_winfile.">",'~'.expand("<slnum>")) - keepj 1 - norm! 0 - endif - else -" "call Decho("used search: w:netrw_winfile<".w:netrw_winfile.">",'~'.expand("<slnum>")) - endif - - else -" "call Decho("goto ulc: win#".winnr()." ".winheight(0)."x".winwidth(0),'~'.expand("<slnum>")) - keepj 1 - norm! 0 - endif - - let &ei= eikeep -" call Dret("netrw#RestorePosn : line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol()) -endfun " --------------------------------------------------------------------- " netrw#Expose: allows UserMaps and pchk to look at otherwise script-local variables {{{2 @@ -10713,48 +10950,6 @@ fun! netrw#RFC2396(fname) endfun " --------------------------------------------------------------------- -" netrw#SavePosn: saves position of cursor on screen {{{2 -fun! netrw#SavePosn() -" call Dfunc("netrw#SavePosn() win#".winnr()." line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol()) - " Save current line and column - let w:netrw_winnr= winnr() - let w:netrw_line = line(".") - let w:netrw_col = virtcol(".") -" "call Decho("currently, win#".w:netrw_winnr." line#".w:netrw_line." col#".w:netrw_col,'~'.expand("<slnum>")) - - " save filename under cursor -" "call Decho("line#".line(".")." w:netrw_bannercnt=".(exists("w:netrw_bannercnt")? w:netrw_bannercnt : 'n/a'),'~'.expand("<slnum>")) - if exists("w:netrw_bannercnt") && line(".") >= w:netrw_bannercnt && &ft == "netrw" - let winfile = "|let w:netrw_winfile=\"".fnameescape(s:NetrwGetWord())."\"" - else - let winfile= "" - endif -" "call Decho("winfile<".winfile.">",'~'.expand("<slnum>")) - if exists("w:netrw_liststyle") - let liststyle = "|let liststyle=".w:netrw_liststyle - else - let liststyle= "" - endif -" "call Decho("liststyle=".liststyle,'~'.expand("<slnum>")) - - " Save top-of-screen line - keepj norm! H0 - let w:netrw_hline= line(".") - - " save up alternate position information - " use this when window height x width has changed - let w:netrw_winh = winheight(0) - let w:netrw_winw = winwidth(0) - - " set up string holding position parameters - let ret = "let w:netrw_winnr=".w:netrw_winnr."|let w:netrw_line=".w:netrw_line."|let w:netrw_col=".w:netrw_col."|let w:netrw_hline=".w:netrw_hline."|let w:netrw_winh=".w:netrw_winh."|let w:netrw_winw=".w:netrw_winw.liststyle.winfile - - keepj call netrw#RestorePosn() -" call Dret("netrw#SavePosn : win#=".(exists("w:netrw_winnr")? w:netrw_winnr : "n/a")." line=".(exists("w:netrw_line")? w:netrw_line : "n/a")." col=".(exists("w:netrw_col")? w:netrw_col : "n/a")." hline=".(exists("w:netrw_hline")? w:netrw_hline : "n/a")) - return ret -endfun - -" --------------------------------------------------------------------- " netrw#UserMaps: supports user-specified maps {{{2 " see :help function() " @@ -11198,6 +11393,9 @@ fun! s:NetrwEnew(...) NetrwKeepj call s:NetrwOptionRestore("w:") " call Decho("generate a buffer with NetrwKeepj keepalt enew!",'~'.expand("<slnum>")) + " when tree listing uses file TreeListing... a new buffer is made. + " Want the old buffer to be unlisted. + setl nobl let netrw_keepdiff= &l:diff noswapfile NetrwKeepj keepalt enew! let &l:diff= netrw_keepdiff @@ -11227,8 +11425,9 @@ fun! s:NetrwEnew(...) let b:netrw_curdir= a:1 if b:netrw_curdir =~ '/$' if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST + setl nobl file NetrwTreeListing - setl bt=nowrite noswf bh=hide + setl nobl bt=nowrite bh=hide nno <silent> <buffer> [ :sil call <SID>TreeListMove('[')<cr> nno <silent> <buffer> ] :sil call <SID>TreeListMove(']')<cr> else @@ -11331,6 +11530,50 @@ fun! s:NetrwSaveWordPosn() endfun " --------------------------------------------------------------------- +" s:NetrwHumanReadable: takes a number and makes it "human readable" {{{2 +" 1000 -> 1K, 1000000 -> 1M, 1000000000 -> 1G +fun! s:NetrwHumanReadable(sz) +" call Dfunc("s:NetrwHumanReadable(sz=".a:sz.") type=".type(a:sz)." style=".g:netrw_sizestyle ) + + if g:netrw_sizestyle == 'h' + if a:sz >= 1000000000 + let sz = printf("%.1f",a:sz/1000000000.0)."g" + elseif a:sz >= 10000000 + let sz = printf("%d",a:sz/1000000)."m" + elseif a:sz >= 1000000 + let sz = printf("%.1f",a:sz/1000000.0)."m" + elseif a:sz >= 10000 + let sz = printf("%d",a:sz/1000)."k" + elseif a:sz >= 1000 + let sz = printf("%.1f",a:sz/1000.0)."k" + else + let sz= a:sz + endif + + elseif g:netrw_sizestyle == 'H' + if a:sz >= 1073741824 + let sz = printf("%.1f",a:sz/1073741824.0)."G" + elseif a:sz >= 10485760 + let sz = printf("%d",a:sz/1048576)."M" + elseif a:sz >= 1048576 + let sz = printf("%.1f",a:sz/1048576.0)."M" + elseif a:sz >= 10240 + let sz = printf("%d",a:sz/1024)."K" + elseif a:sz >= 1024 + let sz = printf("%.1f",a:sz/1024.0)."K" + else + let sz= a:sz + endif + + else + let sz= a:sz + endif + +" call Dret("s:NetrwHumanReadable ".sz) + return sz +endfun + +" --------------------------------------------------------------------- " s:NetrwRestoreWordPosn: used to keep cursor on same word after refresh, {{{2 " changed sorting, etc. Also see s:NetrwSaveWordPosn(). fun! s:NetrwRestoreWordPosn() @@ -11449,7 +11692,7 @@ fun! s:NetrwRexplore(islocal,dirname) if exists("s:netrwdrag") return endif -" call Dfunc("s:NetrwRexplore() w:netrw_rexlocal=".w:netrw_rexlocal." w:netrw_rexdir<".w:netrw_rexdir.">") +" call Dfunc("s:NetrwRexplore() w:netrw_rexlocal=".w:netrw_rexlocal." w:netrw_rexdir<".w:netrw_rexdir."> win#".winnr()) " call Decho("currently in bufname<".bufname("%").">",'~'.expand("<slnum>")) " call Decho("ft=".&ft." win#".winnr()." w:netrw_rexfile<".(exists("w:netrw_rexfile")? w:netrw_rexfile : 'n/a').">",'~'.expand("<slnum>")) @@ -11474,7 +11717,7 @@ fun! s:NetrwRexplore(islocal,dirname) " call Decho("set w:netrw_rexfile<".w:netrw_rexfile."> (win#".winnr().")",'~'.expand("<slnum>")) if !exists("w:netrw_rexlocal") -" call Dret("s:NetrwRexplore w:netrw_rexlocal doesn't exist (".&ft.")") +" call Dret("s:NetrwRexplore w:netrw_rexlocal doesn't exist (".&ft." win#".winnr().")") return endif " call Decho("settings buf#".bufnr("%")."<".bufname("%").">: ".((&l:ma == 0)? "no" : "")."ma ".((&l:mod == 0)? "no" : "")."mod ".((&l:bl == 0)? "no" : "")."bl ".((&l:ro == 0)? "no" : "")."ro fo=".&l:fo,'~'.expand("<slnum>")) @@ -11489,7 +11732,8 @@ fun! s:NetrwRexplore(islocal,dirname) if exists("s:rexposn_".bufnr("%")) " call Decho("restore posn, then unlet s:rexposn_".bufnr('%')."<".bufname("%").">",'~'.expand("<slnum>")) " restore position in directory listing - NetrwKeepj call netrw#RestorePosn(s:rexposn_{bufnr('%')}) +" call Decho("restoring posn to s:rexposn_".bufnr('%')."<".string(s:rexposn_{bufnr('%')}).">",'~'.expand("<slnum>")) + NetrwKeepj call winrestview(s:rexposn_{bufnr('%')}) if exists("s:rexposn_".bufnr('%')) unlet s:rexposn_{bufnr('%')} endif @@ -11571,10 +11815,13 @@ endfun " --------------------------------------------------------------------- " s:SetRexDir: set directory for :Rexplore {{{2 fun! s:SetRexDir(islocal,dirname) -" call Dfunc("s:SetRexDir(islocal=".a:islocal." dirname<".a:dirname.">)") +" call Dfunc("s:SetRexDir(islocal=".a:islocal." dirname<".a:dirname.">) win#".winnr()) let w:netrw_rexdir = a:dirname let w:netrw_rexlocal = a:islocal - let s:rexposn_{bufnr("%")} = netrw#SavePosn() + let s:rexposn_{bufnr("%")} = winsaveview() +" call Decho("setting w:netrw_rexdir =".w:netrw_rexdir) +" call Decho("setting w:netrw_rexlocal=".w:netrw_rexlocal) +" call Decho("saving posn to s:rexposn_".bufnr("%")."<".string(s:rexposn_{bufnr("%")}).">",'~'.expand("<slnum>")) " call Decho("setting s:rexposn_".bufnr("%")."<".bufname("%")."> to SavePosn",'~'.expand("<slnum>")) " call Dret("s:SetRexDir : win#".winnr()." ".(a:islocal? "local" : "remote")." dir: ".a:dirname) endfun @@ -11685,56 +11932,39 @@ fun! s:ShellEscape(s, ...) endfun " --------------------------------------------------------------------- -" s:TreeListMove: {{{2 +" s:TreeListMove: supports [[, ]], [], and ][ in tree mode {{{2 fun! s:TreeListMove(dir) " call Dfunc("s:TreeListMove(dir<".a:dir.">)") - let curline = getline('.') - let prvline = (line(".") > 1)? getline(line(".")-1) : '' - let nxtline = (line(".") < line("$"))? getline(line(".")+1) : '' - let curindent= substitute(curline,'^\([| ]*\).\{-}$','\1','') - let indentm1 = substitute(curindent,'^'.s:treedepthstring.' ','','') -" call Decho("prvline <".prvline."> #".line(".")-1,'~'.expand("<slnum>")) -" call Decho("curline <".curline."> #".line("."),'~'.expand("<slnum>")) -" call Decho("nxtline <".nxtline."> #".line(".")+1,'~'.expand("<slnum>")) -" call Decho("curindent<".curindent.">",'~'.expand("<slnum>")) -" call Decho("indentm1 <".indentm1.">",'~'.expand("<slnum>")) - + let curline = getline('.') + let prvline = (line(".") > 1)? getline(line(".")-1) : '' + let nxtline = (line(".") < line("$"))? getline(line(".")+1) : '' + let curindent = substitute(getline('.'),'^\(\%('.s:treedepthstring.'\)*\)[^'.s:treedepthstring.'].\{-}$','\1','e') + let indentm1 = substitute(curindent,'^'.s:treedepthstring,'','') + let treedepthchr = substitute(s:treedepthstring,' ','','g') + let stopline = exists("w:netrw_bannercnt")? w:netrw_bannercnt : 1 +" call Decho("prvline <".prvline."> #".(line(".")-1), '~'.expand("<slnum>")) +" call Decho("curline <".curline."> #".line(".") , '~'.expand("<slnum>")) +" call Decho("nxtline <".nxtline."> #".(line(".")+1), '~'.expand("<slnum>")) +" call Decho("curindent<".curindent.">" , '~'.expand("<slnum>")) +" call Decho("indentm1 <".indentm1.">" , '~'.expand("<slnum>")) + " COMBAK : need to handle when on a directory + " COMBAK : need to handle ]] and ][. In general, needs work!!! if curline !~ '/$' -" call Decho('regfile','~'.expand("<slnum>")) - if a:dir == '[' && prvline != '' + if a:dir == '[[' && prvline != '' NetrwKeepj norm! 0 - let nl = search('^'.indentm1.'[^'.s:treedepthstring.']','bWe') " search backwards from regular file + let nl = search('^'.indentm1.'\%('.s:treedepthstring.'\)\@!','bWe',stopline) " search backwards " call Decho("regfile srch back: ".nl,'~'.expand("<slnum>")) - elseif a:dir == ']' && nxtline != '' - NetrwKeepj norm! $ - let nl = search('^'.indentm1.'[^'.s:treedepthstring.']','We') " search forwards from regular file -" call Decho("regfile srch fwd: ".nl,'~'.expand("<slnum>")) - endif - - elseif a:dir == '[' && prvline != '' - NetrwKeepj norm! 0 - let curline= line(".") - let nl = search('^'.curindent.'[^'.s:treedepthstring.']','bWe') " search backwards From directory, same indentation -" call Decho("dir srch back ind: ".nl,'~'.expand("<slnum>")) - if nl != 0 - if line(".") == curline-1 - let nl= search('^'.indentm1.'[^'.s:treedepthstring.']','bWe') " search backwards from directory, indentation - 1 -" call Decho("dir srch back ind-1: ".nl,'~'.expand("<slnum>")) - endif - endif - - elseif a:dir == ']' && nxtline != '' - NetrwKeepj norm! $ - let curline = line(".") - let nl = search('^'.curindent.'[^'.s:treedepthstring.']','We') " search forwards from directory, same indentation -" call Decho("dir srch fwd ind: ".nl,'~'.expand("<slnum>")) - if nl != 0 - if line(".") == curline+1 - let nl= search('^'.indentm1.'[^'.s:treedepthstring.']','We') " search forwards from directory, indentation - 1 -" call Decho("dir srch fwd ind-1: ".nl,'~'.expand("<slnum>")) + elseif a:dir == '[]' && nxtline != '' + NetrwKeepj norm! 0 +" call Decho('srchpat<'.'^\%('.curindent.'\)\@!'.'>') + let nl = search('^\%('.curindent.'\)\@!','We') " search forwards + if nl != 0 + NetrwKeepj norm! k + else + NetrwKeepj norm! G endif +" call Decho("regfile srch fwd: ".nl,'~'.expand("<slnum>")) endif - endif " call Dret("s:TreeListMove") diff --git a/runtime/autoload/provider/pythonx.vim b/runtime/autoload/provider/pythonx.vim index 05815a4896..c3256e8308 100644 --- a/runtime/autoload/provider/pythonx.vim +++ b/runtime/autoload/provider/pythonx.vim @@ -18,9 +18,9 @@ function! provider#pythonx#Require(host) abort endfor try - let channel_id = rpcstart((ver == '2' ? + let channel_id = rpcstart((ver ==# '2' ? \ provider#python#Prog() : provider#python3#Prog()), args) - if rpcrequest(channel_id, 'poll') == 'ok' + if rpcrequest(channel_id, 'poll') ==# 'ok' return channel_id endif catch @@ -70,7 +70,7 @@ endfunction function! s:check_interpreter(prog, major_ver, skip) abort let prog_path = exepath(a:prog) - if prog_path == '' + if prog_path ==# '' return [0, a:prog . ' not found in search path or not executable.'] endif @@ -83,8 +83,8 @@ function! s:check_interpreter(prog, major_ver, skip) abort " Try to load neovim module, and output Python version. " Return codes: " 0 Neovim module can be loaded. - " 1 Something else went wrong. " 2 Neovim module cannot be loaded. + " Otherwise something else went wrong (e.g. 1 or 127). let prog_ver = system([ a:prog , '-c' , \ 'import sys; ' . \ 'sys.path.remove(""); ' . @@ -93,7 +93,8 @@ function! s:check_interpreter(prog, major_ver, skip) abort \ 'exit(2*int(pkgutil.get_loader("neovim") is None))' \ ]) - if prog_ver + if v:shell_error == 2 || v:shell_error == 0 + " Check version only for expected return codes. if prog_ver !~ '^' . a:major_ver return [0, prog_path . ' is Python ' . prog_ver . ' and cannot provide Python ' \ . a:major_ver . '.'] @@ -103,12 +104,16 @@ function! s:check_interpreter(prog, major_ver, skip) abort endif endif - if v:shell_error == 1 - return [0, 'Checking ' . prog_path . ' caused an unknown error. ' - \ . 'Please report this at github.com/neovim/neovim.'] - elseif v:shell_error == 2 - return [0, prog_path . ' does have not have the neovim module installed. ' + if v:shell_error == 2 + return [0, prog_path . ' does not have the neovim module installed. ' \ . 'See ":help nvim-python".'] + elseif v:shell_error == 127 + " This can happen with pyenv's shims. + return [0, prog_path . ' does not exist: ' . prog_ver] + elseif v:shell_error + return [0, 'Checking ' . prog_path . ' caused an unknown error. ' + \ . '(' . v:shell_error . ', output: ' . prog_ver . ')' + \ . ' Please report this at github.com/neovim/neovim.'] endif return [1, ''] diff --git a/runtime/autoload/remote/host.vim b/runtime/autoload/remote/host.vim index 8faeaed2ea..a63c6a923b 100644 --- a/runtime/autoload/remote/host.vim +++ b/runtime/autoload/remote/host.vim @@ -140,6 +140,7 @@ function! s:RegistrationCommands(host) abort call remote#host#RegisterClone(host_id, a:host) let pattern = s:plugin_patterns[a:host] let paths = globpath(&rtp, 'rplugin/'.a:host.'/'.pattern, 0, 1) + let paths = map(paths, 'tr(v:val,"\\","/")') " Normalize slashes #4795 if empty(paths) return [] endif diff --git a/runtime/autoload/sqlcomplete.vim b/runtime/autoload/sqlcomplete.vim index 4a8863e15f..e80729add4 100644 --- a/runtime/autoload/sqlcomplete.vim +++ b/runtime/autoload/sqlcomplete.vim @@ -1,8 +1,8 @@ " Vim OMNI completion script for SQL " Language: SQL " Maintainer: David Fishburn <dfishburn dot vim at gmail dot com> -" Version: 15.0 -" Last Change: 2013 May 13 +" Version: 16.0 +" Last Change: 2015 Dec 29 " Homepage: http://www.vim.org/scripts/script.php?script_id=1572 " Usage: For detailed help " ":help sql.txt" @@ -16,6 +16,12 @@ " look backwards to a FROM clause and find the first table " and complete it. " +" Version 16.0 (Dec 2015) +" - NF: If reseting the cache and table, procedure or view completion +" had been used via dbext, have dbext delete or recreate the +" dictionary so that new objects are picked up for the +" next completion. +" " Version 15.0 (May 2013) " - NF: Changed the SQL precached syntax items, omni_sql_precache_syntax_groups, " to use regular expressions to pick up extended syntax group names. @@ -103,7 +109,7 @@ endif if exists('g:loaded_sql_completion') finish endif -let g:loaded_sql_completion = 150 +let g:loaded_sql_completion = 160 let s:keepcpo= &cpo set cpo&vim @@ -459,6 +465,29 @@ function! sqlcomplete#Complete(findstart, base) let s:tbl_cols = [] let s:syn_list = [] let s:syn_value = [] + + if s:sql_file_table != "" + if g:loaded_dbext >= 2300 + call DB_DictionaryDelete("table") + else + DBCompleteTables! + endif + endif + if s:sql_file_procedure != "" + if g:loaded_dbext >= 2300 + call DB_DictionaryDelete("procedure") + else + DBCompleteProcedures! + endif + endif + if s:sql_file_view != "" + if g:loaded_dbext >= 2300 + call DB_DictionaryDelete("view") + else + DBCompleteViews! + endif + endif + let s:sql_file_table = "" let s:sql_file_procedure = "" let s:sql_file_view = "" diff --git a/runtime/doc/Makefile b/runtime/doc/Makefile index 7423e63673..3d10d0ea98 100644 --- a/runtime/doc/Makefile +++ b/runtime/doc/Makefile @@ -6,32 +6,14 @@ AWK = awk -# Set to $(VIMTARGET) when executed from src/Makefile. -VIMEXE = vim - DOCS = $(wildcard *.txt) HTMLS = $(DOCS:.txt=.html) .SUFFIXES: .SUFFIXES: .c .o .txt .html -all: tags html - -# Use Vim to generate the tags file. Can only be used when Vim has been -# compiled and installed. Supports multiple languages. -vimtags: $(DOCS) - $(VIMEXE) -u NONE -es -c "helptags ++t ." -c quit - -# Use "doctags" to generate the tags file. Only works for English! -tags: doctags $(DOCS) - ./doctags $(DOCS) | LANG=C LC_ALL=C sort >tags - uniq -d -2 tags - -doctags: doctags.c - $(CC) doctags.c -o doctags - # Awk version of .txt to .html conversion. -html: noerrors tags $(HTMLS) +html: noerrors $(HTMLS) @if test -f errors.log; then cat errors.log; fi noerrors: @@ -54,5 +36,5 @@ tags.ref tags.html: tags $(AWK) -f maketags.awk tags >tags.html clean: - -rm -f doctags *.html tags.ref $(HTMLS) errors.log + -rm -f *.html tags.ref $(HTMLS) errors.log diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index c8eb0705f6..c3f1b69da7 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1,4 +1,4 @@ -*change.txt* For Vim version 7.4. Last change: 2016 Jan 02 +*change.txt* For Vim version 7.4. Last change: 2016 Feb 10 VIM REFERENCE MANUAL by Bram Moolenaar @@ -97,10 +97,10 @@ These commands delete text. You can repeat them with the `.` command An exception for the d{motion} command: If the motion is not linewise, the start and end of the motion are not in the same line, and there are only -blanks before the start and after the end of the motion, the delete becomes -linewise. This means that the delete also removes the line of blanks that you -might expect to remain. Use the |o_v| operator to force the motion to be -characterwise. +blanks before the start and there are no non-blanks after the end of the +motion, the delete becomes linewise. This means that the delete also removes +the line of blanks that you might expect to remain. Use the |o_v| operator to +force the motion to be characterwise. Trying to delete an empty region of text (e.g., "d0" in the first column) is an error when 'cpoptions' includes the 'E' flag. @@ -396,6 +396,11 @@ CTRL-X Subtract [count] from the number or alphabetic {Visual}CTRL-X Subtract [count] from the number or alphabetic character in the highlighted text. {not in Vi} + On MS-Windows, this is mapped to cut Visual text + |dos-standard-mappings|. If you want to disable the + mapping, use this: > + silent! vunmap <C-X> +< *v_g_CTRL-X* {Visual}g CTRL-X Subtract [count] from the number or alphabetic character in the highlighted text. If several lines diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt index 668790358b..8881845fdd 100644 --- a/runtime/doc/develop.txt +++ b/runtime/doc/develop.txt @@ -1,4 +1,4 @@ -*develop.txt* For Vim version 7.4. Last change: 2014 Mar 27 +*develop.txt* For Vim version 7.4. Last change: 2016 Jan 31 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/doctags.c b/runtime/doc/doctags.c deleted file mode 100644 index 9213dd9c1e..0000000000 --- a/runtime/doc/doctags.c +++ /dev/null @@ -1,83 +0,0 @@ -/* vim:set ts=4 sw=4: - * this program makes a tags file for vim_ref.txt - * - * Usage: doctags vim_ref.txt vim_win.txt ... >tags - * - * A tag in this context is an identifier between stars, e.g. *c_files* - */ - -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <stdlib.h> - -#define LINELEN 200 - - int -main(argc, argv) - int argc; - char **argv; -{ - char line[LINELEN]; - char *p1, *p2; - char *p; - FILE *fd; - - if (argc <= 1) - { - fprintf(stderr, "Usage: doctags docfile ... >tags\n"); - exit(1); - } - printf("help-tags\ttags\t1\n"); - while (--argc > 0) - { - ++argv; - fd = fopen(argv[0], "r"); - if (fd == NULL) - { - fprintf(stderr, "Unable to open %s for reading\n", argv[0]); - continue; - } - while (fgets(line, LINELEN, fd) != NULL) - { - p1 = strchr(line, '*'); /* find first '*' */ - while (p1 != NULL) - { - p2 = strchr(p1 + 1, '*'); /* find second '*' */ - if (p2 != NULL && p2 > p1 + 1) /* skip "*" and "**" */ - { - for (p = p1 + 1; p < p2; ++p) - if (*p == ' ' || *p == '\t' || *p == '|') - break; - /* - * Only accept a *tag* when it consists of valid - * characters, there is white space before it and is - * followed by a white character or end-of-line. - */ - if (p == p2 - && (p1 == line || p1[-1] == ' ' || p1[-1] == '\t') - && (strchr(" \t\n\r", p[1]) != NULL - || p[1] == '\0')) - { - *p2 = '\0'; - ++p1; - printf("%s\t%s\t/*", p1, argv[0]); - while (*p1) - { - /* insert backslash before '\\' and '/' */ - if (*p1 == '\\' || *p1 == '/') - putchar('\\'); - putchar(*p1); - ++p1; - } - printf("*\n"); - p2 = strchr(p2 + 1, '*'); /* find next '*' */ - } - } - p1 = p2; - } - } - fclose(fd); - } - return 0; -} diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index c51286a350..69f834b04d 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -1,4 +1,4 @@ -*editing.txt* For Vim version 7.4. Last change: 2016 Jan 03 +*editing.txt* For Vim version 7.4. Last change: 2016 Feb 16 VIM REFERENCE MANUAL by Bram Moolenaar @@ -368,16 +368,21 @@ Note there are some commands where this works slightly differently, see Example: > :n **/*.txt Finds files: - ttt.txt - subdir/ttt.txt - a/b/c/d/ttt.txt -When non-wildcard characters are used these are only matched in the first -directory. Example: > - :n /usr/inc**/*.h + aaa.txt ~ + subdir/bbb.txt ~ + a/b/c/d/ccc.txt ~ +When non-wildcard characters are used right before or after "**" these are +only matched in the top directory. They are not used for directories further +down in the tree. For example: > + :n /usr/inc**/types.h Finds files: - /usr/include/types.h - /usr/include/sys/types.h - /usr/inc_old/types.h + /usr/include/types.h ~ + /usr/include/sys/types.h ~ + /usr/inc/old/types.h ~ +Note that the path with "/sys" is included because it does not need to match +"/inc". Thus it's like matching "/usr/inc*/*/*...", not +"/usr/inc*/inc*/inc*". + *backtick-expansion* *`-expansion* On Unix and a few other systems you can also use backticks for the file name argument, for example: > @@ -596,6 +601,7 @@ list of the current window. :0argadd x x a b c :1argadd x a x b c :$argadd x a b c x + And after the last one: :+2argadd y a b c x y There is no check for duplicates, it is possible to add a file to the argument list twice. @@ -946,7 +952,7 @@ the newly written file (it might be there but contain bogus data). In that case try recovery, because the swap file is synced to disk and might still be there. |:recover| -The directories given with the 'backupdir' option is used to put the backup +The directories given with the 'backupdir' option are used to put the backup file in. (default: same directory as the written file). Whether the backup is a new file, which is a copy of the original file, or the diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 87b90900cb..219327fd77 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 7.4. Last change: 2016 Jan 16 +*eval.txt* For Vim version 7.4. Last change: 2016 Feb 19 VIM REFERENCE MANUAL by Bram Moolenaar @@ -100,6 +100,9 @@ When mixing Number and Float the Number is converted to Float. Otherwise there is no automatic conversion of Float. You can use str2float() for String to Float, printf() for Float to String and float2nr() for Float to Number. + *E891* *E892* *E893* *E894* +When expecting a Float a Number can also be used, but nothing else. + *E706* *sticky-type-checking* You will get an error if you try to change the type of a variable. You need to |:unlet| it first to avoid this error. String and Number are considered @@ -870,7 +873,7 @@ cursor: > :let c = getline(".")[col(".") - 1] If the length of the String is less than the index, the result is an empty -String. A negative index always results in an empty string (reason: backwards +String. A negative index always results in an empty string (reason: backward compatibility). Use [-1:] to get the last byte. If expr8 is a |List| then it results the item at index expr1. See |list-index| @@ -1788,7 +1791,8 @@ arglistid([{winnr} [, {tabnr}]]) Number argument list id argv({nr}) String {nr} entry of the argument list argv() List the argument list assert_equal({exp}, {act} [, {msg}]) none assert {exp} equals {act} -assert_exception({error} [, {msg}]) none assert {error} is in v:exception +assert_exception( {error} [, {msg}]) none assert {error} is in v:exception +assert_fails( {cmd} [, {error}]) none assert {cmd} fails assert_false({actual} [, {msg}]) none assert {actual} is false assert_true({actual} [, {msg}]) none assert {actual} is true asin({expr}) Float arc sine of {expr} @@ -1920,7 +1924,7 @@ has_key({dict}, {key}) Number TRUE if {dict} has entry {key} haslocaldir() Number TRUE if current window executed |:lcd| hasmapto({what} [, {mode} [, {abbr}]]) Number TRUE if mapping to {what} exists -histadd({history},{item}) String add an item to a history +histadd({history}, {item}) String add an item to a history histdel({history} [, {item}]) String remove an item from a history histget({history} [, {index}]) String get the item {index} from a history histnr({history}) Number highest index of a history @@ -2051,6 +2055,7 @@ serverlist() String get a list of available servers setbufvar({expr}, {varname}, {val}) set {varname} in buffer {expr} to {val} setcharsearch({dict}) Dict set character search from {dict} setcmdpos({pos}) Number set cursor position in command-line +setfperm({fname}, {mode} Number set {fname} file permissions to {mode} setline({lnum}, {line}) Number set line {lnum} to {line} setloclist({nr}, {list}[, {action}[, {title}]]) Number modify location list using {list} @@ -2113,9 +2118,12 @@ tabpagewinnr({tabarg}[, {arg}]) Number number of current window in tab page taglist({expr}) List list of tags matching {expr} tagfiles() List tags files used -tempname() String name for a temporary file tan({expr}) Float tangent of {expr} tanh({expr}) Float hyperbolic tangent of {expr} +tempname() String name for a temporary file +timer_start({time}, {callback} [, {options}]) + Number create a timer +timer_stop({timer}) none stop a timer tolower({expr}) String the String {expr} switched to lowercase toupper({expr}) String the String {expr} switched to uppercase tr({src}, {fromstr}, {tostr}) String translate chars of {src} in {fromstr} @@ -2207,7 +2215,7 @@ argidx() The result is the current index in the argument list. 0 is the first file. argc() - 1 is the last one. See |arglist|. *arglistid()* -arglistid([{winnr}, [ {tabnr} ]]) +arglistid([{winnr} [, {tabnr}]]) Return the argument list ID. This is a number which identifies the argument list being used. Zero is used for the global argument list. See |arglist|. @@ -2259,6 +2267,11 @@ assert_exception({error} [, {msg}]) *assert_exception()* call assert_exception('E492:') endtry +assert_fails({cmd} [, {error}]) *assert_fails()* + Run {cmd} and add an error message to |v:errors| if it does + NOT produce an error. + When {error} is given it must match |v:errmsg|. + assert_false({actual} [, {msg}]) *assert_false()* When {actual} is not false an error message is added to |v:errors|, like with |assert_equal()|. @@ -3161,6 +3174,11 @@ feedkeys({string} [, {mode}]) *feedkeys()* if coming from a mapping. This matters for undo, opening folds, etc. 'i' Insert the string instead of appending (see above). + 'x' Execute commands until typeahead is empty. This is + similar to using ":normal!". You can call feedkeys() + several times without 'x' and then one time with 'x' + (possibly with an empty {string}) to execute all the + typeahead. Return value is always 0. filereadable({file}) *filereadable()* @@ -3572,7 +3590,7 @@ getcmdwintype() *getcmdwintype()* *getcurpos()* getcurpos() Get the position of the cursor. This is like getpos('.'), but includes an extra item in the list: - [bufnum, lnum, col, off, curswant] + [bufnum, lnum, col, off, curswant] ~ The "curswant" number is the preferred column when moving the cursor vertically. This can be used to save and restore the cursor position: > @@ -3628,6 +3646,8 @@ getfperm({fname}) *getfperm()* < This will hopefully (from a security point of view) display the string "rw-r--r--" or even "rw-------". + For setting permissions use |setfperm()|. + getftime({fname}) *getftime()* The result is a Number, which is the last modification time of the given file {fname}. The value is measured as seconds @@ -3653,7 +3673,8 @@ getftype({fname}) *getftype()* getftype("/home") < Note that a type such as "link" will only be returned on systems that support it. On some systems only "dir" and - "file" are returned. + "file" are returned. On MS-Windows a symbolic link to a + directory returns "dir" instead of "link". *getline()* getline({lnum} [, {end}]) @@ -4734,8 +4755,8 @@ matchadd({group}, {pattern}[, {priority}[, {id} [, {dict}]]]) respectively. If the {id} argument is not specified or -1, |matchadd()| automatically chooses a free ID. - The optional {dict} argmument allows for further custom - values. Currently this is used to specify a match specifc + The optional {dict} argument allows for further custom + values. Currently this is used to specify a match specific conceal character that will be shown for |hl-Conceal| highlighted matches. The dict can have the following members: @@ -5588,7 +5609,7 @@ search({pattern} [, {flags} [, {stopline} [, {timeout}]]]) *search()* 'ignorecase', 'smartcase' and 'magic' are used. - When the 'z' flag is not given seaching always starts in + When the 'z' flag is not given, searching always starts in column zero and then matches before the cursor are skipped. When the 'c' flag is present in 'cpo' the next search starts after the match. Without the 'c' flag the next search starts @@ -5866,6 +5887,23 @@ setcmdpos({pos}) *setcmdpos()* Returns 0 when successful, 1 when not editing the command line. +setfperm({fname}, {mode}) *setfperm()* *chmod* + Set the file permissions for {fname} to {mode}. + {mode} must be a string with 9 characters. It is of the form + "rwxrwxrwx", where each group of "rwx" flags represent, in + turn, the permissions of the owner of the file, the group the + file belongs to, and other users. A '-' character means the + permission is off, any other character means on. Multi-byte + characters are not supported. + + For example "rw-r-----" means read-write for the user, + readable by the group, not accessible by others. "xx-x-----" + would do the same thing. + + Returns non-zero for success, zero for failure. + + To read permissions see |getfperm()|. + setline({lnum}, {text}) *setline()* Set line {lnum} of the current buffer to {text}. To insert lines use |append()|. @@ -5997,7 +6035,7 @@ setqflist({list} [, {action}[, {title}]]) *setqflist()* *setreg()* -setreg({regname}, {value} [,{options}]) +setreg({regname}, {value} [, {options}]) Set the register {regname} to {value}. {value} may be any value returned by |getreg()|, including a |List|. @@ -6178,6 +6216,9 @@ sort({list} [, {func} [, {dict}]]) *sort()* *E702* sorted numerical. This is like 'n' but a string containing digits will be used as the number they represent. + When {func} is given and it is 'f' then all items will be + sorted numerical. All values must be a Number or a Float. + When {func} is a |Funcref| or a function name, this function is called to compare items. The function is invoked with two items as argument and must return zero if they are equal, 1 or @@ -6820,6 +6861,37 @@ tanh({expr}) *tanh()* < -0.761594 + *timer_start()* +timer_start({time}, {callback} [, {options}]) + Create a timer and return the timer ID. + + {time} is the waiting time in milliseconds. This is the + minimum time before invoking the callback. When the system is + busy or Vim is not waiting for input the time will be longer. + + {callback} is the function to call. It can be the name of a + function or a Funcref. It is called with one argument, which + is the timer ID. The callback is only invoked when Vim is + waiting for input. + + {options} is a dictionary. Supported entries: + "repeat" Number of times to repeat calling the + callback. -1 means forever. + + Example: > + func MyHandler(timer) + echo 'Handler called' + endfunc + let timer = timer_start(500, 'MyHandler', + \ {'repeat': 3}) +< This will invoke MyHandler() three times at 500 msec + intervals. + {only available when compiled with the |+timers| feature} + +timer_stop({timer}) *timer_stop()* + Stop a timer. {timer} is an ID returned by timer_start(). + The timer callback will no longer be invoked. + tolower({expr}) *tolower()* The result is a copy of the String given, with all uppercase characters turned into lowercase (just like applying |gu| to @@ -7227,7 +7299,7 @@ dialog_gui Compiled with GUI dialog support. digraphs Compiled with support for digraphs. eval Compiled with expression evaluation support. Always true, of course! -ex_extra Compiled with extra Ex commands |+ex_extra|. +ex_extra |+ex_extra|, always true now extra_search Compiled with support for |'incsearch'| and |'hlsearch'| farsi Compiled with Farsi support |farsi|. @@ -7303,6 +7375,7 @@ termresponse Compiled with support for |t_RV| and |v:termresponse|. textobjects Compiled with support for |text-objects|. tgetent Compiled with tgetent support, able to use a termcap or terminfo file. +timers Compiled with |timer_start()| support. title Compiled with window title support |'title'|. toolbar Compiled with support for |gui-toolbar|. unix Unix version of Vim. @@ -7933,7 +8006,7 @@ This does NOT work: > From Vim version 4.5 until 5.0, every Ex command in between the ":if" and ":endif" is ignored. These two commands were just to allow for future expansions in a - backwards compatible way. Nesting was allowed. Note + backward compatible way. Nesting was allowed. Note that any ":else" or ":elseif" was ignored, the "else" part was not executed either. diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt index 19bcb35da8..342c475f9b 100644 --- a/runtime/doc/help.txt +++ b/runtime/doc/help.txt @@ -1,4 +1,4 @@ -*help.txt* For Vim version 7.4. Last change: 2015 Apr 15 +*help.txt* For Vim version 7.4. Last change: 2016 Jan 10 VIM - main help file k @@ -9,14 +9,14 @@ Close this window: Use ":q<Enter>". Jump to a subject: Position the cursor on a tag (e.g. |bars|) and hit CTRL-]. With the mouse: Double-click the left mouse button on a tag, e.g. |bars|. - Jump back: Type CTRL-T or CTRL-O (repeat to go further back). + Jump back: Type CTRL-T or CTRL-O. Repeat to go further back. Get specific help: It is possible to go directly to whatever you want help on, by giving an argument to the |:help| command. - It is possible to further specify the context: - *help-context* + Prepend something to specify the context: *help-context* + WHAT PREPEND EXAMPLE ~ - Normal mode command (nothing) :help x + Normal mode command :help x Visual mode command v_ :help v_u Insert mode command i_ :help i_<Esc> Command-line command : :help :quit @@ -24,6 +24,8 @@ Get specific help: It is possible to go directly to whatever you want help Vim command argument - :help -r Option ' :help 'textwidth' Regular expression / :help /[ + See |help-summary| for more contexts and an explanation. + Search for help: Type ":help word", then hit CTRL-D to see matching help entries for "word". Or use ":helpgrep word". |:helpgrep| diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index e6c1ccc0cf..e75031ccef 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -1,4 +1,4 @@ -*index.txt* For Vim version 7.4. Last change: 2016 Jan 03 +*index.txt* For Vim version 7.4. Last change: 2016 Jan 19 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1171,7 +1171,7 @@ tag command action ~ |:cpfile| :cpf[ile] go to last error in previous file |:cquit| :cq[uit] quit Vim with an error code |:crewind| :cr[ewind] go to the specified error, default first one -|:cscope| :cs[cope] execute cscope command +|:cscope| :cs[cope] execute cscope command |:cstag| :cst[ag] use cscope to jump to a tag |:cunmap| :cu[nmap] like ":unmap" but for Command-line mode |:cunabbrev| :cuna[bbrev] like ":unabbrev" but for Command-line mode @@ -1290,7 +1290,7 @@ tag command action ~ |:lcd| :lc[d] change directory locally |:lchdir| :lch[dir] change directory locally |:lclose| :lcl[ose] close location window -|:lcscope| :lcs[cope] like ":cscope" but uses location list +|:lcscope| :lcs[cope] like ":cscope" but uses location list |:ldo| :ld[o] execute command in valid location list entries |:lfdo| :lfd[o] execute command in each file in location list |:left| :le[ft] left align lines @@ -1341,7 +1341,7 @@ tag command action ~ |:marks| :marks list all marks |:match| :mat[ch] define a match to highlight |:menu| :me[nu] enter a new menu item -|:menutranslate| :menut[ranslate] add a menu translation item +|:menutranslate| :menut[ranslate] add a menu translation item |:messages| :mes[sages] view previously displayed messages |:mkexrc| :mk[exrc] write current mappings and settings to a file |:mksession| :mks[ession] write session info to a file @@ -1494,7 +1494,7 @@ tag command action ~ |:stop| :st[op] suspend the editor or escape to a shell |:stag| :sta[g] split window and jump to a tag |:startinsert| :star[tinsert] start Insert mode -|:startgreplace| :startg[replace] start Virtual Replace mode +|:startgreplace| :startg[replace] start Virtual Replace mode |:startreplace| :startr[eplace] start Replace mode |:stopinsert| :stopi[nsert] stop Insert mode |:stjump| :stj[ump] do ":tjump" and split window @@ -1515,14 +1515,14 @@ tag command action ~ |:tabdo| :tabdo execute command in each tab page |:tabedit| :tabe[dit] edit a file in a new tab page |:tabfind| :tabf[ind] find file in 'path', edit it in a new tab page -|:tabfirst| :tabfir[st] got to first tab page -|:tablast| :tabl[ast] got to last tab page +|:tabfirst| :tabfir[st] go to first tab page +|:tablast| :tabl[ast] go to last tab page |:tabmove| :tabm[ove] move tab page to other position |:tabnew| :tabnew edit a file in a new tab page |:tabnext| :tabn[ext] go to next tab page |:tabonly| :tabo[nly] close all tab pages except the current one |:tabprevious| :tabp[revious] go to previous tab page -|:tabrewind| :tabr[ewind] got to first tab page +|:tabrewind| :tabr[ewind] go to first tab page |:tabs| :tabs list the tab pages and what they contain |:tab| :tab create new tab when opening new window |:tag| :ta[g] jump to tag diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index f931dfa341..818d6cf64c 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -1,4 +1,4 @@ -*insert.txt* For Vim version 7.4. Last change: 2015 Sep 15 +*insert.txt* For Vim version 7.4. Last change: 2016 Jan 31 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 464c700a4d..31c3198f72 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1,4 +1,4 @@ -*map.txt* For Vim version 7.4. Last change: 2014 Dec 08 +*map.txt* For Vim version 7.4. Last change: 2016 Jan 10 VIM REFERENCE MANUAL by Bram Moolenaar @@ -481,7 +481,7 @@ internal code is written to the script file. 1.6 SPECIAL CHARACTERS *:map-special-chars* - *map_backslash* + *map_backslash* *map-backslash* Note that only CTRL-V is mentioned here as a special character for mappings and abbreviations. When 'cpoptions' does not contain 'B', a backslash can also be used like CTRL-V. The <> notation can be fully used then |<>|. But @@ -492,21 +492,21 @@ To map a backslash, or use a backslash literally in the {rhs}, the special sequence "<Bslash>" can be used. This avoids the need to double backslashes when using nested mappings. - *map_CTRL-C* + *map_CTRL-C* *map-CTRL-C* Using CTRL-C in the {lhs} is possible, but it will only work when Vim is waiting for a key, not when Vim is busy with something. When Vim is busy CTRL-C interrupts/breaks the command. When using the GUI version on MS-Windows CTRL-C can be mapped to allow a Copy command to the clipboard. Use CTRL-Break to interrupt Vim. - *map_space_in_lhs* + *map_space_in_lhs* *map-space_in_lhs* To include a space in {lhs} precede it with a CTRL-V (type two CTRL-Vs for each space). - *map_space_in_rhs* + *map_space_in_rhs* *map-space_in_rhs* If you want a {rhs} that starts with a space, use "<Space>". To be fully Vi compatible (but unreadable) don't use the |<>| notation, precede {rhs} with a single CTRL-V (you have to type CTRL-V two times). - *map_empty_rhs* + *map_empty_rhs* *map-empty-rhs* You can create an empty {rhs} by typing nothing after a single CTRL-V (you have to type CTRL-V two times). Unfortunately, you cannot do this in a vimrc file. @@ -581,7 +581,7 @@ Upper and lowercase differences are ignored. It is not possible to put a comment after these commands, because the '"' character is considered to be part of the {lhs} or {rhs}. - *map_bar* + *map_bar* *map-bar* Since the '|' character is used to separate a map command from the next command, you will have to do something special to include a '|' in {rhs}. There are three methods: @@ -599,7 +599,7 @@ When 'b' is present in 'cpoptions', "\|" will be recognized as a mapping ending in a '\' and then another command. This is Vi compatible, but illogical when compared to other commands. - *map_return* + *map_return* *map-return* When you have a mapping that contains an Ex command, you need to put a line terminator after it to have it executed. The use of <CR> is recommended for this (see |<>|). Example: > diff --git a/runtime/doc/mlang.txt b/runtime/doc/mlang.txt index 5f4642274c..a2be3cfd49 100644 --- a/runtime/doc/mlang.txt +++ b/runtime/doc/mlang.txt @@ -1,4 +1,4 @@ -*mlang.txt* For Vim version 7.4. Last change: 2012 Jan 15 +*mlang.txt* For Vim version 7.4. Last change: 2016 Jan 16 VIM REFERENCE MANUAL by Bram Moolenaar @@ -94,13 +94,15 @@ If you used the self-installing .exe file, message translations should work already. Otherwise get the libintl.dll file if you don't have it yet: http://sourceforge.net/projects/gettext +Or: + https://mlocati.github.io/gettext-iconv-windows/ This also contains tools xgettext, msgformat and others. libintl.dll should be placed in same directory with (g)vim.exe, or some -place where PATH environment value describe. Message files (vim.mo) -have to be placed in "$VIMRUNTIME/lang/xx/LC_MESSAGES", where "xx" is the -abbreviation of the language (mostly two letters). +place where PATH environment value describe. Vim also finds libintl-8.dll. +Message files (vim.mo) have to be placed in "$VIMRUNTIME/lang/xx/LC_MESSAGES", +where "xx" is the abbreviation of the language (mostly two letters). If you write your own translations you need to generate the .po file and convert it to a .mo file. You need to get the source distribution and read diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 83ae96a651..105be1cd77 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 7.4. Last change: 2016 Jan 03 +*options.txt* For Vim version 7.4. Last change: 2016 Feb 20 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1602,7 +1602,7 @@ A jump table for the options with a short description can be found at |Q_op|. line, the remaining space is filled in the normal manner. See 'preserveindent'. - *'cpoptions'* *'cpo'* + *'cpoptions'* *'cpo'* *cpo* 'cpoptions' 'cpo' string (Vim default: "aABceFs", Vi default: all flags) global @@ -2515,17 +2515,17 @@ A jump table for the options with a short description can be found at |Q_op|. item default Used for ~ stl:c ' ' or '^' statusline of the current window - stlnc:c ' ' or '-' statusline of the non-current windows + stlnc:c ' ' or '=' statusline of the non-current windows vert:c '|' vertical separators |:vsplit| fold:c '-' filling 'foldtext' diff:c '-' deleted lines of the 'diff' option Any one that is omitted will fall back to the default. For "stl" and - "stlnc" the space will be used when there is highlighting, '^' or '-' + "stlnc" the space will be used when there is highlighting, '^' or '=' otherwise. Example: > - :set fillchars=stl:^,stlnc:-,vert:\|,fold:-,diff:- + :set fillchars=stl:^,stlnc:=,vert:\|,fold:-,diff:- < This is similar to the default, except that these characters will also be used when there is highlighting. @@ -3696,6 +3696,8 @@ A jump table for the options with a short description can be found at |Q_op|. '*', '"' and '|' (so that CTRL-] on a command finds the help for that command). When the 'lisp' option is on the '-' character is always included. + This option also influences syntax highlighting, unless the syntax + uses |:syn-iskeyword|. *'isprint'* *'isp'* 'isprint' 'isp' string (default: "@,161-255") @@ -5955,7 +5957,7 @@ A jump table for the options with a short description can be found at |Q_op|. The option consists of printf style '%' items interspersed with normal text. Each status line item is of the form: %-0{minwid}.{maxwid}{item} - All fields except the {item} is optional. A single percent sign can + All fields except the {item} are optional. A single percent sign can be given as "%%". Up to 80 items can be specified. *E541* When the option starts with "%!" then it is used as an expression, @@ -6461,6 +6463,7 @@ A jump table for the options with a short description can be found at |Q_op|. non-keyword characters (white space is preferred). Maximum line length is 510 bytes. To obtain a file to be used here, check out this ftp site: + [Sorry this link doesn't work anymore, do you know the right one?] ftp://ftp.ox.ac.uk/pub/wordlists/ First get the README file. To include a comma in a file name precede it with a backslash. Spaces after a comma are ignored, otherwise spaces are included in the file diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt index 1705010ff2..2c240fe41f 100644 --- a/runtime/doc/pi_netrw.txt +++ b/runtime/doc/pi_netrw.txt @@ -1,4 +1,4 @@ -*pi_netrw.txt* For Vim version 7.4. Last change: 2015 Oct 31 +*pi_netrw.txt* For Vim version 7.4. Last change: 2016 Feb 16 ------------------------------------------------ NETRW REFERENCE MANUAL by Charles E. Campbell @@ -6,7 +6,7 @@ Author: Charles E. Campbell <NdrOchip@ScampbellPfamily.AbizM> (remove NOSPAM from Campbell's email first) -Copyright: Copyright (C) 1999-2015 Charles E Campbell *netrw-copyright* +Copyright: Copyright (C) 2016 Charles E Campbell *netrw-copyright* The VIM LICENSE applies to the files in this package, including netrw.vim, pi_netrw.txt, netrwFileHandlers.vim, netrwSettings.vim, and syntax/netrw.vim. Like anything else that's free, netrw.vim and its @@ -48,9 +48,10 @@ Copyright: Copyright (C) 1999-2015 Charles E Campbell *netrw-copyright* Introduction To Browsing............................|netrw-intro-browse| Quick Reference: Maps...............................|netrw-browse-maps| Quick Reference: Commands...........................|netrw-browse-cmds| + Banner Display......................................|netrw-I| Bookmarking A Directory.............................|netrw-mb| Browsing............................................|netrw-cr| - Squeezing the Current Tree-Listing Directory......|:netrw-s-cr| + Squeezing the Current Tree-Listing Directory........|netrw-s-cr| Browsing With A Horizontally Split Window...........|netrw-o| Browsing With A New Tab.............................|netrw-t| Browsing With A Vertically Split Window.............|netrw-v| @@ -75,11 +76,13 @@ Copyright: Copyright (C) 1999-2015 Charles E Campbell *netrw-copyright* Making The Browsing Directory The Current Directory.|netrw-c| Marking Files.......................................|netrw-mf| Unmarking Files.....................................|netrw-mF| + Marking Files By Location List......................|netrw-qL| Marking Files By QuickFix List......................|netrw-qF| Marking Files By Regular Expression.................|netrw-mr| Marked Files: Arbitrary Shell Command...............|netrw-mx| Marked Files: Arbitrary Shell Command, En Bloc......|netrw-mX| Marked Files: Arbitrary Vim Command.................|netrw-mv| + Marked Files: Argument List.........................|netrw-ma| |netrw-mA| Marked Files: Compression And Decompression.........|netrw-mz| Marked Files: Copying...............................|netrw-mc| Marked Files: Diff..................................|netrw-md| @@ -1111,6 +1114,7 @@ QUICK REFERENCE: MAPS *netrw-browse-maps* {{{2 qb List bookmarked directories and history |netrw-qb| qf Display information on file |netrw-qf| qF Mark files using a quickfix list |netrw-qF| + qL Mark files using a |location-list| |netrw-qL| r Reverse sorting order |netrw-r| R Rename the designated file(s)/directory(ies) |netrw-R| s Select sorting style: by name, time, or file size |netrw-s| @@ -1160,6 +1164,14 @@ QUICK REFERENCE: COMMANDS *netrw-explore-cmds* *netrw-browse-cmds* {{{2 :Texplore[!] [dir] Tab & Explore..........................|netrw-explore| :Vexplore[!] [dir] Vertical Split & Explore...............|netrw-explore| + +BANNER DISPLAY *netrw-I* + +One may toggle the banner display on and off by pressing "I". + +Also See: |g:netrw_banner| + + BOOKMARKING A DIRECTORY *netrw-mb* *netrw-bookmark* *netrw-bookmarks* {{{2 One may easily "bookmark" the currently browsed directory by using > @@ -1201,7 +1213,7 @@ Related Topics: |g:netrw_home| controls where .netrwbook is kept -BROWSING *netrw-cr* {{{2 +BROWSING *netrw-enter* *netrw-cr* {{{2 Browsing is simple: move the cursor onto a file or directory of interest. Hitting the <cr> (the return key) will select the file or directory. @@ -1242,11 +1254,21 @@ The price for such re-use is that when changes are made (such as new files are introduced into a directory), the listing may become out-of-date. One may always refresh directory listing buffers by pressing ctrl-L (see |netrw-ctrl-l|). - *:netrw-s-cr* - Squeezing the Current Tree-Listing Directory~ - When the tree listing style is enabled (see |netrw-i|) and one is using - gvim, then the <s-cr> mapping may be used to squeeze (close) the - directory currently containing the cursor. + + *netrw-s-cr* +Squeezing the Current Tree-Listing Directory~ + +When the tree listing style is enabled (see |netrw-i|) and one is using +gvim, then the <s-cr> mapping may be used to squeeze (close) the +directory currently containing the cursor. + +Otherwise, one may remap a key combination of one's own choice to get +this effect: > + + nmap <buffer> <silent> <nowait> YOURKEYCOMBO <Plug>NetrwTreeSqueeze +< +Put this line in $HOME/ftplugin/netrw/netrw.vim; it needs to be generated +for netrw buffers only. Related topics: |netrw-ctrl-r| |netrw-o| |netrw-p| @@ -1495,7 +1517,8 @@ One may also use visual mode (see |visual-start|) to select the text that the special handler will use. Normally gx uses expand("<cfile>") to pick up the text under the cursor; one may change what |expand()| uses via the |g:netrw_gx| variable. Alternatively, one may select the text to be used by -gx via first making a visual selection (see |visual-block|). +gx via first making a visual selection (see |visual-block|) or by changing +the |'isfname'| option (which is global, so netrw doesn't modify it). Associated setting variables: |g:netrw_gx| control how gx picks up the text under the cursor @@ -1713,8 +1736,9 @@ Also see: |g:netrw_alto| |g:netrw_altv| |g:netrw_winsize| EXPLORING WITH STARS AND PATTERNS {{{2 When Explore, Sexplore, Hexplore, or Vexplore are used with one of the -following four patterns Explore generates a list of files which satisfy -the request. > +following four patterns Explore generates a list of files which satisfy the +request for the local file system. These exploration patterns will not work +with remote file browsing. */filepat files in current directory which satisfy filepat **/filepat files in current directory or below which satisfy the @@ -2079,15 +2103,22 @@ Netrw provides several ways to mark files: :MF *.c < - * Note that :MF uses |<f-args>| to break the line - at spaces. + (Note that :MF uses |<f-args>| to break the line + at spaces) + + * Mark files using the |argument-list| (|netrw-mA|) + + * Mark files based upon a |location-list| (|netrw-qL|) * Mark files based upon the quickfix list (|netrw-qF|) + (|quickfix-error-lists|) The following netrw maps make use of marked files: |netrw-a| Hide marked files/directories |netrw-D| Delete marked files/directories + |netrw-ma| Move marked files' names to |arglist| + |netrw-mA| Move |arglist| filenames to marked file list |netrw-mb| Append marked files to bookmarks |netrw-mB| Delete marked files from bookmarks |netrw-mc| Copy marked files to target @@ -2146,8 +2177,14 @@ UNMARKING FILES *netrw-mF* {{{2 The "mF" command will unmark all files in the current buffer. One may also use mf (|netrw-mf|) on a specific, already marked, file to unmark just that file. +MARKING FILES BY LOCATION LIST *netrw-qL* {{{2 + (also see |netrw-mf|) + +One may convert |location-list|s into a marked file list using "qL". +You may then proceed with commands such as me (|netrw-me|) to edit them. -MARKING FILES BY QUICKFIX LIST *netrw-qF* {{{2 + +MARKING FILES BY QUICKFIX LIST *netrw-qF* {{{2 (also see |netrw-mf|) One may convert |quickfix-error-lists| into a marked file list using "qF". @@ -2223,6 +2260,16 @@ The command that will be run with this example: tar cf mynewtarball.tar 'file1' 'file2' ... +MARKED FILES: ARGUMENT LIST *netrw-ma* *netrw-mA* + (See |netrw-mf| and |netrw-mr| for how to mark files) + (uses the global marked-file list) + +Using ma, one moves filenames from the marked file list to the argument list. +Using mA, one moves filenames from the argument list to the marked file list. + +See Also: |netrw-qF| |argument-list| |:args| + + MARKED FILES: COMPRESSION AND DECOMPRESSION *netrw-mz* {{{2 (See |netrw-mf| and |netrw-mr| for how to mark files) (uses the local marked file list) @@ -2232,7 +2279,7 @@ If any marked files are decompressed, then "mz" will compress them using the command specified by |g:netrw_compress|; by default, that's "gzip". -For decompression, netrw provides a |Dictionary| of suffices and their +For decompression, netrw uses a |Dictionary| of suffices and their associated decompressing utilities; see |g:netrw_decompress|. Remember that one can mark multiple files by regular expression @@ -2287,7 +2334,7 @@ The command will ask for the requested pattern; one may then enter: > pattern < With /pattern/, editing will start with the first item on the |quickfix| list -that vimgrep sets up (see |:copen|, |:cnext|, |:cprevious|). The |:vimgrep| +that vimgrep sets up (see |:copen|, |:cnext|, |:cprevious|, |:cclose|). The |:vimgrep| command is in use, so without 'g' each line is added to quickfix list only once; with 'g' every match is included. @@ -2756,6 +2803,16 @@ your browsing preferences. (see also: |netrw-settings|) evaluation will be suppressed (see |'ballooneval'|) + *g:netrw_sizestyle* not defined: actual bytes (default) + ="b" : actual bytes (default) + ="h" : human-readable (ex. 5k, 4m, 3g) + uses 1000 base + ="H" : human-readable (ex. 5K, 4M, 3G) + uses 1024 base + The long listing (|netrw-i|) and query-file + maps (|netrw-qf|) will display file size + using the specified style. + *g:netrw_usetab* if this variable exists and is non-zero, then the <tab> map supporting shrinking/expanding a Lexplore or netrw window will be enabled. @@ -3024,14 +3081,14 @@ These will: Related: if you like this idea, you may also find :Lexplore (|netrw-:Lexplore|) or |g:netrw_chgwin| of interest -Also see: |g:netrw_chgwin| |netrw-P| |'previewwindow'| +Also see: |g:netrw_chgwin| |netrw-P| |'previewwindow'| |CTRL-W_z| |:pclose| PREVIOUS WINDOW *netrw-P* *netrw-prvwin* {{{2 -To edit a file or directory in the previously used (last accessed) window (see -:he |CTRL-W_p|), press a "P". If there's only one window, then the one window -will be horizontally split (by default). +To edit a file or directory under the cursor in the previously used (last +accessed) window (see :he |CTRL-W_p|), press a "P". If there's only one +window, then the one window will be horizontally split (by default). If there's more than one window, the previous window will be re-used on the selected file/directory. If the previous window's associated buffer @@ -3170,7 +3227,7 @@ only if your terminal supports differentiating <c-tab> from a plain * Else bring up a |:Lexplore| window If |g:netrw_usetab| exists or is zero, or if there is a pre-existing mapping -for <c-tab>, then the <tab> will not be mapped. One may map something other +for <c-tab>, then the <c-tab> will not be mapped. One may map something other than a <c-tab>, too: (but you'll still need to have had g:netrw_usetab set) > nmap <unique> (whatever) <Plug>NetrwShrink @@ -3637,13 +3694,13 @@ called netrw.vimrc with the following contents: > < Then run netrw as follows: > - vim -u netrw.vimrc --noplugins [some path here] + vim -u netrw.vimrc --noplugins -i NONE [some path here] < Perform whatever netrw commands you need to, and check that the problem is still present. This procedure sidesteps any issues due to personal .vimrc -settings and other plugins. If the problem does not appear, then you need -to determine what setting in your .vimrc is causing the conflict with netrw -or which plugin. +settings, .viminfo file, and other plugins. If the problem does not appear, +then you need to determine which setting in your .vimrc is causing the +conflict with netrw or which plugin(s) is/are involved. Step 3: If the problem still is present, then get a debugging trace from netrw: @@ -3698,6 +3755,37 @@ netrw: ============================================================================== 12. History *netrw-history* {{{1 + v155: Oct 29, 2015 * (Timur Fayzrakhmanov) reported that netrw's + mapping of ctrl-l was not allowing refresh of + other windows when it was done in a netrw + window. + Nov 05, 2015 * Improved s:TreeSqueezeDir() to use search() + instead of a loop + * NetrwBrowse() will return line to + w:netrw_bannercnt if cursor ended up in + banner + Nov 16, 2015 * Added a <Plug>NetrwTreeSqueeze (|netrw-s-cr|) + Nov 17, 2015 * Commented out imaps -- perhaps someone can + tell me how they're useful and should be + retained? + Nov 20, 2015 * Added |netrw-ma| and |netrw-mA| support + Nov 20, 2015 * gx (|netrw-gx|) on an url downloaded the + file in addition to simply bringing up the + url in a browser. Fixed. + Nov 23, 2015 * Added |g:netrw_sizestyle| support + Nov 27, 2015 * Inserted a lot of <c-u>s into various netrw + maps. + Jan 05, 2016 * |netrw-qL| implemented to mark files based + upon |location-list|s; similar to |netrw-qF|. + Jan 19, 2016 * using - call delete(directoryname,"d") - + instead of using g:netrw_localrmdir if + v7.4 + patch#1107 is available + Jan 28, 2016 * changed to using |winsaveview()| and + |winrestview()| + Jan 28, 2016 * s:NetrwTreePath() now does a save and + restore of view + Feb 08, 2016 * Fixed a tree-listing problem with remote + directories v154: Feb 26, 2015 * (Yuri Kanivetsky) reported a situation where a file was not treated properly as a file due to g:netrw_keepdir == 1 @@ -3858,7 +3946,7 @@ netrw: handling. * |:Lexplore| path: will be used to update a left-side netrw browsing directory. - Mar 12, 2014 * |:netrw-s-cr|: use <s-cr> to close + Mar 12, 2014 * |netrw-s-cr|: use <s-cr> to close tree directory implemented Mar 13, 2014 * (Tony Mechylynck) reported that using the browser with ftp on a directory, diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index ff4fded0d9..317226108f 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -1,4 +1,4 @@ -*quickfix.txt* For Vim version 7.4. Last change: 2015 Sep 08 +*quickfix.txt* For Vim version 7.4. Last change: 2016 Jan 21 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index 343d3e62cf..5b382f95f2 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -1,4 +1,4 @@ -*repeat.txt* For Vim version 7.4. Last change: 2016 Jan 16 +*repeat.txt* For Vim version 7.4. Last change: 2016 Feb 12 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/spell.txt b/runtime/doc/spell.txt index 752444a3bd..a767f6cbbf 100644 --- a/runtime/doc/spell.txt +++ b/runtime/doc/spell.txt @@ -1,4 +1,4 @@ -*spell.txt* For Vim version 7.4. Last change: 2014 Sep 19 +*spell.txt* For Vim version 7.4. Last change: 2016 Jan 08 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1373,6 +1373,14 @@ the item name. Case is always ignored. The Hunspell feature to use three arguments and flags is not supported. + *spell-NOCOMPOUNDSUGS* +This item indicates that using compounding to make suggestions is not a good +idea. Use this when compounding is used with very short or one-character +words. E.g. to make numbers out of digits. Without this flag creating +suggestions would spend most time trying all kind of weird compound words. + + NOCOMPOUNDSUGS ~ + *spell-SYLLABLE* The SYLLABLE item defines characters or character sequences that are used to count the number of syllables in a word. Example: diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index 46efe1996a..c9cb849164 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -1,4 +1,4 @@ -*starting.txt* For Vim version 7.4. Last change: 2015 Jan 15 +*starting.txt* For Vim version 7.4. Last change: 2016 Feb 18 VIM REFERENCE MANUAL by Bram Moolenaar @@ -10,9 +10,10 @@ Starting Vim *starting* 2. Initialization |initialization| 3. $VIM and $VIMRUNTIME |$VIM| 4. Suspending |suspend| -5. Saving settings |save-settings| -6. Views and Sessions |views-sessions| -7. The ShaDa file |shada-file| +5. Exiting |exiting| +6. Saving settings |save-settings| +7. Views and Sessions |views-sessions| +8. The ShaDa file |shada-file| ============================================================================== 1. Vim arguments *vim-arguments* @@ -696,7 +697,20 @@ can't paste it in another application (since Vim is going to sleep an attempt to get the selection would make the program hang). ============================================================================== -5. Saving settings *save-settings* +5. Exiting *exiting* + +There are several ways to exit Vim: +- Close the last window with `:quit`. Only when there are no changes. +- Close the last window with `:quit!`. Also when there are changes. +- Close all windows with `:qall`. Only when there are no changes. +- Close all windows with `:qall!`. Also when there are changes. +- Use `:cquit`. Also when there are changes. + +When using `:cquit` or when there was an error message Vim exits with exit +code 1. Errors can be avoide by using `:silent!`. + +============================================================================== +6. Saving settings *save-settings* Mostly you will edit your vimrc files manually. This gives you the greatest flexibility. There are a few commands to generate a vimrc file automatically. @@ -753,7 +767,7 @@ these steps: You need to escape special characters, esp. spaces. ============================================================================== -6. Views and Sessions *views-sessions* +7. Views and Sessions *views-sessions* This is introduced in sections |21.4| and |21.5| of the user manual. @@ -897,7 +911,7 @@ To automatically save and restore views for *.c files: > au BufWinEnter *.c silent loadview ============================================================================== -7. The ShaDa file *shada* *shada-file* +8. The ShaDa file *shada* *shada-file* If you exit Vim and later start it again, you would normally lose a lot of information. The ShaDa file can be used to remember that information, which diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 81ba639dbe..4e4ea39e7c 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -1,4 +1,4 @@ -*syntax.txt* For Vim version 7.4. Last change: 2015 Dec 19 +*syntax.txt* For Vim version 7.4. Last change: 2016 Jan 28 VIM REFERENCE MANUAL by Bram Moolenaar @@ -3422,6 +3422,32 @@ SPELL CHECKING *:syn-spell* To activate spell checking the 'spell' option must be set. +SYNTAX ISKEYWORD SETTING *:syn-iskeyword* + +:sy[ntax] iskeyword [clear | {option}] + This defines the keyword characters. It's like the 'iskeyword' option + for but only applies to syntax highlighting. + + clear: Syntax specific iskeyword setting is disabled and the + buffer-local 'iskeyword' setting is used. + {option} Set the syntax 'iskeyword' option to a new value. + + Example: > + :syntax iskeyword @,48-57,192-255,$,_ +< + This would set the syntax specific iskeyword option to include all + alphabetic characters, plus the numeric characters, all accented + characters and also includes the "_" and the "$". + + If no argument is given, the current value will be output. + + Setting this option influences what |/\k| matches in syntax patterns + and also determines where |:syn-keyword| will be checked for a new + match. + + It is recommended when writing syntax files, to use this command + to the correct value for the specific syntax language and not change + the 'iskeyword' option. DEFINING KEYWORDS *:syn-keyword* @@ -3453,6 +3479,7 @@ DEFINING KEYWORDS *:syn-keyword* isn't, the keyword will never be recognized. Multi-byte characters can also be used. These do not have to be in 'iskeyword'. + See |:syn-iskeyword| for defining syntax specific iskeyword settings. A keyword always has higher priority than a match or region, the keyword is used if more than one item matches. Keywords do not nest diff --git a/runtime/doc/usr_02.txt b/runtime/doc/usr_02.txt index 6a288f8965..c10643940d 100644 --- a/runtime/doc/usr_02.txt +++ b/runtime/doc/usr_02.txt @@ -1,4 +1,4 @@ -*usr_02.txt* For Vim version 7.4. Last change: 2015 Apr 12 +*usr_02.txt* For Vim version 7.4. Last change: 2016 Jan 16 VIM USER MANUAL - by Bram Moolenaar @@ -397,7 +397,15 @@ original version of the file. Everything you always wanted to know can be found in the Vim help files. Don't be afraid to ask! - To get generic help use this command: > + +If you know what you are looking for, it is usually easier to search for it +using the help system, instead of using Google. Because the subjects follow +a certain style guide. + +Also the help has the advantage of belonging to your particular Vim version. +You won't see help for commands added later. These would not work for you. + +To get generic help use this command: > :help @@ -471,7 +479,7 @@ example, use the following command: > :help 'number' -The table with all mode prefixes can be found here: |help-context|. +The table with all mode prefixes can be found below: |help-summary|. Special keys are enclosed in angle brackets. To find help on the up-arrow key in Insert mode, for instance, use this command: > @@ -488,64 +496,191 @@ You can use the error ID at the start to find help about it: > Summary: *help-summary* > - :help -< Gives you very general help. Scroll down to see a list of all - helpfiles, including those added locally (i.e. not distributed - with Vim). > - :help user-toc.txt -< Table of contents of the User Manual. > - :help :subject -< Ex-command "subject", for instance the following: > - :help :help -< Help on getting help. > - :help abc -< normal-mode command "abc". > - :help CTRL-B -< Control key <C-B> in Normal mode. > - :help i_abc - :help i_CTRL-B -< The same in Insert mode. > - :help v_abc - :help v_CTRL-B -< The same in Visual mode. > - :help c_abc - :help c_CTRL-B -< The same in Command-line mode. > - :help 'subject' -< Option 'subject'. > - :help subject() -< Function "subject". > - :help -subject -< Command-line argument "-subject". > - :help +subject -< Compile-time feature "+subject". > - :help /* -< Regular expression item "*" > - :help EventName -< Autocommand event "EventName". > - :help digraphs.txt -< The top of the helpfile "digraph.txt". - Similarly for any other helpfile. > - :help pattern<Tab> -< Find a help tag starting with "pattern". Repeat <Tab> for - others. > - :help pattern<Ctrl-D> -< See all possible help tag matches "pattern" at once. > - :helpgrep pattern -< Search the whole text of all help files for pattern "pattern". - Jumps to the first match. Jump to other matches with: > - :cn -< next match > - :cprev - :cN -< previous match > - :cfirst - :clast -< first or last match > - :copen - :cclose -< open/close the quickfix window; press <Enter> to jump - to the item under the cursor + +1) Use Ctrl-D after typing a topic and let Vim show all available topics. + Or press Tab to complete: > + :help some<Tab> +< More information on how to use the help: > + :help helphelp + +2) Follow the links in bars to related help. You can go from the detailed + help to the user documentation, which describes certain commands more from + a user perspective and less detailed. E.g. after: > + :help pattern.txt +< You can see the user guide topics |03.9| and |usr_27.txt| in the + introduction. + +3) Options are enclosed in single apostrophes. To go to the help topic for the + list option: > + :help 'list' +< If you only know you are looking for a certain option, you can also do: > + :help options.txt +< to open the help page which describes all option handling and then search + using regular expressions, e.g. textwidth. + Certain options have their own namespace, e.g.: > + :help cpo-<letter> +< for the corresponding flag of the 'cpoptions' settings, substitute <letter> + by a specific flag, e.g.: > + :help cpo-; +< And for the guioption flags: > + :help go-<letter> + +4) Normal mode commands do not have a prefix. To go to the help page for the + "gt" command: > + :help gt + +5) Insert mode commands start with i_. Help for deleting a word: > + :help i_CTRL-W + +6) Visual mode commands start with v_. Help for jumping to the other side of + the Visual area: > + :help v_o + +7) Command line editing and arguments start with c_. Help for using the + command argument %: > + :help c_% + +8) Ex-commands always start with ":", so to go to the :s command help: > + :help :s + +9) Commands specifically for debugging start with ">". To go to to the help + for the "cont" debug command: > + :help >cont + +10) Key combinations. They usually start with a single letter indicating + the mode for which they can be used. E.g.: > + :help i_CTRL-X +< takes you to the family of Ctrl-X commands for insert mode which can be + used to auto complete different things. Note, that certain keys will + always be written the same, e.g. Control will always be CTRL. + For normal mode commands there is no prefix and the topic is available at + :h CTRL-<Letter>. E.g. > + :help CTRL-W +< In contrast > + :help c_CTRL-R +< will describe what the Ctrl-R does when entering commands in the Command + line and > + :help v_Ctrl-A +< talks about incrementing numbers in visual mode and > + :help g_CTRL-A +< talks about the g<C-A> command (e.g. you have to press "g" then <Ctrl-A>). + Here the "g" stand for the normal command "g" which always expects a second + key before doing something similar to the commands starting with "z" + +11) Regexp items always start with /. So to get help for the "\+" quantifier + in Vim regexes: > + :help /\+ +< If you need to know everything about regular expressions, start reading + at: > + :help pattern.txt + +12) Registers always start with "quote". To find out about the special ":" + register: > + :help quote: + +13) Vim Script (VimL) is available at > + :help eval.txt +< Certain aspects of the language are available at :h expr-X where "X" is a + single letter. E.g. > + :help expr-! +< will take you to the topic describing the "!" (Not) operator for + VimScript. + Also important is > + :help function-list +< to find a short description of all functions available. Help topics for + VimL functions always include the "()", so: > + :help append() +< talks about the append VimL function rather than how to append text in the + current buffer. + +14) Mappings are talked about in the help page :h |map.txt|. Use > + :help mapmode-i +< to find out about the |:imap| command. Also use :map-topic + to find out about certain subtopics particular for mappings. e.g: > + :help :map-local +< for buffer-local mappings or > + :help map-bar +< for how the '|' is handled in mappings. + +15) Command definitions are talked about :h command-topic, so use > + :help command-bar +< to find out about the '!' argument for custom commands. + +16) Window management commands always start with CTRL-W, so you find the + corresponding help at :h CTRL-W_letter. E.g. > + :help CTRL-W_p +< for moving the previous accessed window. You can also access > + :help windows.txt +< and read your way through if you are looking for window handling + commands. + +17) Use |:helpgrep| to search in all help pages (and also of any installed + plugins). See |:helpgrep| for how to use it. + To search for a topic: > + :helpgrep topic +< This takes you to the first match. To go to the next one: > + :cnext +< All matches are available in the quickfix window which can be opened + with: > + :copen +< Move around to the match you like and press Enter to jump to that help. + +18) The user manual. This describes help topics for beginners in a rather + friendly way. Start at |usr_toc.txt| to find the table of content (as you + might have guessed): > + :help usr_toc.txt +< Skim over the contents to find interesting topics. The "Digraphs" and + "Entering special characters" items are in chapter 24, so to go to that + particular help page: > + :help usr_24.txt +< Also if you want to access a certain chapter in the help, the chapter + number can be accessed directly like this: > + :help 10.1 +< goes to chapter 10.1 in |usr_10.txt| and talks about recording macros. + +19) Highlighting groups. Always start with hl-groupname. E.g. > + :help hl-WarningMsg +< talks about the WarningMsg highlighting group. + +20) Syntax highlighting is namespaced to :syn-topic e.g. > + :help :syn-conceal +< talks about the conceal argument for the :syn command. + +21) Quickfix commands usually start with :c while location list commands + usually start with :l + +22) Autocommand events can be found by their name: > + :help BufWinLeave +< To see all possible events: > + :help autocommands-events + +23) Command-line switches always start with "-". So for the help of the -f + command switch of Vim use: > + :help -f + +24) Optional features always start with "+". To find out about the + conceal feature use: > + :help +conceal + +25) Documentation for included filetype specific functionality is usually + available in the form ft-<filetype>-<functionality>. So > + :help ft-c-syntax +< talks about the C syntax file and the option it provides. Sometimes, + additional sections for omni completion > + :help ft-php-omni +< or filetype plugins > + :help ft-tex-plugin +< are available. + +26) Error and Warning codes can be looked up directly in the help. So > + :help E297 +< takes you exactly to the description of the swap error message and > + :help W10 +< talks about the warning "Changing a readonly file". + Sometimes however, those error codes are not described, but rather are + listed at the Vim command that usually causes this. So: > + :help E128 +< takes you to the |:function| command ============================================================================== diff --git a/runtime/doc/usr_03.txt b/runtime/doc/usr_03.txt index b8f65d9309..943d7b528c 100644 --- a/runtime/doc/usr_03.txt +++ b/runtime/doc/usr_03.txt @@ -1,4 +1,4 @@ -*usr_03.txt* For Vim version 7.4. Last change: 2015 Dec 12 +*usr_03.txt* For Vim version 7.4. Last change: 2016 Jan 05 VIM USER MANUAL - by Bram Moolenaar @@ -414,8 +414,8 @@ in "the" use: > /the\> The "\>" item is a special marker that only matches at the end of a word. -Similarly "\<" only matches at the begin of a word. Thus to search for the -word "the" only: > +Similarly "\<" only matches at the beginning of a word. Thus to search for +the word "the" only: > /\<the\> diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index fc8419a522..a14e722328 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -1,4 +1,4 @@ -*usr_41.txt* For Vim version 7.4. Last change: 2015 Nov 30 +*usr_41.txt* For Vim version 7.4. Last change: 2016 Feb 14 VIM USER MANUAL - by Bram Moolenaar @@ -2224,7 +2224,7 @@ This construct makes sure the function is only defined once: > :endif < -UNDO *undo_ftplugin* +UNDO *undo_indent* *undo_ftplugin* When the user does ":setfiletype xyz" the effect of the previous filetype should be undone. Set the b:undo_ftplugin variable to the commands that will @@ -2239,6 +2239,9 @@ global value. That is mostly the best way to reset the option value. This does require removing the "C" flag from 'cpoptions' to allow line continuation, as mentioned above |use-cpo-save|. +For undoing the effect of an indent script, the b:undo_indent variable should +be set accordingly. + FILE NAME diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index af4224993f..a2c0f45b23 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -1,4 +1,4 @@ -*various.txt* For Vim version 7.4. Last change: 2015 Nov 15 +*various.txt* For Vim version 7.4. Last change: 2016 Feb 18 VIM REFERENCE MANUAL by Bram Moolenaar @@ -319,8 +319,7 @@ N *+dialog_con* Support for |:confirm| with console dialog. N *+dialog_con_gui* Support for |:confirm| with GUI and console dialog. N *+digraphs* |digraphs| *E196* N *+eval* expression evaluation |eval.txt| -N *+ex_extra* Vim's extra Ex commands: |:center|, |:left|, - |:normal|, |:retab| and |:right| +N *+ex_extra* always on now, used to be for Vim's extra Ex commands N *+extra_search* |'hlsearch'| and |'incsearch'| options. B *+farsi* |farsi| language N *+file_in_path* |gf|, |CTRL-W_f| and |<cfile>| @@ -455,7 +454,7 @@ m *+xpm_w32* Win32 GUI only: pixmap support |w32-xpm-support| :redi[r] END End redirecting messages. - *:sil* *:silent* + *:sil* *:silent* *:silent!* :sil[ent][!] {command} Execute {command} silently. Normal messages will not be given or added to the message history. When [!] is added, error messages will also be diff --git a/runtime/doc/vi_diff.txt b/runtime/doc/vi_diff.txt index ec35694c9e..54ef8fecb2 100644 --- a/runtime/doc/vi_diff.txt +++ b/runtime/doc/vi_diff.txt @@ -1,4 +1,4 @@ -*vi_diff.txt* For Vim version 7.4. Last change: 2015 Nov 01 +*vi_diff.txt* For Vim version 7.4. Last change: 2016 Feb 12 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt index 51b73223b6..d5c7db992e 100644 --- a/runtime/doc/windows.txt +++ b/runtime/doc/windows.txt @@ -1,4 +1,4 @@ -*windows.txt* For Vim version 7.4. Last change: 2015 Nov 14 +*windows.txt* For Vim version 7.4. Last change: 2016 Feb 01 VIM REFERENCE MANUAL by Bram Moolenaar @@ -707,8 +707,8 @@ can also get to them with the buffer list commands, like ":bnext". *:bufdo* :[range]bufdo[!] {cmd} Execute {cmd} in each buffer in the buffer list or if [range] is given only for buffers for which their - buffer name is in the [range]. It works like doing - this: > + buffer number is in the [range]. It works like doing + this: > :bfirst :{cmd} :bnext diff --git a/runtime/ftplugin/hgcommit.vim b/runtime/ftplugin/hgcommit.vim new file mode 100644 index 0000000000..d5a6c0a383 --- /dev/null +++ b/runtime/ftplugin/hgcommit.vim @@ -0,0 +1,16 @@ +" Vim filetype plugin file +" Language: hg (Mercurial) commit file +" Maintainer: Ken Takata <kentkt at csc dot jp> +" Last Change: 2016 Jan 6 +" Filenames: hg-editor-*.txt +" License: VIM License +" URL: https://github.com/k-takata/hg-vim + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +setlocal nomodeline + +let b:undo_ftplugin = 'setl modeline<' diff --git a/runtime/indent/fortran.vim b/runtime/indent/fortran.vim index d492889fc7..e19a19fb1f 100644 --- a/runtime/indent/fortran.vim +++ b/runtime/indent/fortran.vim @@ -1,11 +1,11 @@ " Vim indent file " Language: Fortran 2008 (and older: Fortran 2003, 95, 90, and 77) -" Version: 0.42 -" Last Change: 2015 Nov. 30 +" Version: 0.44 +" Last Change: 2016 Jan. 26 " Maintainer: Ajit J. Thakkar <ajit@unb.ca>; <http://www2.unb.ca/~ajit/> " Usage: For instructions, do :help fortran-indent from Vim " Credits: -" Useful suggestions were made by: Albert Oliver Serra. +" Useful suggestions were made by: Albert Oliver Serra and Takuya Fujiwara. " Only load this indent file when no other was loaded. if exists("b:did_indent") @@ -92,10 +92,10 @@ function FortranGetIndent(lnum) "Indent do loops only if they are all guaranteed to be of do/end do type if exists("b:fortran_do_enddo") || exists("g:fortran_do_enddo") if prevstat =~? '^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*do\>' - let ind = ind + &sw + let ind = ind + shiftwidth() endif if getline(v:lnum) =~? '^\s*\(\d\+\s\)\=\s*end\s*do\>' - let ind = ind - &sw + let ind = ind - shiftwidth() endif endif @@ -105,14 +105,14 @@ function FortranGetIndent(lnum) \ ||prevstat=~? '^\s*\(type\|interface\|associate\|enum\)\>' \ ||prevstat=~?'^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*\(forall\|where\|block\)\>' \ ||prevstat=~? '^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*if\>' - let ind = ind + &sw + let ind = ind + shiftwidth() " Remove unwanted indent after logical and arithmetic ifs if prevstat =~? '\<if\>' && prevstat !~? '\<then\>' - let ind = ind - &sw + let ind = ind - shiftwidth() endif " Remove unwanted indent after type( statements if prevstat =~? '^\s*type\s*(' - let ind = ind - &sw + let ind = ind - shiftwidth() endif endif @@ -125,12 +125,12 @@ function FortranGetIndent(lnum) \ ||prevstat =~? '^\s*'.prefix.'subroutine\>' \ ||prevstat =~? '^\s*'.prefix.type.'function\>' \ ||prevstat =~? '^\s*'.type.prefix.'function\>' - let ind = ind + &sw + let ind = ind + shiftwidth() endif if getline(v:lnum) =~? '^\s*contains\>' \ ||getline(v:lnum)=~? '^\s*end\s*' \ .'\(function\|subroutine\|module\|program\)\>' - let ind = ind - &sw + let ind = ind - shiftwidth() endif endif @@ -141,23 +141,23 @@ function FortranGetIndent(lnum) \. '\(else\|else\s*if\|else\s*where\|case\|' \. 'end\s*\(if\|where\|select\|interface\|' \. 'type\|forall\|associate\|enum\|block\)\)\>' - let ind = ind - &sw + let ind = ind - shiftwidth() " Fix indent for case statement immediately after select if prevstat =~? '\<select\s\+\(case\|type\)\>' - let ind = ind + &sw + let ind = ind + shiftwidth() endif endif "First continuation line if prevstat =~ '&\s*$' && prev2stat !~ '&\s*$' - let ind = ind + &sw + let ind = ind + shiftwidth() endif if prevstat =~ '&\s*$' && prevstat =~ '\<else\s*if\>' - let ind = ind - &sw + let ind = ind - shiftwidth() endif "Line after last continuation line if prevstat !~ '&\s*$' && prev2stat =~ '&\s*$' && prevstat !~? '\<then\>' - let ind = ind - &sw + let ind = ind - shiftwidth() endif return ind diff --git a/runtime/indent/lua.vim b/runtime/indent/lua.vim index 393994c590..d1d2c0d600 100644 --- a/runtime/indent/lua.vim +++ b/runtime/indent/lua.vim @@ -2,7 +2,7 @@ " Language: Lua script " Maintainer: Marcus Aurelius Farias <marcus.cf 'at' bol.com.br> " First Author: Max Ischenko <mfi 'at' ukr.net> -" Last Change: 2014 Nov 12 +" Last Change: 2016 Jan 10 " Only load this indent file when no other was loaded. if exists("b:did_indent") @@ -52,7 +52,7 @@ function! GetLuaIndent() endif endif - " Subtract a 'shiftwidth' on end, else (and elseif), until and '}' + " Subtract a 'shiftwidth' on end, else, elseif, until and '}' " This is the part that requires 'indentkeys'. let midx = match(getline(v:lnum), '^\s*\%(end\>\|else\>\|elseif\>\|until\>\|}\)') if midx != -1 && synIDattr(synID(v:lnum, midx + 1, 1), "name") != "luaComment" diff --git a/runtime/indent/php.vim b/runtime/indent/php.vim index 1bffa7f195..07ecd8f141 100644 --- a/runtime/indent/php.vim +++ b/runtime/indent/php.vim @@ -3,8 +3,8 @@ " Author: John Wellesz <John.wellesz (AT) teaser (DOT) fr> " URL: http://www.2072productions.com/vim/indent/php.vim " Home: https://github.com/2072/PHP-Indenting-for-VIm -" Last Change: 2014 November 26th -" Version: 1.57 +" Last Change: 2015 September 8th +" Version: 1.60 " " " Type :help php-indent for available options @@ -50,16 +50,25 @@ let b:did_indent = 1 let g:php_sync_method = 0 +if exists('*shiftwidth') + function! s:sw() + return shiftwidth() + endfunction +else + function! s:sw() + return &shiftwidth + endfunction +endif if exists("PHP_default_indenting") - let b:PHP_default_indenting = PHP_default_indenting * &sw + let b:PHP_default_indenting = PHP_default_indenting * s:sw() else let b:PHP_default_indenting = 0 endif if exists("PHP_outdentSLComments") - let b:PHP_outdentSLComments = PHP_outdentSLComments * &sw + let b:PHP_outdentSLComments = PHP_outdentSLComments * s:sw() else let b:PHP_outdentSLComments = 0 endif @@ -124,7 +133,7 @@ endif if exists("*GetPhpIndent") call ResetPhpOptions() - finish " XXX -- comment this line for easy dev + finish endif @@ -135,7 +144,7 @@ let s:functionDecl = '\<function\>\%(\s\+'.s:PHP_validVariable.'\)\=\s*(.*' let s:endline= '\s*\%(//.*\|#.*\|/\*.*\*/\s*\)\=$' -let s:terminated = '\%(\%(;\%(\s*\%(?>\|}\)\)\=\|<<<''\=\a\w*''\=$\|^\s*}\|^\s*'.s:PHP_validVariable.':\)'.s:endline.'\)\|^[^''"`]*[''"`]$' +let s:terminated = '\%(\%(;\%(\s*\%(?>\|}\)\)\=\|<<<\s*[''"]\=\a\w*[''"]\=$\|^\s*}\|^\s*'.s:PHP_validVariable.':\)'.s:endline.'\)\|^[^''"`]*[''"`]$' let s:PHP_startindenttag = '<?\%(.*?>\)\@!\|<script[^>]*>\%(.*<\/script>\)\@!' @@ -200,7 +209,7 @@ function! GetLastRealCodeLNum(startline) " {{{ elseif lastline =~? '^\a\w*;\=$' && lastline !~? s:notPhpHereDoc - let tofind=substitute( lastline, '\(\a\w*\);\=', '<<<''\\=\1''\\=$', '') + let tofind=substitute( lastline, '\(\a\w*\);\=', '<<<\\s*[''"]\\=\1[''"]\\=$', '') while getline(lnum) !~? tofind && lnum > 1 let lnum = lnum - 1 endwhile @@ -314,7 +323,7 @@ function! FindTheSwitchIndent (lnum) " {{{ let test = GetLastRealCodeLNum(a:lnum - 1) if test <= 1 - return indent(1) - &sw * b:PHP_vintage_case_default_indent + return indent(1) - s:sw() * b:PHP_vintage_case_default_indent end while getline(test) =~ '^\s*}' && test > 1 @@ -328,7 +337,7 @@ function! FindTheSwitchIndent (lnum) " {{{ if getline(test) =~# '^\s*switch\>' return indent(test) elseif getline(test) =~# s:defaultORcase - return indent(test) - &sw * b:PHP_vintage_case_default_indent + return indent(test) - s:sw() * b:PHP_vintage_case_default_indent else return FindTheSwitchIndent(test) endif @@ -401,7 +410,7 @@ function! GetPhpIndent() endif if b:PHP_default_indenting - let b:PHP_default_indenting = g:PHP_default_indenting * &sw + let b:PHP_default_indenting = g:PHP_default_indenting * s:sw() endif let cline = getline(v:lnum) @@ -439,6 +448,7 @@ function! GetPhpIndent() if !b:InPHPcode_checked " {{{ One time check let b:InPHPcode_checked = 1 + let b:UserIsTypingComment = 0 let synname = "" if cline !~ '<?.*?>' @@ -447,8 +457,7 @@ function! GetPhpIndent() if synname!="" if synname == "SpecStringEntrails" - let b:InPHPcode = -1 " thumb down - let b:UserIsTypingComment = 0 + let b:InPHPcode = -1 let b:InPHPcode_tofind = "" elseif synname != "phpHereDoc" && synname != "phpHereDocDelimiter" let b:InPHPcode = 1 @@ -456,8 +465,7 @@ function! GetPhpIndent() if synname =~# '^php\%(Doc\)\?Comment' let b:UserIsTypingComment = 1 - else - let b:UserIsTypingComment = 0 + let b:InPHPcode_checked = 0 endif if synname =~? '^javaScript' @@ -466,18 +474,16 @@ function! GetPhpIndent() else let b:InPHPcode = 0 - let b:UserIsTypingComment = 0 let lnum = v:lnum - 1 - while getline(lnum) !~? '<<<''\=\a\w*''\=$' && lnum > 1 + while getline(lnum) !~? '<<<\s*[''"]\=\a\w*[''"]\=$' && lnum > 1 let lnum = lnum - 1 endwhile - let b:InPHPcode_tofind = substitute( getline(lnum), '^.*<<<''\=\(\a\w*\)''\=$', '^\\s*\1;\\=$', '') + let b:InPHPcode_tofind = substitute( getline(lnum), '^.*<<<\s*[''"]\=\(\a\w*\)[''"]\=$', '^\\s*\1;\\=$', '') endif else let b:InPHPcode = 0 - let b:UserIsTypingComment = 0 let b:InPHPcode_tofind = s:PHP_startindenttag endif endif "!b:InPHPcode_checked }}} @@ -537,9 +543,9 @@ function! GetPhpIndent() elseif last_line =~ '^[^''"`]\+[''"`]$' let b:InPHPcode = -1 let b:InPHPcode_tofind = substitute( last_line, '^.*\([''"`]\).*$', '^[^\1]*\1[;,]$', '') - elseif last_line =~? '<<<''\=\a\w*''\=$' + elseif last_line =~? '<<<\s*[''"]\=\a\w*[''"]\=$' let b:InPHPcode = 0 - let b:InPHPcode_tofind = substitute( last_line, '^.*<<<''\=\(\a\w*\)''\=$', '^\\s*\1;\\=$', '') + let b:InPHPcode_tofind = substitute( last_line, '^.*<<<\s*[''"]\=\(\a\w*\)[''"]\=$', '^\\s*\1;\\=$', '') elseif !UserIsEditing && cline =~ '^\s*/\*\%(.*\*/\)\@!' && getline(v:lnum + 1) !~ '^\s*\*' let b:InPHPcode = 0 @@ -660,7 +666,7 @@ function! GetPhpIndent() let b:PHP_CurrentIndentLevel = b:PHP_default_indenting return indent(FindTheIfOfAnElse(v:lnum, 1)) elseif cline =~# s:defaultORcase - return FindTheSwitchIndent(v:lnum) + &sw * b:PHP_vintage_case_default_indent + return FindTheSwitchIndent(v:lnum) + s:sw() * b:PHP_vintage_case_default_indent elseif cline =~ '^\s*)\=\s*{' let previous_line = last_line let last_line_num = lnum @@ -672,7 +678,7 @@ function! GetPhpIndent() let ind = indent(last_line_num) if b:PHP_BracesAtCodeLevel - let ind = ind + &sw + let ind = ind + s:sw() endif return ind @@ -683,7 +689,7 @@ function! GetPhpIndent() endwhile elseif last_line =~# unstated && cline !~ '^\s*);\='.endline - let ind = ind + &sw + let ind = ind + s:sw() return ind + addSpecial elseif (ind != b:PHP_default_indenting || last_line =~ '^[)\]]' ) && last_line =~ terminated @@ -782,7 +788,7 @@ function! GetPhpIndent() endif if !dontIndent && (!b:PHP_BracesAtCodeLevel || last_line !~# '^\s*{') - let ind = ind + &sw + let ind = ind + s:sw() endif if b:PHP_BracesAtCodeLevel || b:PHP_vintage_case_default_indent == 1 @@ -800,17 +806,17 @@ function! GetPhpIndent() endif elseif last_line =~ '^\s*'.s:blockstart - let ind = ind + &sw + let ind = ind + s:sw() elseif AntepenultimateLine =~ '{'.endline || AntepenultimateLine =~ terminated || AntepenultimateLine =~# s:defaultORcase - let ind = ind + &sw + let ind = ind + s:sw() endif endif if cline =~ '^\s*[)\]];\=' - let ind = ind - &sw + let ind = ind - s:sw() endif let b:PHP_CurrentIndentLevel = ind diff --git a/runtime/indent/sh.vim b/runtime/indent/sh.vim index 5bd8c77fab..2d603b0afa 100644 --- a/runtime/indent/sh.vim +++ b/runtime/indent/sh.vim @@ -3,7 +3,7 @@ " Maintainer: Christian Brabandt <cb@256bit.org> " Previous Maintainer: Peter Aronoff <telemachus@arpinum.org> " Original Author: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2015-12-15 +" Latest Revision: 2016-01-15 " License: Vim (see :h license) " Repository: https://github.com/chrisbra/vim-sh-indent @@ -28,7 +28,7 @@ let s:cpo_save = &cpo set cpo&vim function s:buffer_shiftwidth() - return &shiftwidth + return shiftwidth() endfunction let s:sh_indent_defaults = { diff --git a/runtime/indent/vim.vim b/runtime/indent/vim.vim index 7511325af4..31b76b8c0c 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: 2014 Dec 12 +" Last Change: 2016 Jan 24 " Only load this indent file when no other was loaded. if exists("b:did_indent") @@ -58,19 +58,19 @@ function GetVimIndentIntern() if exists("g:vim_indent_cont") let ind = ind + g:vim_indent_cont else - let ind = ind + &sw * 3 + let ind = ind + shiftwidth() * 3 endif elseif prev_text =~ '^\s*aug\%[roup]' && prev_text !~ '^\s*aug\%[roup]\s*!\=\s\+END' - let ind = ind + &sw + let ind = ind + shiftwidth() else " A line starting with :au does not increment/decrement indent. if prev_text !~ '^\s*au\%[tocmd]' let i = match(prev_text, '\(^\||\)\s*\(if\|wh\%[ile]\|for\|try\|cat\%[ch]\|fina\%[lly]\|fu\%[nction]\|el\%[seif]\)\>') if i >= 0 - let ind += &sw + let ind += shiftwidth() if strpart(prev_text, i, 1) == '|' && has('syntax_items') \ && synIDattr(synID(lnum, i, 1), "name") =~ '\(Comment\|String\)$' - let ind -= &sw + let ind -= shiftwidth() endif endif endif @@ -82,7 +82,7 @@ function GetVimIndentIntern() let i = match(prev_text, '[^\\]|\s*\(ene\@!\)') if i > 0 && prev_text !~ '^\s*au\%[tocmd]' if !has('syntax_items') || synIDattr(synID(lnum, i + 2, 1), "name") !~ '\(Comment\|String\)$' - let ind = ind - &sw + let ind = ind - shiftwidth() endif endif @@ -90,7 +90,7 @@ function GetVimIndentIntern() " Subtract a 'shiftwidth' on a :endif, :endwhile, :catch, :finally, :endtry, " :endfun, :else and :augroup END. if cur_text =~ '^\s*\(ene\@!\|cat\|fina\|el\|aug\%[roup]\s*!\=\s\+[eE][nN][dD]\)' - let ind = ind - &sw + let ind = ind - shiftwidth() endif return ind diff --git a/runtime/indent/zimbu.vim b/runtime/indent/zimbu.vim index 9565b10843..5451877ea7 100644 --- a/runtime/indent/zimbu.vim +++ b/runtime/indent/zimbu.vim @@ -1,7 +1,7 @@ " Vim indent file " Language: Zimbu " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2012 Sep 08 +" Last Change: 2016 Jan 25 " Only load this indent file when no other was loaded. if exists("b:did_indent") @@ -74,9 +74,9 @@ func GetZimbuIndent(lnum) \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" \ . " =~ '\\(Comment\\|String\\|Char\\)$'") if pp > 0 - return indent(prevLnum) + &sw + return indent(prevLnum) + shiftwidth() endif - return indent(prevLnum) + &sw * 2 + return indent(prevLnum) + shiftwidth() * 2 endif if plnumstart == p return indent(prevLnum) @@ -102,13 +102,13 @@ func GetZimbuIndent(lnum) endif if prevline =~ '^\s*\(IF\|\|ELSEIF\|ELSE\|GENERATE_IF\|\|GENERATE_ELSEIF\|GENERATE_ELSE\|WHILE\|REPEAT\|TRY\|CATCH\|FINALLY\|FOR\|DO\|SWITCH\|CASE\|DEFAULT\|FUNC\|VIRTUAL\|ABSTRACT\|DEFINE\|REPLACE\|FINAL\|PROC\|MAIN\|NEW\|ENUM\|CLASS\|INTERFACE\|BITS\|MODULE\|SHARED\)\>' - let plindent += &sw + let plindent += shiftwidth() endif if thisline =~ '^\s*\(}\|ELSEIF\>\|ELSE\>\|CATCH\|FINALLY\|GENERATE_ELSEIF\>\|GENERATE_ELSE\>\|UNTIL\>\)' - let plindent -= &sw + let plindent -= shiftwidth() endif if thisline =~ '^\s*\(CASE\>\|DEFAULT\>\)' && prevline !~ '^\s*SWITCH\>' - let plindent -= &sw + let plindent -= shiftwidth() endif " line up continued comment that started after some code diff --git a/runtime/plugin/matchparen.vim b/runtime/plugin/matchparen.vim index 873302efee..5db1f64c78 100644 --- a/runtime/plugin/matchparen.vim +++ b/runtime/plugin/matchparen.vim @@ -1,6 +1,6 @@ " Vim plugin for showing matching parens " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2015 Dec 31 +" Last Change: 2016 Feb 16 " Exit quickly when: " - this plugin was already loaded (or disabled) diff --git a/runtime/plugin/netrwPlugin.vim b/runtime/plugin/netrwPlugin.vim index 3776ac30f8..69902b1f19 100644 --- a/runtime/plugin/netrwPlugin.vim +++ b/runtime/plugin/netrwPlugin.vim @@ -1,6 +1,6 @@ " netrwPlugin.vim: Handles file transfer and remote directory listing across a network " PLUGIN SECTION -" Date: Nov 07, 2014 +" Date: Feb 08, 2016 " Maintainer: Charles E Campbell <NdrOchip@ScampbellPfamily.AbizM-NOSPAM> " GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim " Copyright: Copyright (C) 1999-2013 Charles E. Campbell {{{1 @@ -20,7 +20,7 @@ if &cp || exists("g:loaded_netrwPlugin") finish endif -let g:loaded_netrwPlugin = "v154" +let g:loaded_netrwPlugin = "v155" let s:keepcpo = &cpo set cpo&vim "DechoRemOn @@ -55,10 +55,10 @@ augroup Network augroup END " Commands: :Nread, :Nwrite, :NetUserPass {{{2 -com! -count=1 -nargs=* Nread call netrw#SavePosn()<bar>call netrw#NetRead(<count>,<f-args>)<bar>call netrw#RestorePosn() -com! -range=% -nargs=* Nwrite call netrw#SavePosn()<bar><line1>,<line2>call netrw#NetWrite(<f-args>)<bar>call netrw#RestorePosn() +com! -count=1 -nargs=* Nread let s:svpos= winsaveview()<bar>call netrw#NetRead(<count>,<f-args>)<bar>call winrestview(s:svpos) +com! -range=% -nargs=* Nwrite let s:svpos= winsaveview()<bar><line1>,<line2>call netrw#NetWrite(<f-args>)<bar>call winrestview(s:svpos) com! -nargs=* NetUserPass call NetUserPass(<f-args>) -com! -nargs=* Nsource call netrw#SavePosn()<bar>call netrw#NetSource(<f-args>)<bar>call netrw#RestorePosn() +com! -nargs=* Nsource let s:svpos= winsaveview()<bar>call netrw#NetSource(<f-args>)<bar>call winrestview(s:svpos) com! -nargs=? Ntree call netrw#SetTreetop(<q-args>) " Commands: :Explore, :Sexplore, Hexplore, Vexplore, Lexplore {{{2 diff --git a/runtime/syntax/aptconf.vim b/runtime/syntax/aptconf.vim index 0607ca10f5..7a31b2d15e 100644 --- a/runtime/syntax/aptconf.vim +++ b/runtime/syntax/aptconf.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: APT config file " Maintainer: Yann Amar <quidame@poivron.org> -" Last Change: 2013 Apr 12 +" Last Change: 2015 Dec 22 " For version 5.x: Clear all syntax items " For version 6.x and 7.x: Quit when a syntax file was already loaded @@ -38,22 +38,22 @@ setlocal iskeyword+=/,-,.,_,+ " Incomplete keywords will be treated differently than completely bad strings: syn keyword aptconfGroupIncomplete - \ a[cquire] a[ptitude] d[ebtags] d[ebug] d[ir] d[pkg] d[select] - \ o[rderlist] p[ackagemanager] p[kgcachegen] q[uiet] r[pm] - \ u[nattended-upgrade] + \ a[cquire] a[dequate] a[ptitude] a[ptlistbugs] d[ebtags] d[ebug] + \ d[ir] d[pkg] d[select] o[rderlist] p[ackagemanager] p[kgcachegen] + \ q[uiet] r[pm] s[ynaptic] u[nattended-upgrade] w[hatmaps] " Only the following keywords can be used at toplevel (to begin an option): syn keyword aptconfGroup - \ acquire apt aptitude debtags debug dir dpkg dselect - \ orderlist packagemanager pkgcachegen quiet rpm - \ unattended-upgrade + \ acquire adequate apt aptitude aptlistbugs debtags debug + \ dir dpkg dselect orderlist packagemanager pkgcachegen + \ quiet rpm synaptic unattended-upgrade whatmaps " Possible options for each group: " Acquire: {{{ syn keyword aptconfAcquire contained - \ cdrom Check-Valid-Until CompressionTypes ForceHash ftp gpgv - \ GzipIndexes http https Languages Max-ValidTime Min-ValidTime PDiffs - \ Queue-Mode Retries Source-Symlinks + \ cdrom Check-Valid-Until CompressionTypes ForceHash ForceIPv4 + \ ForceIPv6 ftp gpgv GzipIndexes http https Languages Max-ValidTime + \ Min-ValidTime PDiffs Queue-Mode Retries Source-Symlinks syn keyword aptconfAcquireCDROM contained \ AutoDetect CdromOnly Mount UMount @@ -62,14 +62,15 @@ syn keyword aptconfAcquireCompressionTypes contained \ bz2 lzma gz Order syn keyword aptconfAcquireFTP contained - \ Passive Proxy ProxyLogin Timeout + \ ForceExtended Passive Proxy ProxyLogin Timeout syn keyword aptconfAcquireHTTP contained \ AllowRedirect Dl-Limit Max-Age No-Cache No-Store Pipeline-Depth - \ Proxy Timeout User-Agent + \ Proxy ProxyAutoDetect Proxy-Auto-Detect Timeout User-Agent syn keyword aptconfAcquireHTTPS contained - \ CaInfo CaPath CrlFile IssuerCert SslCert SslForceVersion SslKey + \ AllowRedirect CaInfo CaPath CrlFile Dl-Limit IssuerCert Max-Age + \ No-Cache No-Store Proxy SslCert SslForceVersion SslKey Timeout \ Verify-Host Verify-Peer syn keyword aptconfAcquireMaxValidTime contained @@ -83,14 +84,21 @@ syn cluster aptconfAcquire_ contains=aptconfAcquire, \ aptconfAcquireHTTP,aptconfAcquireHTTPS,aptconfAcquireMaxValidTime, \ aptconfAcquirePDiffs " }}} +" Adequate: {{{ +syn keyword aptconfAdequate contained + \ Enabled + +syn cluster aptconfAdequate_ contains=aptconfAdequate +" }}} " Apt: {{{ syn keyword aptconfApt contained \ Architecture Architectures Archive Authentication AutoRemove - \ Build-Essential Cache Cache-Grow Cache-Limit Cache-Start CDROM - \ Changelogs Clean-Installed Compressor Default-Release - \ Force-LoopBreak Get Ignore-Hold Immediate-Configure + \ Build-Essential Build-Profiles Cache Cache-Grow Cache-Limit + \ Cache-Start CDROM Changelogs Clean-Installed Compressor + \ Default-Release Force-LoopBreak Get Ignore-Hold Immediate-Configure \ Install-Recommends Install-Suggests Keep-Fds List-Cleanup - \ NeverAutoRemove Never-MarkAuto-Sections Periodic Status-Fd Update + \ Move-Autobit-Sections NeverAutoRemove Never-MarkAuto-Sections + \ Periodic Status-Fd Update VersionedKernelPackages syn keyword aptconfAptAuthentication contained \ TrustCDROM @@ -124,11 +132,12 @@ syn keyword aptconfAptGet contained syn keyword aptconfAptPeriodic contained \ AutocleanInterval BackupArchiveInterval BackupLevel - \ Download-Upgradeable-Packages MaxAge MaxSize MinAge - \ Unattended-Upgrade Update-Package-Lists Verbose + \ Download-Upgradeable-Packages Download-Upgradeable-Packages-Debdelta + \ Enable MaxAge MaxSize MinAge Unattended-Upgrade Update-Package-Lists + \ Verbose syn keyword aptconfAptUpdate contained - \ Pre-Invoke Post-Invoke Post-Invoke-Success + \ List-Refresh Pre-Invoke Post-Invoke Post-Invoke-Success syn cluster aptconfApt_ contains=aptconfApt, \ aptconfAptAuthentication,aptconfAptAutoRemove,aptconfAptCache, @@ -240,6 +249,12 @@ syn cluster aptconfAptitude_ contains=aptconfAptitude, \ aptconfAptitudeUIKeyBindings,aptconfAptitudeUIStyles, \ aptconfAptitudeUIStylesElements " }}} +" AptListbugs: {{{ +syn keyword aptconfAptListbugs contained + \ IgnoreRegexp Severities + +syn cluster aptconfAptListbugs_ contains=aptconfAptListbugs +" }}} " DebTags: {{{ syn keyword aptconfDebTags contained \ Vocabulary @@ -251,7 +266,8 @@ syn keyword aptconfDebug contained \ Acquire aptcdrom BuildDeps Hashes IdentCdrom Nolocking \ pkgAcquire pkgAutoRemove pkgCacheGen pkgDepCache pkgDPkgPM \ pkgDPkgProgressReporting pkgInitialize pkgOrderList - \ pkgPackageManager pkgPolicy pkgProblemResolver sourceList + \ pkgPackageManager pkgPolicy pkgProblemResolver RunScripts + \ sourceList syn keyword aptconfDebugAcquire contained \ cdrom Ftp gpgv Http Https netrc @@ -295,7 +311,7 @@ syn keyword aptconfDirMedia contained \ MountPath syn keyword aptconfDirState contained - \ cdroms extended_states Lists mirrors status + \ cdroms extended_states Lists mirrors preferences status syn cluster aptconfDir_ contains=aptconfDir, \ aptconfDirAptitude,aptconfDirBin,aptconfDirCache,aptconfDirEtc, @@ -303,15 +319,16 @@ syn cluster aptconfDir_ contains=aptconfDir, " }}} " DPkg: {{{ syn keyword aptconfDPkg contained - \ Build-Options Chroot-Directory ConfigurePending FlushSTDIN MaxArgs - \ MaxBytes NoTriggers options Pre-Install-Pkgs Pre-Invoke Post-Invoke + \ Build-Options Chroot-Directory ConfigurePending FlushSTDIN + \ MaxArgBytes MaxArgs MaxBytes NoTriggers options + \ Pre-Install-Pkgs Pre-Invoke Post-Invoke \ Run-Directory StopOnError Tools TriggersPending syn keyword aptconfDPkgTools contained - \ Options Version + \ adequate InfoFD Options Version syn cluster aptconfDPkg_ contains=aptconfDPkg, - \ aptconfDPkgOrderList,aptconfDPkgOrderListScore,aptconfDPkgTools + \ aptconfDPkgTools " }}} " DSelect: {{{ syn keyword aptconfDSelect contained @@ -353,23 +370,59 @@ syn keyword aptconfRpm contained syn cluster aptconfRpm_ contains=aptconfRpm " }}} -" Unattened Upgrade: {{{ +" Synaptic: {{{ +syn keyword aptconfSynaptic contained + \ AskQuitOnProceed AskRelated AutoCleanCache CleanCache DefaultDistro + \ delAction delHistory Download-Only ftpProxy ftpProxyPort httpProxy + \ httpProxyPort Install-Recommends LastSearchType Maximized noProxy + \ OneClickOnStatusActions ShowAllPkgInfoInMain showWelcomeDialog + \ ToolbarState undoStackSize update upgradeType useProxy UseStatusColors + \ UseTerminal useUserFont useUserTerminalFont ViewMode + \ availVerColumnPos availVerColumnVisible componentColumnPos + \ componentColumnVisible descrColumnPos descrColumnVisible + \ downloadSizeColumnPos downloadSizeColumnVisible hpanedPos + \ instVerColumnPos instVerColumnVisible instSizeColumnPos + \ instSizeColumnVisible nameColumnPos nameColumnVisible + \ sectionColumnPos sectionColumnVisible statusColumnPos + \ statusColumnVisible supportedColumnPos supportedColumnVisible + \ vpanedPos windowWidth windowHeight windowX windowY closeZvt + \ color-available color-available-locked color-broken color-downgrade + \ color-install color-installed-locked color-installed-outdated + \ color-installed-updated color-new color-purge color-reinstall + \ color-remove color-upgrade + +syn keyword aptconfSynapticUpdate contained + \ last type + +syn cluster aptconfSynaptic_ contains=aptconfSynaptic, + \ aptconfSynapticUpdate +" }}} +" Unattended Upgrade: {{{ syn keyword aptconfUnattendedUpgrade contained - \ AutoFixInterruptedDpkg Automatic-Reboot InstallOnShutdown Mail - \ MailOnlyOnError MinimalSteps Origins-Pattern Package-Blacklist + \ AutoFixInterruptedDpkg Automatic-Reboot Automatic-Reboot-Time + \ Automatic-Reboot-WithUsers InstallOnShutdown Mail MailOnlyOnError + \ MinimalSteps Origins-Pattern Package-Blacklist \ Remove-Unused-Dependencies syn cluster aptconfUnattendedUpgrade_ contains=aptconfUnattendedUpgrade " }}} +" Whatmaps: {{{ +syn keyword aptconfWhatmaps contained + \ Enable-Restart Security-Update-Origins + +syn cluster aptconfWhatmaps_ contains=aptconfWhatmaps +" }}} syn case match " Now put all the keywords (and 'valid' options) in a single cluster: syn cluster aptconfOptions contains=aptconfRegexpOpt, - \ @aptconfAcquire_,@aptconfApt_,@aptconfAptitude_,@aptconfDebTags_, - \ @aptconfDebug_,@aptconfDir_,@aptconfDPkg_,@aptconfDSelect_, - \ @aptconfOrderList_,@aptconfPackageManager_,@aptconfPkgCacheGen_, - \ @aptconfQuiet_,@aptconfRpm_,@aptconfUnattendedUpgrade_ + \ @aptconfAcquire_,@aptconfAdequate_,@aptconfApt_,@aptconfAptitude_, + \ @aptconfAptListbugs_,@aptconfDebTags_,@aptconfDebug_,@aptconfDir_, + \ @aptconfDPkg_,@aptconfDSelect_,@aptconfOrderList_, + \ @aptconfPackageManager_,@aptconfPkgCacheGen_,@aptconfQuiet_, + \ @aptconfRpm_,@aptconfSynaptic_,@aptconfUnattendedUpgrade_, + \ @aptconfWhatmaps_ " Syntax: syn match aptconfSemiColon ';' @@ -382,8 +435,11 @@ syn region aptconfInclude matchgroup=aptconfOperator start='::' end='::\|\s'me= " Basic Syntax Errors: XXX avoid to generate false positives !!! " -" * Invalid comment format (seems to not cause errors, but...): -syn match aptconfAsError display '^#.*' +" * Undocumented inline comment. Since it is currently largely used, and does +" not seem to cause trouble ('apt-config dump' never complains when # is used +" the same way than //) it has been moved to aptconfComment group. But it +" still needs to be defined here (i.e. before #clear and #include directives) +syn match aptconfComment '#.*' contains=@aptconfCommentSpecial " " * When a semicolon is missing after a double-quoted string: " There are some cases (for example in the Dir group of options, but not only) @@ -445,6 +501,8 @@ hi def link aptconfAcquireHTTPS aptconfOption hi def link aptconfAcquireMaxValidTime aptconfOption hi def link aptconfAcquirePDiffs aptconfOption +hi def link aptconfAdequate aptconfOption + hi def link aptconfApt aptconfOption hi def link aptconfAptAuthentication aptconfOption hi def link aptconfAptAutoRemove aptconfOption @@ -471,6 +529,8 @@ hi def link aptconfAptitudeUIKeyBindings aptconfOption hi def link aptconfAptitudeUIStyles aptconfOption hi def link aptconfAptitudeUIStylesElements aptconfOption +hi def link aptconfAptListbugs aptconfOption + hi def link aptconfDebTags aptconfOption hi def link aptconfDebug aptconfOption @@ -504,8 +564,13 @@ hi def link aptconfQuiet aptconfOption hi def link aptconfRpm aptconfOption +hi def link aptconfSynaptic aptconfOption +hi def link aptconfSynapticUpdate aptconfOption + hi def link aptconfUnattendedUpgrade aptconfOption +hi def link aptconfWhatmaps aptconfOption + let b:current_syntax = "aptconf" let &cpo = s:cpo_save diff --git a/runtime/syntax/c.vim b/runtime/syntax/c.vim index ac4909edba..32b63e09e4 100644 --- a/runtime/syntax/c.vim +++ b/runtime/syntax/c.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: C " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2015 Mar 05 +" Last Change: 2016 Feb 08 " Quit when a (custom) syntax file was already loaded if exists("b:current_syntax") @@ -264,7 +264,7 @@ syn keyword cStorageClass static register auto volatile extern const if exists("c_gnu") syn keyword cStorageClass inline __attribute__ endif -if !exists("c_no_c99") +if !exists("c_no_c99") && s:ft !=# 'cpp' syn keyword cStorageClass inline restrict endif if !exists("c_no_c11") diff --git a/runtime/syntax/d.vim b/runtime/syntax/d.vim index 07a299fa55..8be9b9ff28 100644 --- a/runtime/syntax/d.vim +++ b/runtime/syntax/d.vim @@ -1,9 +1,9 @@ -" Vim syntax file for the D programming language (version 1.076 and 2.063). +" Vim syntax file for the D programming language (version 1.076 and 2.069). " " Language: D " Maintainer: Jesse Phillips <Jesse.K.Phillips+D@gmail.com> -" Last Change: 2013 October 5 -" Version: 0.26 +" Last Change: 2016 Feb 2 +" Version: 0.28 " " Contributors: " - Jason Mills: original Maintainer @@ -15,6 +15,7 @@ " - Steven N. Oliver " - Sohgo Takeuchi " - Robert Clipsham +" - Petar Kirov " " Please submit bugs/comments/suggestions to the github repo: " https://github.com/JesseKPhillips/d.vim @@ -114,17 +115,19 @@ syn keyword dTraitsIdentifier contained isIntegral isScalar isStaticArray syn keyword dTraitsIdentifier contained isUnsigned isVirtualFunction syn keyword dTraitsIdentifier contained isVirtualMethod isAbstractFunction syn keyword dTraitsIdentifier contained isFinalFunction isStaticFunction +syn keyword dTraitsIdentifier contained isOverrideFunction isTemplate syn keyword dTraitsIdentifier contained isRef isOut isLazy hasMember -syn keyword dTraitsIdentifier contained identifier getAttributes getMember -syn keyword dTraitsIdentifier contained getOverloads getProtection -syn keyword dTraitsIdentifier contained getVirtualFunctions -syn keyword dTraitsIdentifier contained getVirtualMethods parent -syn keyword dTraitsIdentifier contained classInstanceSize allMembers +syn keyword dTraitsIdentifier contained identifier getAliasThis +syn keyword dTraitsIdentifier contained getAttributes getFunctionAttributes getMember +syn keyword dTraitsIdentifier contained getOverloads getPointerBitmap getProtection +syn keyword dTraitsIdentifier contained getVirtualFunctions getVirtualIndex +syn keyword dTraitsIdentifier contained getVirtualMethods getUnitTests +syn keyword dTraitsIdentifier contained parent classInstanceSize allMembers syn keyword dTraitsIdentifier contained derivedMembers isSame compiles -syn keyword dPragmaIdentifier contained lib msg startaddress GNU_asm -syn keyword dExternIdentifier contained Windows Pascal Java System D +syn keyword dPragmaIdentifier contained inline lib mangle msg startaddress GNU_asm +syn keyword dExternIdentifier contained C C++ D Windows Pascal System Objective-C syn keyword dAttribute contained safe trusted system -syn keyword dAttribute contained property disable +syn keyword dAttribute contained property disable nogc syn keyword dVersionIdentifier contained DigitalMars GNU LDC SDC D_NET syn keyword dVersionIdentifier contained X86 X86_64 ARM PPC PPC64 IA64 MIPS MIPS64 Alpha syn keyword dVersionIdentifier contained SPARC SPARC64 S390 S390X HPPA HPPA64 SH SH64 @@ -134,7 +137,7 @@ syn keyword dVersionIdentifier contained Cygwin MinGW syn keyword dVersionIdentifier contained LittleEndian BigEndian syn keyword dVersionIdentifier contained D_InlineAsm_X86 D_InlineAsm_X86_64 syn keyword dVersionIdentifier contained D_Version2 D_Coverage D_Ddoc D_LP64 D_PIC -syn keyword dVersionIdentifier contained unittest none all +syn keyword dVersionIdentifier contained unittest assert none all syn cluster dComment contains=dNestedComment,dBlockComment,dLineComment @@ -168,10 +171,10 @@ syn match dExternal "\<extern\>" syn match dExtern "\<extern\s*([_a-zA-Z][_a-zA-Z0-9\+]*\>"he=s+6 contains=dExternIdentifier " Make import a region to prevent highlighting keywords -syn region dImport start="import\_s" end=";" contains=dExternal,@dComment +syn region dImport start="\<import\_s" end=";" contains=dExternal,@dComment " Make module a region to prevent highlighting keywords -syn region dImport start="module\_s" end=";" contains=dExternal,@dComment +syn region dImport start="\<module\_s" end=";" contains=dExternal,@dComment " dTokens is used by the token string highlighting syn cluster dTokens contains=dExternal,dConditional,dBranch,dRepeat,dBoolean @@ -246,13 +249,17 @@ syn match dUnicode "\\u\d\{4\}" " String. " -syn region dString start=+"+ end=+"[cwd]\=+ skip=+\\\\\|\\"+ contains=dEscSequence,@Spell +syn match dFormat display "%\(\d\+\$\)\=[-+' #0*]*\(\d*\|\*\|\*\d\+\$\)\(\.\(\d*\|\*\|\*\d\+\$\)\)\=\([hlL]\|ll\)\=\([bdiuoxXDOUfeEgGcCsSpn]\|\[\^\=.[^]]*\]\)" contained +syn match dFormat display "%%" contained + +syn region dString start=+"+ end=+"[cwd]\=+ skip=+\\\\\|\\"+ contains=dFormat,dEscSequence,@Spell syn region dRawString start=+`+ end=+`[cwd]\=+ contains=@Spell syn region dRawString start=+r"+ end=+"[cwd]\=+ contains=@Spell syn region dHexString start=+x"+ end=+"[cwd]\=+ contains=@Spell syn region dDelimString start=+q"\z(.\)+ end=+\z1"+ contains=@Spell syn region dHereString start=+q"\z(\I\i*\)\n+ end=+^\z1"+ contains=@Spell + " Nesting delimited string contents " syn region dNestParenString start=+(+ end=+)+ contained transparent contains=dNestParenString,@Spell @@ -276,8 +283,8 @@ syn cluster dTokens add=dString,dRawString,dHexString,dDelimString,dNestString " Token strings " -syn region dNestTokenString start=+{+ end=+}+ contained contains=dNestTokenString,@dTokens -syn region dTokenString matchgroup=dTokenStringBrack transparent start=+q{+ end=+}+ contains=dNestTokenString,@dTokens +syn region dNestTokenString start=+{+ end=+}+ contained contains=dNestTokenString,@dTokens,dFormat +syn region dTokenString matchgroup=dTokenStringBrack transparent start=+q{+ end=+}+ contains=dNestTokenString,@dTokens,dFormat syn cluster dTokens add=dTokenString @@ -357,6 +364,7 @@ hi def link dString String hi def link dHexString String hi def link dCharacter Character hi def link dEscSequence SpecialChar +hi def link dFormat SpecialChar hi def link dSpecialCharError Error hi def link dOctalError Error hi def link dOperator Operator diff --git a/runtime/syntax/dcl.vim b/runtime/syntax/dcl.vim index 37bf38fe11..b08adec31d 100644 --- a/runtime/syntax/dcl.vim +++ b/runtime/syntax/dcl.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: DCL (Digital Command Language - vms) " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Oct 23, 2014 -" Version: 7 +" Last Change: Jan 20, 2016 +" Version: 8 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_DCL " For version 5.x: Clear all syntax items @@ -13,10 +13,10 @@ elseif exists("b:current_syntax") finish endif -if version < 600 - set iskeyword=$,@,48-57,_ -else +if !has("patch-7.4.1141") setlocal iskeyword=$,@,48-57,_ +else + syn iskeyword $,@,48-57,_ endif syn case ignore diff --git a/runtime/syntax/lisp.vim b/runtime/syntax/lisp.vim index 2528f4f9b1..f496398d50 100644 --- a/runtime/syntax/lisp.vim +++ b/runtime/syntax/lisp.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: Lisp " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Oct 06, 2014 -" Version: 23 +" Last Change: Jan 20, 2016 +" Version: 24 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_LISP " " Thanks to F Xavier Noria for a list of 978 Common Lisp symbols taken from HyperSpec @@ -16,8 +16,10 @@ endif if exists("g:lisp_isk") exe "setl isk=".g:lisp_isk -else +elseif !has("patch-7.4.1141") setl isk=38,42,43,45,47-58,60-62,64-90,97-122,_ +else + syn iskeyword 38,42,43,45,47-58,60-62,64-90,97-122,_ endif if exists("g:lispsyntax_ignorecase") || exists("g:lispsyntax_clisp") diff --git a/runtime/syntax/maple.vim b/runtime/syntax/maple.vim index 9c94643836..9a4db26dd8 100644 --- a/runtime/syntax/maple.vim +++ b/runtime/syntax/maple.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: Maple V (based on release 4) " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Oct 23, 2014 -" Version: 11 +" Last Change: Jan 20, 2016 +" Version: 12 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_MAPLE " " Package Function Selection: {{{1 @@ -30,10 +30,10 @@ elseif exists("b:current_syntax") endif " Iskeyword Effects: {{{1 -if version < 600 - set iskeyword=$,48-57,_,a-z,@-Z +if !has("patch-7.4.1141") + setl isk=$,48-57,_,a-z,@-Z else - setlocal iskeyword=$,48-57,_,a-z,@-Z + syn iskeyword $,48-57,_,a-z,@-Z endif " Package Selection: {{{1 diff --git a/runtime/syntax/messages.vim b/runtime/syntax/messages.vim index 4648e94c13..c22e4e8d0c 100644 --- a/runtime/syntax/messages.vim +++ b/runtime/syntax/messages.vim @@ -3,6 +3,7 @@ " Maintainer: Yakov Lerner <iler.ml@gmail.com> " Latest Revision: 2008-06-29 " Changes: 2008-06-29 support for RFC3339 tuimestamps James Vega +" 2016 Jan 19: messagesDate changed by Bram if exists("b:current_syntax") finish @@ -13,7 +14,7 @@ set cpo&vim syn match messagesBegin display '^' nextgroup=messagesDate,messagesDateRFC3339 -syn match messagesDate contained display '\a\a\a [ 0-9]\d *' +syn match messagesDate contained display '[[:lower:][:upper:]][[:lower:][:upper:]][[:lower:][:upper:]] [ 0-9]\d *' \ nextgroup=messagesHour syn match messagesHour contained display '\d\d:\d\d:\d\d\s*' diff --git a/runtime/syntax/rst.vim b/runtime/syntax/rst.vim index 8b17104be4..b3c89f8352 100644 --- a/runtime/syntax/rst.vim +++ b/runtime/syntax/rst.vim @@ -2,7 +2,7 @@ " Language: reStructuredText documentation format " Maintainer: Marshall Ward <marshall.ward@gmail.com> " Previous Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2015-09-07 +" Latest Revision: 2016-01-05 if exists("b:current_syntax") finish @@ -13,8 +13,6 @@ set cpo&vim syn case ignore -syn match rstSections "^\%(\([=`:.'"~^_*+#-]\)\1\+\n\)\=.\+\n\([=`:.'"~^_*+#-]\)\2\+$" - syn match rstTransition /^[=`:.'"~^_*+#-]\{4,}\s*$/ syn cluster rstCruft contains=rstEmphasis,rstStrongEmphasis, @@ -123,6 +121,8 @@ call s:DefineInlineMarkup('InlineLiteral', '``', "", '``') call s:DefineInlineMarkup('SubstitutionReference', '|', '|', '|_\{0,2}') call s:DefineInlineMarkup('InlineInternalTargets', '_`', '`', '`') +syn match rstSections "^\%(\([=`:.'"~^_*+#-]\)\1\+\n\)\=.\+\n\([=`:.'"~^_*+#-]\)\2\+$" + " TODO: Can’t remember why these two can’t be defined like the ones above. execute 'syn match rstFootnoteReference contains=@NoSpell' . \ ' +\[\%(\d\+\|#\%(' . s:ReferenceName . '\)\=\|\*\)\]_+' diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim index efe0bcb461..15a00eb516 100644 --- a/runtime/syntax/sh.vim +++ b/runtime/syntax/sh.vim @@ -2,8 +2,8 @@ " Language: shell (sh) Korn shell (ksh) bash (sh) " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> " Previous Maintainer: Lennart Schultz <Lennart.Schultz@ecmwf.int> -" Last Change: Nov 09, 2015 -" Version: 142 +" Last Change: Feb 16, 2016 +" Version: 144 " 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) @@ -85,6 +85,11 @@ if g:sh_fold_enabled && &fdm == "manual" setl fdm=syntax endif +" set up the syntax-highlighting iskeyword +if has("patch-7.4.1141") + exe "syn iskeyword ".&iskeyword.",-" +endif + " Set up folding commands for shell {{{1 " ================================= if s:sh_fold_functions @@ -119,7 +124,7 @@ syn cluster shCaseList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSu syn cluster shCommandSubList contains=shAlias,shArithmetic,shComment,shCmdParenRegion,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shEcho,shEscape,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shOption,shPosnParm,shSingleQuote,shSpecial,shStatement,shSubSh,shTest,shVariable syn cluster shCurlyList contains=shNumber,shComma,shDeref,shDerefSimple,shDerefSpecial syn cluster shDblQuoteList contains=shCommandSub,shDeref,shDerefSimple,shEscape,shPosnParm,shCtrlSeq,shSpecial -syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPPS +syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPSR,shDerefPPS syn cluster shDerefVarList contains=shDerefOp,shDerefVarArray,shDerefOpError syn cluster shEchoList contains=shArithmetic,shCommandSub,shDeref,shDerefSimple,shEscape,shExpr,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq,shEchoQuote syn cluster shExprList1 contains=shCharClass,shNumber,shOperator,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shDblBrace,shDeref,shDerefSimple,shCtrlSeq @@ -493,6 +498,11 @@ if exists("b:is_bash") syn match shDerefPPS contained '/\{1,2}' nextgroup=shDerefPPSleft syn region shDerefPPSleft contained start='.' skip=@\%(\\\\\)*\\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPPSright contains=@shCommandSubList syn region shDerefPPSright contained start='.' skip=@\%(\\\\\)\+@ end='\ze}' contains=@shCommandSubList + + " bash : ${parameter/#substring/replacement} + syn match shDerefPSR contained '/#' nextgroup=shDerefPSRleft + syn region shDerefPSRleft contained start='.' skip=@\%(\\\\\)*\\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPSRright + syn region shDerefPSRright contained start='.' skip=@\%(\\\\\)\+@ end='\ze}' endif " Arithmetic Parenthesized Expressions: {{{1 @@ -563,6 +573,7 @@ hi def link shColon shComment hi def link shDerefOp shOperator hi def link shDerefPOL shDerefOp hi def link shDerefPPS shDerefOp +hi def link shDerefPSR shDerefOp hi def link shDeref shShellVariables hi def link shDerefDelim shOperator hi def link shDerefSimple shDeref diff --git a/runtime/syntax/sshconfig.vim b/runtime/syntax/sshconfig.vim index 479277e17f..ef2ca07976 100644 --- a/runtime/syntax/sshconfig.vim +++ b/runtime/syntax/sshconfig.vim @@ -2,9 +2,10 @@ " Language: OpenSSH client configuration file (ssh_config) " Author: David Necas (Yeti) " Maintainer: Dominik Fischer <d dot f dot fischer at web dot de> -" Contributor: Leonard Ehrenfried <leonard.ehrenfried@web.de> -" Last Change: 2015 Dec 3 -" SSH Version: 7.0 +" Contributor: Leonard Ehrenfried <leonard.ehrenfried@web.de> +" Contributor: Karsten Hopp <karsten@redhat.com> +" Last Change: 2016 Jan 15 +" SSH Version: 7.1 " " Setup @@ -69,8 +70,8 @@ syn keyword sshconfigSysLogFacility DAEMON USER AUTH AUTHPRIV LOCAL0 LOCAL1 syn keyword sshconfigSysLogFacility LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7 syn keyword sshconfigAddressFamily inet inet6 -syn match sshconfigIPQoS "af1[1234]" -syn match sshconfigIPQoS "af2[23]" +syn match sshconfigIPQoS "af1[123]" +syn match sshconfigIPQoS "af2[123]" syn match sshconfigIPQoS "af3[123]" syn match sshconfigIPQoS "af4[123]" syn match sshconfigIPQoS "cs[0-7]" @@ -106,6 +107,10 @@ syn keyword sshconfigMatch canonical exec host originalhost user localuser all syn keyword sshconfigKeyword AddressFamily syn keyword sshconfigKeyword BatchMode syn keyword sshconfigKeyword BindAddress +syn keyword sshconfigKeyword CanonicalDomains +syn keyword sshconfigKeyword CanonicalizeFallbackLocal +syn keyword sshconfigKeyword CanonicalizeHostname +syn keyword sshconfigKeyword CanonicalizeMaxDots syn keyword sshconfigKeyword ChallengeResponseAuthentication syn keyword sshconfigKeyword CheckHostIP syn keyword sshconfigKeyword Cipher @@ -145,6 +150,8 @@ syn keyword sshconfigKeyword HostbasedKeyTypes syn keyword sshconfigKeyword IPQoS syn keyword sshconfigKeyword IdentitiesOnly syn keyword sshconfigKeyword IdentityFile +syn keyword sshconfigKeyword IgnoreUnknown +syn keyword sshconfigKeyword IPQoS syn keyword sshconfigKeyword KbdInteractiveAuthentication syn keyword sshconfigKeyword KbdInteractiveDevices syn keyword sshconfigKeyword KexAlgorithms @@ -182,6 +189,7 @@ syn keyword sshconfigKeyword UseBlacklistedKeys syn keyword sshconfigKeyword UsePrivilegedPort syn keyword sshconfigKeyword User syn keyword sshconfigKeyword UserKnownHostsFile +syn keyword sshconfigKeyword UseRoaming syn keyword sshconfigKeyword VerifyHostKeyDNS syn keyword sshconfigKeyword VisualHostKey syn keyword sshconfigKeyword XAuthLocation diff --git a/runtime/syntax/sshdconfig.vim b/runtime/syntax/sshdconfig.vim index ac90a80aa5..4203047d2c 100644 --- a/runtime/syntax/sshdconfig.vim +++ b/runtime/syntax/sshdconfig.vim @@ -4,9 +4,10 @@ " Maintainer: Dominik Fischer <d dot f dot fischer at web dot de> " Contributor: Thilo Six " Contributor: Leonard Ehrenfried <leonard.ehrenfried@web.de> +" Contributor: Karsten Hopp <karsten@redhat.com> " Originally: 2009-07-09 -" Last Change: 2015 Dec 3 -" SSH Version: 7.0 +" Last Change: 2016 Jan 12 +" SSH Version: 7.1 " " Setup @@ -65,8 +66,8 @@ syn keyword sshdconfigSysLogFacility LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7 syn keyword sshdconfigCompression delayed -syn match sshdconfigIPQoS "af1[1234]" -syn match sshdconfigIPQoS "af2[23]" +syn match sshdconfigIPQoS "af1[123]" +syn match sshdconfigIPQoS "af2[123]" syn match sshdconfigIPQoS "af3[123]" syn match sshdconfigIPQoS "af4[123]" syn match sshdconfigIPQoS "cs[0-7]" @@ -109,6 +110,7 @@ syn keyword sshdconfigKeyword AllowGroups syn keyword sshdconfigKeyword AllowStreamLocalForwarding syn keyword sshdconfigKeyword AllowTcpForwarding syn keyword sshdconfigKeyword AllowUsers +syn keyword sshdconfigKeyword AuthenticationMethods syn keyword sshdconfigKeyword AuthorizedKeysFile syn keyword sshdconfigKeyword AuthorizedKeysCommand syn keyword sshdconfigKeyword AuthorizedKeysCommandUser @@ -132,6 +134,7 @@ syn keyword sshdconfigKeyword GSSAPIStrictAcceptorCheck syn keyword sshdconfigKeyword GatewayPorts syn keyword sshdconfigKeyword HostCertificate syn keyword sshdconfigKeyword HostKey +syn keyword sshdconfigKeyword HostKeyAgent syn keyword sshdconfigKeyword HostKeyAlgorithms syn keyword sshdconfigKeyword HostbasedAcceptedKeyTypes syn keyword sshdconfigKeyword HostbasedAuthentication diff --git a/runtime/syntax/tex.vim b/runtime/syntax/tex.vim index d31e14bed0..40013b5b99 100644 --- a/runtime/syntax/tex.vim +++ b/runtime/syntax/tex.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: TeX " Maintainer: Charles E. Campbell <NdrchipO@ScampbellPfamily.AbizM> -" Last Change: Oct 20, 2015 -" Version: 90 +" Last Change: Jan 20, 2016 +" Version: 91 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_TEX " " Notes: {{{1 @@ -129,8 +129,10 @@ endif " g:tex_isk if exists("g:tex_isk") exe "setlocal isk=".g:tex_isk +elseif !has("patch-7.4.1141") + setl isk=48-57,a-z,A-Z,192-255 else - setlocal isk=48-57,a-z,A-Z,192-255 + syn iskeyword 48-57,a-z,A-Z,192-255 endif if b:tex_stylish setlocal isk+=@-@ diff --git a/runtime/syntax/zsh.vim b/runtime/syntax/zsh.vim index 162577669f..25d4cd4936 100644 --- a/runtime/syntax/zsh.vim +++ b/runtime/syntax/zsh.vim @@ -2,7 +2,7 @@ " Language: Zsh shell script " Maintainer: Christian Brabandt <cb@256bit.org> " Previous Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2015-12-25 +" Latest Revision: 2016-01-25 " License: Vim (see :h license) " Repository: https://github.com/chrisbra/vim-zsh @@ -14,6 +14,7 @@ let s:cpo_save = &cpo set cpo&vim setlocal iskeyword+=- +setlocal foldmethod=syntax syn keyword zshTodo contained TODO FIXME XXX NOTE @@ -307,19 +308,19 @@ syn match zshNumber '[+-]\=\d\+\.\d\+\>' " TODO: $[...] is the same as $((...)), so add that as well. syn cluster zshSubst contains=zshSubst,zshOldSubst,zshMathSubst syn region zshSubst matchgroup=zshSubstDelim transparent - \ start='\$(' skip='\\)' end=')' contains=TOP -syn region zshParentheses transparent start='(' skip='\\)' end=')' + \ start='\$(' skip='\\)' end=')' contains=TOP fold +syn region zshParentheses transparent start='(' skip='\\)' end=')' fold syn region zshMathSubst matchgroup=zshSubstDelim transparent \ start='\$((' skip='\\)' \ matchgroup=zshSubstDelim end='))' \ contains=zshParentheses,@zshSubst,zshNumber, - \ @zshDerefs,zshString keepend + \ @zshDerefs,zshString keepend fold syn region zshBrackets contained transparent start='{' skip='\\}' - \ end='}' + \ end='}' fold syn region zshSubst matchgroup=zshSubstDelim start='\${' skip='\\}' - \ end='}' contains=@zshSubst,zshBrackets,zshQuoted,zshString + \ end='}' contains=@zshSubst,zshBrackets,zshQuoted,zshString fold syn region zshOldSubst matchgroup=zshSubstDelim start=+`+ skip=+\\`+ - \ end=+`+ contains=TOP,zshOldSubst + \ end=+`+ contains=TOP,zshOldSubst fold syn sync minlines=50 maxlines=90 syn sync match zshHereDocSync grouphere NONE '<<-\=\s*\%(\\\=\S\+\|\(["']\)\S\+\1\)' diff --git a/scripts/gendeclarations.lua b/scripts/gendeclarations.lua index 4e74e4e301..ff69b18ae4 100755 --- a/scripts/gendeclarations.lua +++ b/scripts/gendeclarations.lua @@ -143,7 +143,7 @@ local pattern = concat( lit(')'), any_amount(concat( -- optional attributes spaces, - lit('FUNC_ATTR_'), + lit('FUNC_'), any_amount(aw), one_or_no(concat( -- attribute argument spaces, diff --git a/scripts/msgpack-gen.lua b/scripts/msgpack-gen.lua index c726db3920..2da3c174f9 100644 --- a/scripts/msgpack-gen.lua +++ b/scripts/msgpack-gen.lua @@ -35,7 +35,8 @@ c_proto = Ct( Cg(c_type, 'return_type') * Cg(c_id, 'name') * fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * Cg(Cc(false), 'async') * - (fill * Cg((P('FUNC_ATTR_ASYNC') * Cc(true)), 'async') ^ -1) * + (fill * Cg((P('FUNC_API_ASYNC') * Cc(true)), 'async') ^ -1) * + (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) * fill * P(';') ) grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) @@ -44,7 +45,7 @@ grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) assert(#arg >= 1) functions = {} --- names of all headers relative to the source root(for inclusion in the +-- names of all headers relative to the source root (for inclusion in the -- generated file) headers = {} -- output file(dispatch function + metadata serialized with msgpack) @@ -62,20 +63,22 @@ for i = 1, #arg - 1 do local input = io.open(full_path, 'rb') local tmp = grammar:match(input:read('*all')) for i = 1, #tmp do - functions[#functions + 1] = tmp[i] local fn = tmp[i] - if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then - -- this function should receive the channel id - fn.receives_channel_id = true - -- remove the parameter since it won't be passed by the api client - table.remove(fn.parameters, 1) - end - if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'error' then - -- function can fail if the last parameter type is 'Error' - fn.can_fail = true - -- remove the error parameter, msgpack has it's own special field - -- for specifying errors - fn.parameters[#fn.parameters] = nil + if not fn.noexport then + functions[#functions + 1] = tmp[i] + if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then + -- this function should receive the channel id + fn.receives_channel_id = true + -- remove the parameter since it won't be passed by the api client + table.remove(fn.parameters, 1) + end + if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'error' then + -- function can fail if the last parameter type is 'Error' + fn.can_fail = true + -- remove the error parameter, msgpack has it's own special field + -- for specifying errors + fn.parameters[#fn.parameters] = nil + end end end input:close() @@ -217,7 +220,7 @@ for i = 1, #functions do if fn.receives_channel_id then -- if the function receives the channel id, pass it as first argument - if #args > 0 then + if #args > 0 or fn.can_fail then output:write('channel_id, '..call_args) else output:write('channel_id') diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index 7a0001769a..a40090d4c3 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -92,7 +92,7 @@ commit_message() { find_git_remote() { git remote -v \ - | awk '$2 ~ /github.com[:/]neovim\/neovim/ && $3 == "(fetch)" {print $1}' + | awk '$2 ~ /github.com[:\/]neovim\/neovim/ && $3 == "(fetch)" {print $1; exit}' } assign_commit_details() { diff --git a/.asan-blacklist b/src/.asan-blacklist index 63558170b3..63558170b3 100644 --- a/.asan-blacklist +++ b/src/.asan-blacklist diff --git a/.valgrind.supp b/src/.valgrind.supp index 8b630fcaaf..8b630fcaaf 100644 --- a/.valgrind.supp +++ b/src/.valgrind.supp diff --git a/Doxyfile b/src/Doxyfile index de31c8355f..de31c8355f 100644 --- a/Doxyfile +++ b/src/Doxyfile diff --git a/clint.py b/src/clint.py index c19ba4b7ae..c19ba4b7ae 100755 --- a/clint.py +++ b/src/clint.py diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 172643091a..4aaae5172f 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -55,6 +55,10 @@ foreach(subdir event eval ) + if(${subdir} MATCHES "tui" AND NOT FEAT_TUI) + continue() + endif() + file(MAKE_DIRECTORY ${GENERATED_DIR}/${subdir}) file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/${subdir}) file(GLOB sources ${subdir}/*.c) @@ -74,6 +78,9 @@ foreach(sfile ${NEOVIM_SOURCES}) if(${f} MATCHES "^(regexp_nfa.c)$") list(APPEND to_remove ${sfile}) endif() + if(WIN32 AND ${f} MATCHES "^(pty_process_unix.c)$") + list(APPEND to_remove ${sfile}) + endif() endforeach() list(REMOVE_ITEM NEOVIM_SOURCES ${to_remove}) @@ -265,7 +272,7 @@ if(CLANG_ASAN_UBSAN) set(SANITIZE_RECOVER -fno-sanitize-recover) # Clang 3.5- endif() set_property(TARGET nvim APPEND_STRING PROPERTY COMPILE_FLAGS "-DEXITFREE ") - set_property(TARGET nvim APPEND_STRING PROPERTY COMPILE_FLAGS "${SANITIZE_RECOVER} -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=address -fsanitize=undefined -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/.asan-blacklist") + set_property(TARGET nvim APPEND_STRING PROPERTY COMPILE_FLAGS "${SANITIZE_RECOVER} -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=address -fsanitize=undefined -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/src/.asan-blacklist") set_property(TARGET nvim APPEND_STRING PROPERTY LINK_FLAGS "-fsanitize=address -fsanitize=undefined ") elseif(CLANG_MSAN) message(STATUS "Enabling Clang memory sanitizer for nvim.") diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index a0f14ac7a4..7ed726c7ce 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -62,12 +62,10 @@ #define NIL ((Object) {.type = kObjectTypeNil}) #define PUT(dict, k, v) \ - kv_push(KeyValuePair, \ - dict, \ - ((KeyValuePair) {.key = cstr_to_string(k), .value = v})) + kv_push(dict, ((KeyValuePair) { .key = cstr_to_string(k), .value = v })) #define ADD(array, item) \ - kv_push(Object, array, item) + kv_push(array, item) #define STATIC_CSTR_AS_STRING(s) ((String) {.data = s, .size = sizeof(s) - 1}) diff --git a/src/nvim/msgpack_rpc/remote_ui.c b/src/nvim/api/ui.c index 6ffcffe2e1..1703d49296 100644 --- a/src/nvim/msgpack_rpc/remote_ui.c +++ b/src/nvim/api/ui.c @@ -7,13 +7,12 @@ #include "nvim/ui.h" #include "nvim/memory.h" #include "nvim/map.h" -#include "nvim/msgpack_rpc/remote_ui.h" #include "nvim/msgpack_rpc/channel.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #ifdef INCLUDE_GENERATED_DECLARATIONS -# include "msgpack_rpc/remote_ui.c.generated.h" +# include "api/ui.c.generated.h" #endif typedef struct { @@ -24,21 +23,13 @@ typedef struct { static PMap(uint64_t) *connected_uis = NULL; void remote_ui_init(void) + FUNC_API_NOEXPORT { connected_uis = pmap_new(uint64_t)(); - // Add handler for "attach_ui" - String method = cstr_as_string("ui_attach"); - MsgpackRpcRequestHandler handler = {.fn = remote_ui_attach, .async = false}; - msgpack_rpc_add_method_handler(method, handler); - method = cstr_as_string("ui_detach"); - handler.fn = remote_ui_detach; - msgpack_rpc_add_method_handler(method, handler); - method = cstr_as_string("ui_try_resize"); - handler.fn = remote_ui_try_resize; - msgpack_rpc_add_method_handler(method, handler); } void remote_ui_disconnect(uint64_t channel_id) + FUNC_API_NOEXPORT { UI *ui = pmap_get(uint64_t)(connected_uis, channel_id); if (!ui) { @@ -49,34 +40,30 @@ void remote_ui_disconnect(uint64_t channel_id) api_free_array(data->buffer); pmap_del(uint64_t)(connected_uis, channel_id); xfree(ui->data); - ui_detach(ui); + ui_detach_impl(ui); xfree(ui); } -static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, - Array args, Error *error) +void ui_attach(uint64_t channel_id, Integer width, Integer height, + Boolean enable_rgb, Error *err) { if (pmap_has(uint64_t)(connected_uis, channel_id)) { - api_set_error(error, Exception, _("UI already attached for channel")); - return NIL; + api_set_error(err, Exception, _("UI already attached for channel")); + return; } - if (args.size != 3 || args.items[0].type != kObjectTypeInteger - || args.items[1].type != kObjectTypeInteger - || args.items[2].type != kObjectTypeBoolean - || args.items[0].data.integer <= 0 || args.items[1].data.integer <= 0) { - api_set_error(error, Validation, - _("Invalid arguments. Expected: " - "(uint width > 0, uint height > 0, bool enable_rgb)")); - return NIL; + if (width <= 0 || height <= 0) { + api_set_error(err, Validation, + _("Expected width > 0 and height > 0")); + return; } UIData *data = xmalloc(sizeof(UIData)); data->channel_id = channel_id; data->buffer = (Array)ARRAY_DICT_INIT; UI *ui = xcalloc(1, sizeof(UI)); - ui->width = (int)args.items[0].data.integer; - ui->height = (int)args.items[1].data.integer; - ui->rgb = args.items[2].data.boolean; + ui->width = (int)width; + ui->height = (int)height; + ui->rgb = enable_rgb; ui->data = data; ui->resize = remote_ui_resize; ui->clear = remote_ui_clear; @@ -102,45 +89,38 @@ static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, ui->set_title = remote_ui_set_title; ui->set_icon = remote_ui_set_icon; pmap_put(uint64_t)(connected_uis, channel_id, ui); - ui_attach(ui); - return NIL; + ui_attach_impl(ui); + return; } -static Object remote_ui_detach(uint64_t channel_id, uint64_t request_id, - Array args, Error *error) +void ui_detach(uint64_t channel_id, Error *err) { if (!pmap_has(uint64_t)(connected_uis, channel_id)) { - api_set_error(error, Exception, _("UI is not attached for channel")); + api_set_error(err, Exception, _("UI is not attached for channel")); } remote_ui_disconnect(channel_id); - - return NIL; } -static Object remote_ui_try_resize(uint64_t channel_id, uint64_t request_id, - Array args, Error *error) +Object ui_try_resize(uint64_t channel_id, Integer width, + Integer height, Error *err) { if (!pmap_has(uint64_t)(connected_uis, channel_id)) { - api_set_error(error, Exception, _("UI is not attached for channel")); + api_set_error(err, Exception, _("UI is not attached for channel")); } - if (args.size != 2 || args.items[0].type != kObjectTypeInteger - || args.items[1].type != kObjectTypeInteger - || args.items[0].data.integer <= 0 || args.items[1].data.integer <= 0) { - api_set_error(error, Validation, - _("Invalid arguments. Expected: " - "(uint width > 0, uint height > 0)")); + if (width <= 0 || height <= 0) { + api_set_error(err, Validation, + _("Expected width > 0 and height > 0")); return NIL; } UI *ui = pmap_get(uint64_t)(connected_uis, channel_id); - ui->width = (int)args.items[0].data.integer; - ui->height = (int)args.items[1].data.integer; + ui->width = (int)width; + ui->height = (int)height; ui_refresh(); return NIL; } - static void push_call(UI *ui, char *name, Array args) { Array call = ARRAY_DICT_INIT; @@ -236,7 +216,7 @@ static void remote_ui_mode_change(UI *ui, int mode) } static void remote_ui_set_scroll_region(UI *ui, int top, int bot, int left, - int right) + int right) { Array args = ARRAY_DICT_INIT; ADD(args, INTEGER_OBJ(top)); @@ -297,7 +277,7 @@ static void remote_ui_highlight_set(UI *ui, HlAttrs attrs) static void remote_ui_put(UI *ui, uint8_t *data, size_t size) { Array args = ARRAY_DICT_INIT; - String str = {.data = xmemdupz(data, size), .size = size}; + String str = { .data = xmemdupz(data, size), .size = size }; ADD(args, STRING_OBJ(str)); push_call(ui, "put", args); } diff --git a/src/nvim/api/ui.h b/src/nvim/api/ui.h new file mode 100644 index 0000000000..b3af14f8a8 --- /dev/null +++ b/src/nvim/api/ui.h @@ -0,0 +1,11 @@ +#ifndef NVIM_API_UI_H +#define NVIM_API_UI_H + +#include <stdint.h> + +#include "nvim/api/private/defs.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "api/ui.h.generated.h" +#endif +#endif // NVIM_API_UI_H diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 46ac3c9022..43d58a539a 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -57,6 +57,7 @@ void vim_feedkeys(String keys, String mode, Boolean escape_csi) bool remap = true; bool insert = false; bool typed = false; + bool execute = false; if (keys.size == 0) { return; @@ -68,6 +69,7 @@ void vim_feedkeys(String keys, String mode, Boolean escape_csi) case 'm': remap = true; break; case 't': typed = true; break; case 'i': insert = true; break; + case 'x': execute = true; break; } } @@ -86,8 +88,12 @@ void vim_feedkeys(String keys, String mode, Boolean escape_csi) xfree(keys_esc); } - if (vgetc_busy) + if (vgetc_busy) { typebuf_was_filled = true; + } + if (execute) { + exec_normal(true); + } } /// Passes input keys to Neovim. Unlike `vim_feedkeys`, this will use a @@ -98,7 +104,7 @@ void vim_feedkeys(String keys, String mode, Boolean escape_csi) /// @return The number of bytes actually written, which can be lower than /// requested if the buffer becomes full. Integer vim_input(String keys) - FUNC_ATTR_ASYNC + FUNC_API_ASYNC { return (Integer)input_enqueue(keys); } @@ -618,7 +624,7 @@ Dictionary vim_get_color_map(void) Array vim_get_api_info(uint64_t channel_id) - FUNC_ATTR_ASYNC + FUNC_API_ASYNC { Array rv = ARRAY_DICT_INIT; diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 72716daf0e..71ec20c788 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1534,6 +1534,7 @@ void free_buf_options(buf_T *buf, int free_p_ff) clear_string_option(&buf->b_p_cms); clear_string_option(&buf->b_p_nf); clear_string_option(&buf->b_p_syn); + clear_string_option(&buf->b_s.b_syn_isk); clear_string_option(&buf->b_s.b_p_spc); clear_string_option(&buf->b_s.b_p_spf); vim_regfree(buf->b_s.b_cap_prog); @@ -4950,7 +4951,7 @@ int bufhl_add_hl(buf_T *buf, bufhl_vec_T* lineinfo = map_ref(linenr_T, bufhl_vec_T)(buf->b_bufhl_info, lnum, true); - bufhl_hl_item_T *hlentry = kv_pushp(bufhl_hl_item_T, *lineinfo); + bufhl_hl_item_T *hlentry = kv_pushp(*lineinfo); hlentry->src_id = src_id; hlentry->hl_id = hl_id; hlentry->start = col_start; diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 0324f6b88a..b515c4e1e4 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -438,15 +438,17 @@ typedef struct { linenr_T b_sst_check_lnum; uint16_t b_sst_lasttick; /* last display tick */ - /* for spell checking */ - garray_T b_langp; /* list of pointers to slang_T, see spell.c */ - bool b_spell_ismw[256]; /* flags: is midword char */ - char_u *b_spell_ismw_mb; /* multi-byte midword chars */ - char_u *b_p_spc; /* 'spellcapcheck' */ - regprog_T *b_cap_prog; /* program for 'spellcapcheck' */ - char_u *b_p_spf; /* 'spellfile' */ - char_u *b_p_spl; /* 'spelllang' */ - int b_cjk; /* all CJK letters as OK */ + // for spell checking + garray_T b_langp; // list of pointers to slang_T, see spell.c + bool b_spell_ismw[256]; // flags: is midword char + char_u *b_spell_ismw_mb; // multi-byte midword chars + char_u *b_p_spc; // 'spellcapcheck' + regprog_T *b_cap_prog; // program for 'spellcapcheck' + char_u *b_p_spf; // 'spellfile' + char_u *b_p_spl; // 'spelllang' + int b_cjk; // all CJK letters as OK + char_u b_syn_chartab[32]; // syntax iskeyword option + char_u *b_syn_isk; // iskeyword option } synblock_T; diff --git a/src/nvim/edit.c b/src/nvim/edit.c index e131da8fe0..44aaedb9b4 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -961,7 +961,7 @@ static int insert_handle_key(InsertState *s) break; case K_EVENT: // some event - queue_process_events(loop.events); + queue_process_events(main_loop.events); break; case K_FOCUSGAINED: // Neovim has been given focus diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 201a71facb..d8f1ce8494 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -67,6 +67,7 @@ #include "nvim/syntax.h" #include "nvim/tag.h" #include "nvim/ui.h" +#include "nvim/main.h" #include "nvim/mouse.h" #include "nvim/terminal.h" #include "nvim/undo.h" @@ -76,9 +77,10 @@ #include "nvim/eval/decode.h" #include "nvim/os/os.h" #include "nvim/event/libuv_process.h" -#include "nvim/event/pty_process.h" +#include "nvim/os/pty_process.h" #include "nvim/event/rstream.h" #include "nvim/event/wstream.h" +#include "nvim/event/time.h" #include "nvim/os/time.h" #include "nvim/msgpack_rpc/channel.h" #include "nvim/msgpack_rpc/server.h" @@ -428,6 +430,14 @@ typedef struct { int status; } JobEvent; +typedef struct { + TimeWatcher tw; + int timer_id; + int repeat_count; + bool stopped; + ufunc_T *callback; +} timer_T; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval.c.generated.h" #endif @@ -438,6 +448,9 @@ typedef struct { static uint64_t current_job_id = 1; static PMap(uint64_t) *jobs = NULL; +static uint64_t last_timer_id = 0; +static PMap(uint64_t) *timers = NULL; + static const char *const msgpack_type_names[] = { [kMPNil] = "nil", [kMPBoolean] = "boolean", @@ -469,6 +482,7 @@ void eval_init(void) vimvars[VV_VERSION].vv_nr = VIM_VERSION_100; jobs = pmap_new(uint64_t)(); + timers = pmap_new(uint64_t)(); struct vimvar *p; init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE); @@ -494,6 +508,7 @@ void eval_init(void) /* add to compat scope dict */ hash_add(&compat_hashtab, p->vv_di.di_key); } + vimvars[VV_VERSION].vv_nr = VIM_VERSION_100; dict_T *const msgpack_types_dict = dict_alloc(); for (size_t i = 0; i < ARRAY_SIZE(msgpack_type_names); i++) { @@ -2964,11 +2979,16 @@ int do_unlet(char_u *name, int forceit) } else if (current_funccal != NULL && ht == ¤t_funccal->l_vars.dv_hashtab) { d = ¤t_funccal->l_vars; + } else if (ht == &compat_hashtab) { + d = &vimvardict; } else { di = find_var_in_ht(ht, *name, (char_u *)"", false); d = di->di_tv.vval.v_dict; } - + if (d == NULL) { + EMSG2(_(e_intern2), "do_unlet()"); + return FAIL; + } hi = hash_find(ht, varname); if (!HASHITEM_EMPTY(hi)) { di = HI2DI(hi); @@ -2977,6 +2997,11 @@ int do_unlet(char_u *name, int forceit) || tv_check_lock(d->dv_lock, name, false)) { return FAIL; } + + if (d == NULL || tv_check_lock(d->dv_lock, name, false)) { + return FAIL; + } + typval_T oldtv; bool watched = is_watched(dict); @@ -6667,6 +6692,7 @@ static struct fst { { "asin", 1, 1, f_asin }, // WJMc { "assert_equal", 2, 3, f_assert_equal }, { "assert_exception", 1, 2, f_assert_exception }, + { "assert_fails", 1, 2, f_assert_fails }, { "assert_false", 1, 2, f_assert_false }, { "assert_true", 1, 2, f_assert_true }, { "atan", 1, 1, f_atan }, @@ -6877,6 +6903,7 @@ static struct fst { { "setbufvar", 3, 3, f_setbufvar }, { "setcharsearch", 1, 1, f_setcharsearch }, { "setcmdpos", 1, 1, f_setcmdpos }, + { "setfperm", 2, 2, f_setfperm }, { "setline", 2, 2, f_setline }, { "setloclist", 2, 4, f_setloclist }, { "setmatches", 1, 1, f_setmatches }, @@ -6929,6 +6956,8 @@ static struct fst { { "tempname", 0, 0, f_tempname }, { "termopen", 1, 2, f_termopen }, { "test", 1, 1, f_test }, + { "timer_start", 2, 3, f_timer_start }, + { "timer_stop", 1, 1, f_timer_stop }, { "tolower", 1, 1, f_tolower }, { "toupper", 1, 1, f_toupper }, { "tr", 3, 3, f_tr }, @@ -7651,6 +7680,43 @@ static void f_assert_exception(typval_T *argvars, typval_T *rettv) } } +/// "assert_fails(cmd [, error])" function +static void f_assert_fails(typval_T *argvars, typval_T *rettv) +{ + char_u *cmd = get_tv_string_chk(&argvars[0]); + garray_T ga; + + called_emsg = false; + suppress_errthrow = true; + emsg_silent = true; + do_cmdline_cmd((char *)cmd); + if (!called_emsg) { + prepare_assert_error(&ga); + ga_concat(&ga, (char_u *)"command did not fail: "); + ga_concat(&ga, cmd); + assert_error(&ga); + ga_clear(&ga); + } else if (argvars[1].v_type != VAR_UNKNOWN) { + char_u buf[NUMBUFLEN]; + char *error = (char *)get_tv_string_buf_chk(&argvars[1], buf); + + if (error == NULL + || strstr((char *)vimvars[VV_ERRMSG].vv_str, error) == NULL) { + prepare_assert_error(&ga); + fill_assert_error(&ga, &argvars[2], NULL, &argvars[1], + &vimvars[VV_ERRMSG].vv_tv); + assert_error(&ga); + ga_clear(&ga); + } + } + + called_emsg = false; + suppress_errthrow = false; + emsg_silent = false; + emsg_on_display = false; + set_vim_var_string(VV_ERRMSG, NULL, 0); +} + // Common for assert_true() and assert_false(). static void assert_bool(typval_T *argvars, bool is_true) { @@ -9833,7 +9899,7 @@ static void f_getcmdwintype(typval_T *argvars, typval_T *rettv) static void f_getcwd(typval_T *argvars, typval_T *rettv) { // Possible scope of working directory to return. - CdScope scope = MIN_CD_SCOPE; + CdScope scope = kCdScopeInvalid; // Numbers of the scope objects (window, tab) we want the working directory // of. A `-1` means to skip this scope, a `0` means the current object. @@ -9862,26 +9928,27 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv) return; } scope_number[i] = argvars[i].vval.v_number; - // The scope is the current iteration step. - scope = i; // It is an error for the scope number to be less than `-1`. if (scope_number[i] < -1) { EMSG(_(e_invarg)); return; } + // Use the narrowest scope the user requested + if (scope_number[i] >= 0 && scope == kCdScopeInvalid) { + // The scope is the current iteration step. + scope = i; + } else if (scope_number[i] < 0) { + scope = i + 1; + } } - // Normalize scope, the number of the new scope will be 0. - if (scope_number[scope] < 0) { - // Arguments to `getcwd` always end at second-highest scope, so scope will - // always be <= `MAX_CD_SCOPE`. - scope++; + // If the user didn't specify anything, default to window scope + if (scope == kCdScopeInvalid) { + scope = MIN_CD_SCOPE; } // Find the tabpage by number - if (scope_number[kCdScopeTab] == -1) { - tp = NULL; - } else if (scope_number[kCdScopeTab] > 0) { + if (scope_number[kCdScopeTab] > 0) { tp = find_tabpage(scope_number[kCdScopeTab]); if (!tp) { EMSG(_("E5000: Cannot find tab number.")); @@ -9890,16 +9957,14 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv) } // Find the window in `tp` by number, `NULL` if none. - if (scope_number[kCdScopeWindow] == -1) { - win = NULL; - } else if (scope_number[kCdScopeWindow] >= 0) { - if (!tp) { + if (scope_number[kCdScopeWindow] >= 0) { + if (scope_number[kCdScopeTab] < 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], curtab); + win = find_win_by_nr(&argvars[0], tp); if (!win) { EMSG(_("E5002: Cannot find window number.")); return; @@ -9934,6 +9999,9 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv) } } break; + case kCdScopeInvalid: + // We should never get here + assert(false); } if (from) { @@ -10687,6 +10755,7 @@ static void f_has(typval_T *argvars, typval_T *rettv) "termguicolors", "termresponse", "textobjects", + "timers", "title", "user-commands", /* was accidentally included in 5.4 */ "user_commands", @@ -10780,7 +10849,7 @@ static void f_has_key(typval_T *argvars, typval_T *rettv) static void f_haslocaldir(typval_T *argvars, typval_T *rettv) { // Possible scope of working directory to return. - CdScope scope = MIN_CD_SCOPE; + CdScope scope = kCdScopeInvalid; // Numbers of the scope objects (window, tab) we want the working directory // of. A `-1` means to skip this scope, a `0` means the current object. @@ -10805,25 +10874,26 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv) return; } scope_number[i] = argvars[i].vval.v_number; - // The scope is the current iteration step. - scope = i; if (scope_number[i] < -1) { EMSG(_(e_invarg)); return; } + // Use the narrowest scope the user requested + if (scope_number[i] >= 0 && scope == kCdScopeInvalid) { + // The scope is the current iteration step. + scope = i; + } else if (scope_number[i] < 0) { + scope = i + 1; + } } - // Normalize scope, the number of the new scope will be 0. - if (scope_number[scope] < 0) { - // Arguments to `haslocaldir` always end at second-highest scope, so scope - // will always be <= `MAX_CD_SCOPE`. - scope++; + // If the user didn't specify anything, default to window scope + if (scope == kCdScopeInvalid) { + scope = MIN_CD_SCOPE; } // Find the tabpage by number - if (scope_number[kCdScopeTab] == -1) { - tp = NULL; - } else if (scope_number[kCdScopeTab] > 0) { + if (scope_number[kCdScopeTab] > 0) { tp = find_tabpage(scope_number[kCdScopeTab]); if (!tp) { EMSG(_("5000: Cannot find tab number.")); @@ -10832,16 +10902,14 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv) } // Find the window in `tp` by number, `NULL` if none. - if (scope_number[kCdScopeWindow] == -1) { - win = NULL; - } else if (scope_number[kCdScopeWindow] >= 0) { - if (!tp) { + if (scope_number[kCdScopeWindow] >= 0) { + if (scope_number[kCdScopeTab] < 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], curtab); + win = find_win_by_nr(&argvars[0], tp); if (!win) { EMSG(_("E5002: Cannot find window number.")); return; @@ -10862,6 +10930,9 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv) // The global scope never has a local directory rettv->vval.v_number = 0; break; + case kCdScopeInvalid: + // We should never get here + assert(false); } } @@ -11757,7 +11828,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv) list_T *rv = list_alloc(); ui_busy_start(); - Queue *waiting_jobs = queue_new_parent(loop_on_put, &loop); + Queue *waiting_jobs = queue_new_parent(loop_on_put, &main_loop); // For each item in the input list append an integer to the output list. -3 // is used to represent an invalid job id, -2 is for a interrupted job and // -1 for jobs that were skipped or timed out. @@ -11835,7 +11906,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv) } // restore the parent queue for the job queue_process_events(data->events); - queue_replace_parent(data->events, loop.events); + queue_replace_parent(data->events, main_loop.events); } queue_free(waiting_jobs); @@ -14446,6 +14517,38 @@ static void f_setcmdpos(typval_T *argvars, typval_T *rettv) rettv->vval.v_number = set_cmdline_pos(pos); } + +/// "setfperm({fname}, {mode})" function +static void f_setfperm(typval_T *argvars, typval_T *rettv) +{ + rettv->vval.v_number = 0; + + char_u *fname = get_tv_string_chk(&argvars[0]); + if (fname == NULL) { + return; + } + + char_u modebuf[NUMBUFLEN]; + char_u *mode_str = get_tv_string_buf_chk(&argvars[1], modebuf); + if (mode_str == NULL) { + return; + } + if (STRLEN(mode_str) != 9) { + EMSG2(_(e_invarg2), mode_str); + return; + } + + int mask = 1; + int mode = 0; + for (int i = 8; i >= 0; i--) { + if (mode_str[i] != '-') { + mode |= mask; + } + mask = mask << 1; + } + rettv->vval.v_number = os_setperm(fname, mode) == OK; +} + /* * "setline()" function */ @@ -14991,13 +15094,18 @@ typedef struct { int idx; } sortItem_T; -static int item_compare_ic; -static bool item_compare_numeric; -static bool item_compare_numbers; -static bool item_compare_float; -static char_u *item_compare_func; -static dict_T *item_compare_selfdict; -static int item_compare_func_err; +/// struct storing information about current sort +typedef struct { + int item_compare_ic; + bool item_compare_numeric; + bool item_compare_numbers; + bool item_compare_float; + char_u *item_compare_func; + dict_T *item_compare_selfdict; + int item_compare_func_err; +} sortinfo_T; +static sortinfo_T *sortinfo = NULL; + #define ITEM_COMPARE_FAIL 999 /* @@ -15017,14 +15125,14 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero) typval_T *tv1 = &si1->item->li_tv; typval_T *tv2 = &si2->item->li_tv; - if (item_compare_numbers) { + if (sortinfo->item_compare_numbers) { long v1 = get_tv_number(tv1); long v2 = get_tv_number(tv2); return v1 == v2 ? 0 : v1 > v2 ? 1 : -1; } - if (item_compare_float) { + if (sortinfo->item_compare_float) { float_T v1 = get_tv_float(tv1); float_T v2 = get_tv_float(tv2); @@ -15035,7 +15143,7 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero) // do that for string variables. Use a single quote when comparing with // a non-string to do what the docs promise. if (tv1->v_type == VAR_STRING) { - if (tv2->v_type != VAR_STRING || item_compare_numeric) { + if (tv2->v_type != VAR_STRING || sortinfo->item_compare_numeric) { p1 = (char_u *)"'"; } else { p1 = tv1->vval.v_string; @@ -15044,7 +15152,7 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero) tofree1 = p1 = (char_u *) encode_tv2string(tv1, NULL); } if (tv2->v_type == VAR_STRING) { - if (tv1->v_type != VAR_STRING || item_compare_numeric) { + if (tv1->v_type != VAR_STRING || sortinfo->item_compare_numeric) { p2 = (char_u *)"'"; } else { p2 = tv2->vval.v_string; @@ -15052,12 +15160,14 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero) } else { tofree2 = p2 = (char_u *) encode_tv2string(tv2, NULL); } - if (p1 == NULL) + if (p1 == NULL) { p1 = (char_u *)""; - if (p2 == NULL) + } + if (p2 == NULL) { p2 = (char_u *)""; - if (!item_compare_numeric) { - if (item_compare_ic) { + } + if (!sortinfo->item_compare_numeric) { + if (sortinfo->item_compare_ic) { res = STRICMP(p1, p2); } else { res = STRCMP(p1, p2); @@ -15098,9 +15208,10 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero) typval_T argv[3]; int dummy; - /* shortcut after failure in previous call; compare all items equal */ - if (item_compare_func_err) + // shortcut after failure in previous call; compare all items equal + if (sortinfo->item_compare_func_err) { return 0; + } si1 = (sortItem_T *)s1; si2 = (sortItem_T *)s2; @@ -15110,19 +15221,22 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero) copy_tv(&si1->item->li_tv, &argv[0]); copy_tv(&si2->item->li_tv, &argv[1]); - rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */ - res = call_func(item_compare_func, (int)STRLEN(item_compare_func), - &rettv, 2, argv, 0L, 0L, &dummy, TRUE, - item_compare_selfdict); + rettv.v_type = VAR_UNKNOWN; // clear_tv() uses this + res = call_func(sortinfo->item_compare_func, + (int)STRLEN(sortinfo->item_compare_func), + &rettv, 2, argv, 0L, 0L, &dummy, true, + sortinfo->item_compare_selfdict); clear_tv(&argv[0]); clear_tv(&argv[1]); - if (res == FAIL) + if (res == FAIL) { res = ITEM_COMPARE_FAIL; - else - res = get_tv_number_chk(&rettv, &item_compare_func_err); - if (item_compare_func_err) - res = ITEM_COMPARE_FAIL; /* return value has wrong type */ + } else { + res = get_tv_number_chk(&rettv, &sortinfo->item_compare_func_err); + } + if (sortinfo->item_compare_func_err) { + res = ITEM_COMPARE_FAIL; // return value has wrong type + } clear_tv(&rettv); // When the result would be zero, compare the pointers themselves. Makes @@ -15155,6 +15269,12 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) long len; long i; + // Pointer to current info struct used in compare function. Save and restore + // the current one for nested calls. + sortinfo_T info; + sortinfo_T *old_sortinfo = sortinfo; + sortinfo = &info; + if (argvars[0].v_type != VAR_LIST) { EMSG2(_(e_listarg), sort ? "sort()" : "uniq()"); } else { @@ -15165,61 +15285,70 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) ? N_("sort() argument") : N_("uniq() argument")), true)) { - return; + goto theend; } rettv->vval.v_list = l; rettv->v_type = VAR_LIST; ++l->lv_refcount; len = list_len(l); - if (len <= 1) - return; /* short list sorts pretty quickly */ + if (len <= 1) { + goto theend; // short list sorts pretty quickly + } - item_compare_ic = FALSE; - item_compare_numeric = false; - item_compare_numbers = false; - item_compare_float = false; - item_compare_func = NULL; - item_compare_selfdict = NULL; + info.item_compare_ic = false; + info.item_compare_numeric = false; + info.item_compare_numbers = false; + info.item_compare_float = false; + info.item_compare_func = NULL; + info.item_compare_selfdict = NULL; if (argvars[1].v_type != VAR_UNKNOWN) { /* optional second argument: {func} */ if (argvars[1].v_type == VAR_FUNC) { - item_compare_func = argvars[1].vval.v_string; + info.item_compare_func = argvars[1].vval.v_string; } else { int error = FALSE; i = get_tv_number_chk(&argvars[1], &error); - if (error) - return; /* type error; errmsg already given */ - if (i == 1) - item_compare_ic = TRUE; - else - item_compare_func = get_tv_string(&argvars[1]); - if (item_compare_func != NULL) { - if (STRCMP(item_compare_func, "n") == 0) { - item_compare_func = NULL; - item_compare_numeric = true; - } else if (STRCMP(item_compare_func, "N") == 0) { - item_compare_func = NULL; - item_compare_numbers = true; - } else if (STRCMP(item_compare_func, "f") == 0) { - item_compare_func = NULL; - item_compare_float = true; - } else if (STRCMP(item_compare_func, "i") == 0) { - item_compare_func = NULL; - item_compare_ic = TRUE; + if (error) { + goto theend; // type error; errmsg already given + } + if (i == 1) { + info.item_compare_ic = true; + } else if (argvars[1].v_type != VAR_NUMBER) { + info.item_compare_func = get_tv_string(&argvars[1]); + } else if (i != 0) { + EMSG(_(e_invarg)); + goto theend; + } + if (info.item_compare_func != NULL) { + if (*info.item_compare_func == NUL) { + // empty string means default sort + info.item_compare_func = NULL; + } else if (STRCMP(info.item_compare_func, "n") == 0) { + info.item_compare_func = NULL; + info.item_compare_numeric = true; + } else if (STRCMP(info.item_compare_func, "N") == 0) { + info.item_compare_func = NULL; + info.item_compare_numbers = true; + } else if (STRCMP(info.item_compare_func, "f") == 0) { + info.item_compare_func = NULL; + info.item_compare_float = true; + } else if (STRCMP(info.item_compare_func, "i") == 0) { + info.item_compare_func = NULL; + info.item_compare_ic = true; } } } if (argvars[2].v_type != VAR_UNKNOWN) { - /* optional third argument: {dict} */ + // optional third argument: {dict} if (argvars[2].v_type != VAR_DICT) { EMSG(_(e_dictreq)); - return; + goto theend; } - item_compare_selfdict = argvars[2].vval.v_dict; + info.item_compare_selfdict = argvars[2].vval.v_dict; } } @@ -15235,19 +15364,20 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) i++; } - item_compare_func_err = FALSE; + info.item_compare_func_err = false; // Test the compare function. - if (item_compare_func != NULL + if (info.item_compare_func != NULL && item_compare2_not_keeping_zero(&ptrs[0], &ptrs[1]) == ITEM_COMPARE_FAIL) { EMSG(_("E702: Sort compare function failed")); } else { // Sort the array with item pointers. qsort(ptrs, (size_t)len, sizeof (sortItem_T), - item_compare_func == NULL ? item_compare_not_keeping_zero : - item_compare2_not_keeping_zero); + (info.item_compare_func == NULL ? + item_compare_not_keeping_zero : + item_compare2_not_keeping_zero)); - if (!item_compare_func_err) { + if (!info.item_compare_func_err) { // Clear the list and append the items in the sorted order. l->lv_first = NULL; l->lv_last = NULL; @@ -15263,21 +15393,24 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) int (*item_compare_func_ptr)(const void *, const void *); // f_uniq(): ptrs will be a stack of items to remove. - item_compare_func_err = FALSE; - item_compare_func_ptr = item_compare_func ? item_compare2_keeping_zero : - item_compare_keeping_zero; + info.item_compare_func_err = false; + if (info.item_compare_func != NULL) { + item_compare_func_ptr = item_compare2_keeping_zero; + } else { + item_compare_func_ptr = item_compare_keeping_zero; + } for (li = l->lv_first; li != NULL && li->li_next != NULL; li = li->li_next) { if (item_compare_func_ptr(&li, &li->li_next) == 0) { ptrs[i++].item = li; } - if (item_compare_func_err) { + if (info.item_compare_func_err) { EMSG(_("E882: Uniq compare function failed")); break; } } - if (!item_compare_func_err) { + if (!info.item_compare_func_err) { while (--i >= 0) { assert(ptrs[i].item->li_next); li = ptrs[i].item->li_next; @@ -15296,6 +15429,9 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) xfree(ptrs); } + +theend: + sortinfo = old_sortinfo; } /// "sort"({list})" function @@ -16408,6 +16544,127 @@ static void f_tanh(typval_T *argvars, typval_T *rettv) float_op_wrapper(argvars, rettv, &tanh); } + +/// "timer_start(timeout, callback, opts)" function +static void f_timer_start(typval_T *argvars, typval_T *rettv) +{ + long timeout = get_tv_number(&argvars[0]); + timer_T *timer; + int repeat = 1; + dict_T *dict; + + rettv->vval.v_number = -1; + + if (argvars[2].v_type != VAR_UNKNOWN) { + if (argvars[2].v_type != VAR_DICT + || (dict = argvars[2].vval.v_dict) == NULL) { + EMSG2(_(e_invarg2), get_tv_string(&argvars[2])); + return; + } + if (dict_find(dict, (char_u *)"repeat", -1) != NULL) { + repeat = get_dict_number(dict, (char_u *)"repeat"); + } + } + + if (argvars[1].v_type != VAR_FUNC && argvars[1].v_type != VAR_STRING) { + EMSG2(e_invarg2, "funcref"); + return; + } + ufunc_T *func = find_ufunc(argvars[1].vval.v_string); + if (!func) { + // Invalid function name. Error already reported by `find_ufunc`. + return; + } + func->uf_refcount++; + + timer = xmalloc(sizeof *timer); + timer->stopped = false; + timer->repeat_count = repeat; + timer->timer_id = last_timer_id++; + timer->callback = func; + + time_watcher_init(&main_loop, &timer->tw, timer); + timer->tw.events = queue_new_child(main_loop.events); + // if main loop is blocked, don't queue up multiple events + timer->tw.blockable = true; + time_watcher_start(&timer->tw, timer_due_cb, timeout, + timeout * (repeat != 1)); + + pmap_put(uint64_t)(timers, timer->timer_id, timer); + rettv->vval.v_number = timer->timer_id; +} + + +// "timer_stop(timerid)" function +static void f_timer_stop(typval_T *argvars, typval_T *rettv) +{ + if (argvars[0].v_type != VAR_NUMBER) { + EMSG(_(e_number_exp)); + return; + } + + timer_T *timer = pmap_get(uint64_t)(timers, get_tv_number(&argvars[0])); + + if (timer == NULL) { + return; + } + + timer_stop(timer); +} + +// invoked on the main loop +static void timer_due_cb(TimeWatcher *tw, void *data) +{ + timer_T *timer = (timer_T *)data; + if (timer->stopped) { + return; + } + // if repeat was negative repeat forever + if (timer->repeat_count >= 0 && --timer->repeat_count == 0) { + timer_stop(timer); + } + + typval_T argv[1]; + init_tv(argv); + argv[0].v_type = VAR_NUMBER; + argv[0].vval.v_number = timer->timer_id; + typval_T rettv; + + init_tv(&rettv); + call_user_func(timer->callback, ARRAY_SIZE(argv), argv, &rettv, + curwin->w_cursor.lnum, curwin->w_cursor.lnum, NULL); + clear_tv(&rettv); +} + +static void timer_stop(timer_T *timer) +{ + if (timer->stopped) { + // avoid double free + return; + } + timer->stopped = true; + time_watcher_stop(&timer->tw); + time_watcher_close(&timer->tw, timer_free_cb); +} + +// invoked on next event loop tick, so queue is empty +static void timer_free_cb(TimeWatcher *tw, void *data) +{ + timer_T *timer = (timer_T *)data; + queue_free(timer->tw.events); + user_func_unref(timer->callback); + pmap_del(uint64_t)(timers, timer->timer_id); + xfree(timer); +} + +void timer_teardown(void) +{ + timer_T *timer; + map_foreach_value(timers, timer, { + timer_stop(timer); + }) +} + /* * "tolower(string)" function */ @@ -17507,7 +17764,8 @@ void set_vim_var_special(const VimVarIndex idx, const SpecialVarValue val) void set_vim_var_string(const VimVarIndex idx, const char *const val, const ptrdiff_t len) { - xfree(vimvars[idx].vv_str); + clear_tv(&vimvars[idx].vv_di.di_tv); + vimvars[idx].vv_type = VAR_STRING; if (val == NULL) { vimvars[idx].vv_str = NULL; } else if (len == -1) { @@ -17523,7 +17781,8 @@ void set_vim_var_string(const VimVarIndex idx, const char *const val, /// @param[in,out] val Value to set to. Reference count will be incremented. void set_vim_var_list(const VimVarIndex idx, list_T *const val) { - list_unref(vimvars[idx].vv_list); + clear_tv(&vimvars[idx].vv_di.di_tv); + vimvars[idx].vv_type = VAR_LIST; vimvars[idx].vv_list = val; if (val != NULL) { val->lv_refcount++; @@ -17537,7 +17796,8 @@ void set_vim_var_list(const VimVarIndex idx, list_T *const val) /// Also keys of the dictionary will be made read-only. void set_vim_var_dict(const VimVarIndex idx, dict_T *const val) { - dict_unref(vimvars[idx].vv_dict); + clear_tv(&vimvars[idx].vv_di.di_tv); + vimvars[idx].vv_type = VAR_DICT; vimvars[idx].vv_dict = val; if (val != NULL) { @@ -21512,11 +21772,11 @@ static inline TerminalJobData *common_job_init(char **argv, data->on_stderr = on_stderr; data->on_exit = on_exit; data->self = self; - data->events = queue_new_child(loop.events); + data->events = queue_new_child(main_loop.events); if (pty) { - data->proc.pty = pty_process_init(&loop, data); + data->proc.pty = pty_process_init(&main_loop, data); } else { - data->proc.uv = libuv_process_init(&loop, data); + data->proc.uv = libuv_process_init(&main_loop, data); } Process *proc = (Process *)&data->proc; proc->argv = argv; @@ -21614,7 +21874,7 @@ static inline void free_term_job_data(TerminalJobData *data) { // data->queue may still be used after this function returns(process_wait), so // only free in the next event loop iteration - queue_put(loop.fast_events, free_term_job_data_event, 1, data); + queue_put(main_loop.fast_events, free_term_job_data_event, 1, data); } // vimscript job callbacks must be executed on Nvim main loop @@ -21818,6 +22078,7 @@ static void script_host_eval(char *name, typval_T *argvars, typval_T *rettv) if (argvars[0].v_type != VAR_STRING) { EMSG(_(e_invarg)); + return; } list_T *args = list_alloc(); @@ -21901,9 +22162,8 @@ bool eval_has_provider(char *name) return false; } -// Compute the `DictWatcher` address from a QUEUE node. This only exists because -// ASAN doesn't handle `QUEUE_DATA` pointer arithmetic, and we blacklist this -// function on .asan-blacklist. +// Compute the `DictWatcher` address from a QUEUE node. This only exists for +// .asan-blacklist (ASAN doesn't handle QUEUE_DATA pointer arithmetic). static DictWatcher *dictwatcher_node_data(QUEUE *q) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET { diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index 0774ef515f..43e9f76c0f 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -101,7 +101,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, FUNC_ATTR_NONNULL_ALL { if (kv_size(*container_stack) == 0) { - kv_push(ValuesStackItem, *stack, obj); + kv_push(*stack, obj); return OK; } ContainerStackItem last_container = kv_last(*container_stack); @@ -190,7 +190,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, *next_map_special = true; return OK; } - kv_push(ValuesStackItem, *stack, obj); + kv_push(*stack, obj); } return OK; } @@ -628,10 +628,8 @@ int json_decode_string(const char *const buf, const size_t buf_len, convert_setup(&conv, (char_u *) "utf-8", p_enc); conv.vc_fail = true; int ret = OK; - ValuesStack stack; - kv_init(stack); - ContainerStack container_stack; - kv_init(container_stack); + ValuesStack stack = KV_INITIAL_VALUE; + ContainerStack container_stack = KV_INITIAL_VALUE; rettv->v_type = VAR_UNKNOWN; bool didcomma = false; bool didcolon = false; @@ -815,13 +813,13 @@ json_decode_string_cycle_start: .v_lock = VAR_UNLOCKED, .vval = { .v_list = list }, }; - kv_push(ContainerStackItem, container_stack, ((ContainerStackItem) { + kv_push(container_stack, ((ContainerStackItem) { .stack_index = kv_size(stack), .s = p, .container = tv, .special_val = NULL, })); - kv_push(ValuesStackItem, stack, OBJ(tv, false, didcomma, didcolon)); + kv_push(stack, OBJ(tv, false, didcomma, didcolon)); break; } case '{': { @@ -845,13 +843,13 @@ json_decode_string_cycle_start: .vval = { .v_dict = dict }, }; } - kv_push(ContainerStackItem, container_stack, ((ContainerStackItem) { + kv_push(container_stack, ((ContainerStackItem) { .stack_index = kv_size(stack), .s = p, .container = tv, .special_val = val_list, })); - kv_push(ValuesStackItem, stack, OBJ(tv, false, didcomma, didcolon)); + kv_push(stack, OBJ(tv, false, didcomma, didcolon)); break; } default: { diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index c651a50be9..54daf7557e 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -6,6 +6,7 @@ #include <msgpack.h> #include <inttypes.h> +#include <stddef.h> #include <assert.h> #include <math.h> @@ -22,6 +23,7 @@ #include "nvim/ascii.h" #include "nvim/vim.h" // For _() #include "nvim/lib/kvec.h" +#include "nvim/eval/typval_encode.h" #define ga_concat(a, b) ga_concat(a, (char_u *)b) #define utf_ptr2char(b) utf_ptr2char((char_u *)b) @@ -32,29 +34,6 @@ #define convert_setup(vcp, from, to) \ (convert_setup(vcp, (char_u *)from, (char_u *)to)) -/// Structure representing current VimL to messagepack conversion state -typedef struct { - enum { - kMPConvDict, ///< Convert dict_T *dictionary. - kMPConvList, ///< Convert list_T *list. - kMPConvPairs, ///< Convert mapping represented as a list_T* of pairs. - } type; - union { - struct { - dict_T *dict; ///< Currently converted dictionary. - hashitem_T *hi; ///< Currently converted dictionary item. - size_t todo; ///< Amount of items left to process. - } d; ///< State of dictionary conversion. - struct { - list_T *list; ///< Currently converted list. - listitem_T *li; ///< Currently converted list item. - } l; ///< State of list or generic mapping conversion. - } data; ///< Data to convert. -} MPConvStackVal; - -/// Stack used to convert VimL values to messagepack. -typedef kvec_t(MPConvStackVal) MPConvStack; - const char *const encode_special_var_names[] = { [kSpecialVarNull] = "null", [kSpecialVarTrue] = "true", @@ -275,368 +254,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, : OK); } -/// Code for checking whether container references itself -/// -/// @param[in,out] val Container to check. -/// @param copyID_attr Name of the container attribute that holds copyID. -/// After checking whether value of this attribute is -/// copyID (variable) it is set to copyID. -#define CHECK_SELF_REFERENCE(val, copyID_attr, conv_type) \ - do { \ - if ((val)->copyID_attr == copyID) { \ - CONV_RECURSE((val), conv_type); \ - } \ - (val)->copyID_attr = copyID; \ - } while (0) - -#define TV_STRLEN(tv) \ - (tv->vval.v_string == NULL ? 0 : STRLEN(tv->vval.v_string)) - -/// Define functions which convert VimL value to something else -/// -/// Creates function `vim_to_{name}(firstargtype firstargname, typval_T *const -/// tv)` which returns OK or FAIL and helper functions. -/// -/// @param firstargtype Type of the first argument. It will be used to return -/// the results. -/// @param firstargname Name of the first argument. -/// @param name Name of the target converter. -#define DEFINE_VIML_CONV_FUNCTIONS(scope, name, firstargtype, firstargname) \ -static int name##_convert_one_value(firstargtype firstargname, \ - MPConvStack *const mpstack, \ - typval_T *const tv, \ - const int copyID, \ - const char *const objname) \ - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT \ -{ \ - switch (tv->v_type) { \ - case VAR_STRING: { \ - CONV_STRING(tv->vval.v_string, TV_STRLEN(tv)); \ - break; \ - } \ - case VAR_NUMBER: { \ - CONV_NUMBER(tv->vval.v_number); \ - break; \ - } \ - case VAR_FLOAT: { \ - CONV_FLOAT(tv->vval.v_float); \ - break; \ - } \ - case VAR_FUNC: { \ - CONV_FUNC(tv->vval.v_string); \ - break; \ - } \ - case VAR_LIST: { \ - if (tv->vval.v_list == NULL || tv->vval.v_list->lv_len == 0) { \ - CONV_EMPTY_LIST(); \ - break; \ - } \ - CHECK_SELF_REFERENCE(tv->vval.v_list, lv_copyID, kMPConvList); \ - CONV_LIST_START(tv->vval.v_list); \ - kv_push(MPConvStackVal, *mpstack, ((MPConvStackVal) { \ - .type = kMPConvList, \ - .data = { \ - .l = { \ - .list = tv->vval.v_list, \ - .li = tv->vval.v_list->lv_first, \ - }, \ - }, \ - })); \ - break; \ - } \ - case VAR_SPECIAL: { \ - switch (tv->vval.v_special) { \ - case kSpecialVarNull: { \ - CONV_NIL(); \ - break; \ - } \ - case kSpecialVarTrue: \ - case kSpecialVarFalse: { \ - CONV_BOOL(tv->vval.v_special == kSpecialVarTrue); \ - break; \ - } \ - } \ - break; \ - } \ - case VAR_DICT: { \ - if (tv->vval.v_dict == NULL \ - || tv->vval.v_dict->dv_hashtab.ht_used == 0) { \ - CONV_EMPTY_DICT(); \ - break; \ - } \ - const dictitem_T *type_di; \ - const dictitem_T *val_di; \ - if (CONV_ALLOW_SPECIAL \ - && tv->vval.v_dict->dv_hashtab.ht_used == 2 \ - && (type_di = dict_find((dict_T *) tv->vval.v_dict, \ - (char_u *) "_TYPE", -1)) != NULL \ - && type_di->di_tv.v_type == VAR_LIST \ - && (val_di = dict_find((dict_T *) tv->vval.v_dict, \ - (char_u *) "_VAL", -1)) != NULL) { \ - size_t i; \ - for (i = 0; i < ARRAY_SIZE(eval_msgpack_type_lists); i++) { \ - if (type_di->di_tv.vval.v_list == eval_msgpack_type_lists[i]) { \ - break; \ - } \ - } \ - if (i == ARRAY_SIZE(eval_msgpack_type_lists)) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - switch ((MessagePackType) i) { \ - case kMPNil: { \ - CONV_NIL(); \ - break; \ - } \ - case kMPBoolean: { \ - if (val_di->di_tv.v_type != VAR_NUMBER) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - CONV_BOOL(val_di->di_tv.vval.v_number); \ - break; \ - } \ - case kMPInteger: { \ - const list_T *val_list; \ - varnumber_T sign; \ - varnumber_T highest_bits; \ - varnumber_T high_bits; \ - varnumber_T low_bits; \ - /* List of 4 integers; first is signed (should be 1 or -1, but */ \ - /* this is not checked), second is unsigned and have at most */ \ - /* one (sign is -1) or two (sign is 1) non-zero bits (number of */ \ - /* bits is not checked), other unsigned and have at most 31 */ \ - /* non-zero bits (number of bits is not checked).*/ \ - if (val_di->di_tv.v_type != VAR_LIST \ - || (val_list = val_di->di_tv.vval.v_list) == NULL \ - || val_list->lv_len != 4 \ - || val_list->lv_first->li_tv.v_type != VAR_NUMBER \ - || (sign = val_list->lv_first->li_tv.vval.v_number) == 0 \ - || val_list->lv_first->li_next->li_tv.v_type != VAR_NUMBER \ - || (highest_bits = \ - val_list->lv_first->li_next->li_tv.vval.v_number) < 0 \ - || val_list->lv_last->li_prev->li_tv.v_type != VAR_NUMBER \ - || (high_bits = \ - val_list->lv_last->li_prev->li_tv.vval.v_number) < 0 \ - || val_list->lv_last->li_tv.v_type != VAR_NUMBER \ - || (low_bits = val_list->lv_last->li_tv.vval.v_number) < 0) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - uint64_t number = ((uint64_t) (((uint64_t) highest_bits) << 62) \ - | (uint64_t) (((uint64_t) high_bits) << 31) \ - | (uint64_t) low_bits); \ - if (sign > 0) { \ - CONV_UNSIGNED_NUMBER(number); \ - } else { \ - CONV_NUMBER(-number); \ - } \ - break; \ - } \ - case kMPFloat: { \ - if (val_di->di_tv.v_type != VAR_FLOAT) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - CONV_FLOAT(val_di->di_tv.vval.v_float); \ - break; \ - } \ - case kMPString: \ - case kMPBinary: { \ - const bool is_string = ((MessagePackType) i == kMPString); \ - if (val_di->di_tv.v_type != VAR_LIST) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - size_t len; \ - char *buf; \ - if (!encode_vim_list_to_buf(val_di->di_tv.vval.v_list, &len, \ - &buf)) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - if (is_string) { \ - CONV_STR_STRING(buf, len); \ - } else { \ - CONV_STRING(buf, len); \ - } \ - xfree(buf); \ - break; \ - } \ - case kMPArray: { \ - if (val_di->di_tv.v_type != VAR_LIST) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - CHECK_SELF_REFERENCE(val_di->di_tv.vval.v_list, lv_copyID, \ - kMPConvList); \ - CONV_LIST_START(val_di->di_tv.vval.v_list); \ - kv_push(MPConvStackVal, *mpstack, ((MPConvStackVal) { \ - .type = kMPConvList, \ - .data = { \ - .l = { \ - .list = val_di->di_tv.vval.v_list, \ - .li = val_di->di_tv.vval.v_list->lv_first, \ - }, \ - }, \ - })); \ - break; \ - } \ - case kMPMap: { \ - if (val_di->di_tv.v_type != VAR_LIST) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - list_T *const val_list = val_di->di_tv.vval.v_list; \ - if (val_list == NULL || val_list->lv_len == 0) { \ - CONV_EMPTY_DICT(); \ - break; \ - } \ - for (const listitem_T *li = val_list->lv_first; li != NULL; \ - li = li->li_next) { \ - if (li->li_tv.v_type != VAR_LIST \ - || li->li_tv.vval.v_list->lv_len != 2) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - } \ - CHECK_SELF_REFERENCE(val_list, lv_copyID, kMPConvPairs); \ - CONV_DICT_START(val_list->lv_len); \ - kv_push(MPConvStackVal, *mpstack, ((MPConvStackVal) { \ - .type = kMPConvPairs, \ - .data = { \ - .l = { \ - .list = val_list, \ - .li = val_list->lv_first, \ - }, \ - }, \ - })); \ - break; \ - } \ - case kMPExt: { \ - const list_T *val_list; \ - varnumber_T type; \ - if (val_di->di_tv.v_type != VAR_LIST \ - || (val_list = val_di->di_tv.vval.v_list) == NULL \ - || val_list->lv_len != 2 \ - || (val_list->lv_first->li_tv.v_type != VAR_NUMBER) \ - || (type = val_list->lv_first->li_tv.vval.v_number) > INT8_MAX \ - || type < INT8_MIN \ - || (val_list->lv_last->li_tv.v_type != VAR_LIST)) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - size_t len; \ - char *buf; \ - if (!encode_vim_list_to_buf(val_list->lv_last->li_tv.vval.v_list, \ - &len, &buf)) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - CONV_EXT_STRING(buf, len, type); \ - xfree(buf); \ - break; \ - } \ - } \ - break; \ - } \ -name##_convert_one_value_regular_dict: \ - CHECK_SELF_REFERENCE(tv->vval.v_dict, dv_copyID, kMPConvDict); \ - CONV_DICT_START(tv->vval.v_dict->dv_hashtab.ht_used); \ - kv_push(MPConvStackVal, *mpstack, ((MPConvStackVal) { \ - .type = kMPConvDict, \ - .data = { \ - .d = { \ - .dict = tv->vval.v_dict, \ - .hi = tv->vval.v_dict->dv_hashtab.ht_array, \ - .todo = tv->vval.v_dict->dv_hashtab.ht_used, \ - }, \ - }, \ - })); \ - break; \ - } \ - case VAR_UNKNOWN: { \ - EMSG2(_(e_intern2), #name "_convert_one_value()"); \ - return FAIL; \ - } \ - } \ - return OK; \ -} \ -\ -scope int encode_vim_to_##name(firstargtype firstargname, typval_T *const tv, \ - const char *const objname) \ - FUNC_ATTR_WARN_UNUSED_RESULT \ -{ \ - const int copyID = get_copyID(); \ - MPConvStack mpstack; \ - kv_init(mpstack); \ - if (name##_convert_one_value(firstargname, &mpstack, tv, copyID, objname) \ - == FAIL) { \ - goto encode_vim_to_##name##_error_ret; \ - } \ - while (kv_size(mpstack)) { \ - MPConvStackVal *cur_mpsv = &kv_A(mpstack, kv_size(mpstack) - 1); \ - typval_T *cur_tv = NULL; \ - switch (cur_mpsv->type) { \ - case kMPConvDict: { \ - if (!cur_mpsv->data.d.todo) { \ - (void) kv_pop(mpstack); \ - cur_mpsv->data.d.dict->dv_copyID = copyID - 1; \ - CONV_DICT_END(); \ - continue; \ - } else if (cur_mpsv->data.d.todo \ - != cur_mpsv->data.d.dict->dv_hashtab.ht_used) { \ - CONV_DICT_BETWEEN_ITEMS(); \ - } \ - while (HASHITEM_EMPTY(cur_mpsv->data.d.hi)) { \ - cur_mpsv->data.d.hi++; \ - } \ - dictitem_T *const di = HI2DI(cur_mpsv->data.d.hi); \ - cur_mpsv->data.d.todo--; \ - cur_mpsv->data.d.hi++; \ - CONV_STR_STRING(&di->di_key[0], STRLEN(&di->di_key[0])); \ - CONV_DICT_AFTER_KEY(); \ - cur_tv = &di->di_tv; \ - break; \ - } \ - case kMPConvList: { \ - if (cur_mpsv->data.l.li == NULL) { \ - (void) kv_pop(mpstack); \ - cur_mpsv->data.l.list->lv_copyID = copyID - 1; \ - CONV_LIST_END(cur_mpsv->data.l.list); \ - continue; \ - } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { \ - CONV_LIST_BETWEEN_ITEMS(); \ - } \ - cur_tv = &cur_mpsv->data.l.li->li_tv; \ - cur_mpsv->data.l.li = cur_mpsv->data.l.li->li_next; \ - break; \ - } \ - case kMPConvPairs: { \ - if (cur_mpsv->data.l.li == NULL) { \ - (void) kv_pop(mpstack); \ - cur_mpsv->data.l.list->lv_copyID = copyID - 1; \ - CONV_DICT_END(); \ - continue; \ - } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { \ - CONV_DICT_BETWEEN_ITEMS(); \ - } \ - const list_T *const kv_pair = cur_mpsv->data.l.li->li_tv.vval.v_list; \ - CONV_SPECIAL_DICT_KEY_CHECK(name, kv_pair); \ - if (name##_convert_one_value(firstargname, &mpstack, \ - &kv_pair->lv_first->li_tv, copyID, \ - objname) == FAIL) { \ - goto encode_vim_to_##name##_error_ret; \ - } \ - CONV_DICT_AFTER_KEY(); \ - cur_tv = &kv_pair->lv_last->li_tv; \ - cur_mpsv->data.l.li = cur_mpsv->data.l.li->li_next; \ - break; \ - } \ - } \ - assert(cur_tv != NULL); \ - if (name##_convert_one_value(firstargname, &mpstack, cur_tv, copyID, \ - objname) == FAIL) { \ - goto encode_vim_to_##name##_error_ret; \ - } \ - } \ - kv_destroy(mpstack); \ - return OK; \ -encode_vim_to_##name##_error_ret: \ - kv_destroy(mpstack); \ - return FAIL; \ -} - -#define CONV_STRING(buf, len) \ +#define TYPVAL_ENCODE_CONV_STRING(buf, len) \ do { \ const char *const buf_ = (const char *) buf; \ if (buf == NULL) { \ @@ -655,19 +273,19 @@ encode_vim_to_##name##_error_ret: \ } \ } while (0) -#define CONV_STR_STRING(buf, len) \ - CONV_STRING(buf, len) +#define TYPVAL_ENCODE_CONV_STR_STRING(buf, len) \ + TYPVAL_ENCODE_CONV_STRING(buf, len) -#define CONV_EXT_STRING(buf, len, type) +#define TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type) -#define CONV_NUMBER(num) \ +#define TYPVAL_ENCODE_CONV_NUMBER(num) \ do { \ char numbuf[NUMBUFLEN]; \ vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRId64, (int64_t) (num)); \ ga_concat(gap, numbuf); \ } while (0) -#define CONV_FLOAT(flt) \ +#define TYPVAL_ENCODE_CONV_FLOAT(flt) \ do { \ const float_T flt_ = (flt); \ switch (fpclassify(flt_)) { \ @@ -690,51 +308,51 @@ encode_vim_to_##name##_error_ret: \ } \ } while (0) -#define CONV_FUNC(fun) \ +#define TYPVAL_ENCODE_CONV_FUNC(fun) \ do { \ ga_concat(gap, "function("); \ - CONV_STRING(fun, STRLEN(fun)); \ + TYPVAL_ENCODE_CONV_STRING(fun, STRLEN(fun)); \ ga_append(gap, ')'); \ } while (0) -#define CONV_EMPTY_LIST() \ +#define TYPVAL_ENCODE_CONV_EMPTY_LIST() \ ga_concat(gap, "[]") -#define CONV_LIST_START(lst) \ +#define TYPVAL_ENCODE_CONV_LIST_START(len) \ ga_append(gap, '[') -#define CONV_EMPTY_DICT() \ +#define TYPVAL_ENCODE_CONV_EMPTY_DICT() \ ga_concat(gap, "{}") -#define CONV_NIL() \ +#define TYPVAL_ENCODE_CONV_NIL() \ ga_concat(gap, "v:null") -#define CONV_BOOL(num) \ +#define TYPVAL_ENCODE_CONV_BOOL(num) \ ga_concat(gap, ((num)? "v:true": "v:false")) -#define CONV_UNSIGNED_NUMBER(num) +#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(num) -#define CONV_DICT_START(len) \ +#define TYPVAL_ENCODE_CONV_DICT_START(len) \ ga_append(gap, '{') -#define CONV_DICT_END() \ +#define TYPVAL_ENCODE_CONV_DICT_END() \ ga_append(gap, '}') -#define CONV_DICT_AFTER_KEY() \ +#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY() \ ga_concat(gap, ": ") -#define CONV_DICT_BETWEEN_ITEMS() \ +#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS() \ ga_concat(gap, ", ") -#define CONV_SPECIAL_DICT_KEY_CHECK(name, kv_pair) +#define TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK(label, kv_pair) -#define CONV_LIST_END(lst) \ +#define TYPVAL_ENCODE_CONV_LIST_END() \ ga_append(gap, ']') -#define CONV_LIST_BETWEEN_ITEMS() \ - CONV_DICT_BETWEEN_ITEMS() +#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS() \ + TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS() -#define CONV_RECURSE(val, conv_type) \ +#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ do { \ if (!did_echo_string_emsg) { \ /* Only give this message once for a recursive call to avoid */ \ @@ -764,12 +382,12 @@ encode_vim_to_##name##_error_ret: \ return OK; \ } while (0) -#define CONV_ALLOW_SPECIAL false +#define TYPVAL_ENCODE_ALLOW_SPECIALS false -DEFINE_VIML_CONV_FUNCTIONS(static, string, garray_T *const, gap) +TYPVAL_ENCODE_DEFINE_CONV_FUNCTIONS(static, string, garray_T *const, gap) -#undef CONV_RECURSE -#define CONV_RECURSE(val, conv_type) \ +#undef TYPVAL_ENCODE_CONV_RECURSE +#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ do { \ char ebuf[NUMBUFLEN + 7]; \ size_t backref = 0; \ @@ -796,10 +414,10 @@ DEFINE_VIML_CONV_FUNCTIONS(static, string, garray_T *const, gap) return OK; \ } while (0) -DEFINE_VIML_CONV_FUNCTIONS(, echo, garray_T *const, gap) +TYPVAL_ENCODE_DEFINE_CONV_FUNCTIONS(, echo, garray_T *const, gap) -#undef CONV_RECURSE -#define CONV_RECURSE(val, conv_type) \ +#undef TYPVAL_ENCODE_CONV_RECURSE +#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ do { \ if (!did_echo_string_emsg) { \ /* Only give this message once for a recursive call to avoid */ \ @@ -811,27 +429,27 @@ DEFINE_VIML_CONV_FUNCTIONS(, echo, garray_T *const, gap) return OK; \ } while (0) -#undef CONV_ALLOW_SPECIAL -#define CONV_ALLOW_SPECIAL true +#undef TYPVAL_ENCODE_ALLOW_SPECIALS +#define TYPVAL_ENCODE_ALLOW_SPECIALS true -#undef CONV_NIL -#define CONV_NIL() \ +#undef TYPVAL_ENCODE_CONV_NIL +#define TYPVAL_ENCODE_CONV_NIL() \ ga_concat(gap, "null") -#undef CONV_BOOL -#define CONV_BOOL(num) \ +#undef TYPVAL_ENCODE_CONV_BOOL +#define TYPVAL_ENCODE_CONV_BOOL(num) \ ga_concat(gap, ((num)? "true": "false")) -#undef CONV_UNSIGNED_NUMBER -#define CONV_UNSIGNED_NUMBER(num) \ +#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER +#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(num) \ do { \ char numbuf[NUMBUFLEN]; \ vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRIu64, (num)); \ ga_concat(gap, numbuf); \ } while (0) -#undef CONV_FLOAT -#define CONV_FLOAT(flt) \ +#undef TYPVAL_ENCODE_CONV_FLOAT +#define TYPVAL_ENCODE_CONV_FLOAT(flt) \ do { \ const float_T flt_ = (flt); \ switch (fpclassify(flt_)) { \ @@ -1019,24 +637,24 @@ static inline int convert_to_json_string(garray_T *const gap, return OK; } -#undef CONV_STRING -#define CONV_STRING(buf, len) \ +#undef TYPVAL_ENCODE_CONV_STRING +#define TYPVAL_ENCODE_CONV_STRING(buf, len) \ do { \ if (convert_to_json_string(gap, (const char *) (buf), (len)) != OK) { \ return FAIL; \ } \ } while (0) -#undef CONV_EXT_STRING -#define CONV_EXT_STRING(buf, len, type) \ +#undef TYPVAL_ENCODE_CONV_EXT_STRING +#define TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type) \ do { \ xfree(buf); \ EMSG(_("E474: Unable to convert EXT string to JSON")); \ return FAIL; \ } while (0) -#undef CONV_FUNC -#define CONV_FUNC(fun) \ +#undef TYPVAL_ENCODE_CONV_FUNC +#define TYPVAL_ENCODE_CONV_FUNC(fun) \ return conv_error(_("E474: Error while dumping %s, %s: " \ "attempt to dump function reference"), \ mpstack, objname) @@ -1080,38 +698,38 @@ static inline bool check_json_key(const typval_T *const tv) return true; } -#undef CONV_SPECIAL_DICT_KEY_CHECK -#define CONV_SPECIAL_DICT_KEY_CHECK(name, kv_pair) \ +#undef TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK +#define TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK(label, kv_pair) \ do { \ if (!check_json_key(&kv_pair->lv_first->li_tv)) { \ EMSG(_("E474: Invalid key in special dictionary")); \ - goto encode_vim_to_##name##_error_ret; \ + goto label; \ } \ } while (0) -DEFINE_VIML_CONV_FUNCTIONS(static, json, garray_T *const, gap) - -#undef CONV_STRING -#undef CONV_STR_STRING -#undef CONV_EXT_STRING -#undef CONV_NUMBER -#undef CONV_FLOAT -#undef CONV_FUNC -#undef CONV_EMPTY_LIST -#undef CONV_LIST_START -#undef CONV_EMPTY_DICT -#undef CONV_NIL -#undef CONV_BOOL -#undef CONV_UNSIGNED_NUMBER -#undef CONV_DICT_START -#undef CONV_DICT_END -#undef CONV_DICT_AFTER_KEY -#undef CONV_DICT_BETWEEN_ITEMS -#undef CONV_SPECIAL_DICT_KEY_CHECK -#undef CONV_LIST_END -#undef CONV_LIST_BETWEEN_ITEMS -#undef CONV_RECURSE -#undef CONV_ALLOW_SPECIAL +TYPVAL_ENCODE_DEFINE_CONV_FUNCTIONS(static, json, garray_T *const, gap) + +#undef TYPVAL_ENCODE_CONV_STRING +#undef TYPVAL_ENCODE_CONV_STR_STRING +#undef TYPVAL_ENCODE_CONV_EXT_STRING +#undef TYPVAL_ENCODE_CONV_NUMBER +#undef TYPVAL_ENCODE_CONV_FLOAT +#undef TYPVAL_ENCODE_CONV_FUNC +#undef TYPVAL_ENCODE_CONV_EMPTY_LIST +#undef TYPVAL_ENCODE_CONV_LIST_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_DICT_END +#undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY +#undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS +#undef TYPVAL_ENCODE_CONV_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 /// Return a string with the string representation of a variable. /// Puts quotes around strings, so that they can be parsed back by eval(). @@ -1181,7 +799,7 @@ char *encode_tv2json(typval_T *tv, size_t *len) return (char *) ga.ga_data; } -#define CONV_STRING(buf, len) \ +#define TYPVAL_ENCODE_CONV_STRING(buf, len) \ do { \ if (buf == NULL) { \ msgpack_pack_bin(packer, 0); \ @@ -1192,7 +810,7 @@ char *encode_tv2json(typval_T *tv, size_t *len) } \ } while (0) -#define CONV_STR_STRING(buf, len) \ +#define TYPVAL_ENCODE_CONV_STR_STRING(buf, len) \ do { \ if (buf == NULL) { \ msgpack_pack_str(packer, 0); \ @@ -1203,7 +821,7 @@ char *encode_tv2json(typval_T *tv, size_t *len) } \ } while (0) -#define CONV_EXT_STRING(buf, len, type) \ +#define TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type) \ do { \ if (buf == NULL) { \ msgpack_pack_ext(packer, 0, (int8_t) type); \ @@ -1214,30 +832,30 @@ char *encode_tv2json(typval_T *tv, size_t *len) } \ } while (0) -#define CONV_NUMBER(num) \ +#define TYPVAL_ENCODE_CONV_NUMBER(num) \ msgpack_pack_int64(packer, (int64_t) (num)) -#define CONV_FLOAT(flt) \ +#define TYPVAL_ENCODE_CONV_FLOAT(flt) \ msgpack_pack_double(packer, (double) (flt)) -#define CONV_FUNC(fun) \ +#define TYPVAL_ENCODE_CONV_FUNC(fun) \ return conv_error(_("E951: Error while dumping %s, %s: " \ "attempt to dump function reference"), \ mpstack, objname) -#define CONV_EMPTY_LIST() \ +#define TYPVAL_ENCODE_CONV_EMPTY_LIST() \ msgpack_pack_array(packer, 0) -#define CONV_LIST_START(lst) \ - msgpack_pack_array(packer, (size_t) (lst)->lv_len) +#define TYPVAL_ENCODE_CONV_LIST_START(len) \ + msgpack_pack_array(packer, (size_t) (len)) -#define CONV_EMPTY_DICT() \ +#define TYPVAL_ENCODE_CONV_EMPTY_DICT() \ msgpack_pack_map(packer, 0) -#define CONV_NIL() \ +#define TYPVAL_ENCODE_CONV_NIL() \ msgpack_pack_nil(packer) -#define CONV_BOOL(num) \ +#define TYPVAL_ENCODE_CONV_BOOL(num) \ do { \ if ((num)) { \ msgpack_pack_true(packer); \ @@ -1246,51 +864,51 @@ char *encode_tv2json(typval_T *tv, size_t *len) } \ } while (0) -#define CONV_UNSIGNED_NUMBER(num) \ +#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(num) \ msgpack_pack_uint64(packer, (num)) -#define CONV_DICT_START(len) \ +#define TYPVAL_ENCODE_CONV_DICT_START(len) \ msgpack_pack_map(packer, (size_t) (len)) -#define CONV_DICT_END() +#define TYPVAL_ENCODE_CONV_DICT_END() -#define CONV_DICT_AFTER_KEY() +#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY() -#define CONV_DICT_BETWEEN_ITEMS() +#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS() -#define CONV_SPECIAL_DICT_KEY_CHECK(name, kv_pair) +#define TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK(label, kv_pair) -#define CONV_LIST_END(lst) +#define TYPVAL_ENCODE_CONV_LIST_END() -#define CONV_LIST_BETWEEN_ITEMS() +#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS() -#define CONV_RECURSE(val, conv_type) \ +#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ return conv_error(_("E952: Unable to dump %s: " \ "container references itself in %s"), \ mpstack, objname) -#define CONV_ALLOW_SPECIAL true - -DEFINE_VIML_CONV_FUNCTIONS(, msgpack, msgpack_packer *const, packer) - -#undef CONV_STRING -#undef CONV_STR_STRING -#undef CONV_EXT_STRING -#undef CONV_NUMBER -#undef CONV_FLOAT -#undef CONV_FUNC -#undef CONV_EMPTY_LIST -#undef CONV_LIST_START -#undef CONV_EMPTY_DICT -#undef CONV_NIL -#undef CONV_BOOL -#undef CONV_UNSIGNED_NUMBER -#undef CONV_DICT_START -#undef CONV_DICT_END -#undef CONV_DICT_AFTER_KEY -#undef CONV_DICT_BETWEEN_ITEMS -#undef CONV_SPECIAL_DICT_KEY_CHECK -#undef CONV_LIST_END -#undef CONV_LIST_BETWEEN_ITEMS -#undef CONV_RECURSE -#undef CONV_ALLOW_SPECIAL +#define TYPVAL_ENCODE_ALLOW_SPECIALS true + +TYPVAL_ENCODE_DEFINE_CONV_FUNCTIONS(, msgpack, msgpack_packer *const, packer) + +#undef TYPVAL_ENCODE_CONV_STRING +#undef TYPVAL_ENCODE_CONV_STR_STRING +#undef TYPVAL_ENCODE_CONV_EXT_STRING +#undef TYPVAL_ENCODE_CONV_NUMBER +#undef TYPVAL_ENCODE_CONV_FLOAT +#undef TYPVAL_ENCODE_CONV_FUNC +#undef TYPVAL_ENCODE_CONV_EMPTY_LIST +#undef TYPVAL_ENCODE_CONV_LIST_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_DICT_END +#undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY +#undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS +#undef TYPVAL_ENCODE_CONV_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 diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h new file mode 100644 index 0000000000..f70a6c9e94 --- /dev/null +++ b/src/nvim/eval/typval_encode.h @@ -0,0 +1,563 @@ +/// @file eval/typval_convert.h +/// +/// Contains set of macros used to convert (possibly recursive) typval_T into +/// something else. For these macros to work the following macros must be +/// defined: + +/// @def TYPVAL_ENCODE_CONV_NIL +/// @brief Macros used to convert NIL value +/// +/// Is called both for special dictionary (unless #TYPVAL_ENCODE_ALLOW_SPECIALS +/// is false) and `v:null`. Accepts no arguments, but still must be +/// a function-like macros. + +/// @def TYPVAL_ENCODE_CONV_BOOL +/// @brief Macros used to convert boolean value +/// +/// Is called both for special dictionary (unless #TYPVAL_ENCODE_ALLOW_SPECIALS +/// is false) and `v:true`/`v:false`. +/// +/// @param num Boolean value to convert. Value is an expression which +/// evaluates to some integer. + +/// @def TYPVAL_ENCODE_CONV_NUMBER +/// @brief Macros used to convert integer +/// +/// @param num Integer to convert, must accept both varnumber_T and int64_t. + +/// @def TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER +/// @brief Macros used to convert unsigned integer +/// +/// Not used if #TYPVAL_ENCODE_ALLOW_SPECIALS is false, but still must be +/// defined. +/// +/// @param num Integer to convert, must accept uint64_t. + +/// @def TYPVAL_ENCODE_CONV_FLOAT +/// @brief Macros used to convert floating-point number +/// +/// @param flt Number to convert, must accept float_T. + +/// @def TYPVAL_ENCODE_CONV_STRING +/// @brief Macros used to convert plain string +/// +/// Is used to convert VAR_STRING objects as well as BIN strings represented as +/// special dictionary. +/// +/// @param buf String to convert. Is a char[] buffer, not NUL-terminated. +/// @param len String length. + +/// @def TYPVAL_ENCODE_CONV_STR_STRING +/// @brief Like #TYPVAL_ENCODE_CONV_STRING, but for STR strings +/// +/// Is used to convert dictionary keys and STR strings represented as special +/// dictionaries. + +/// @def TYPVAL_ENCODE_CONV_EXT_STRING +/// @brief Macros used to convert EXT string +/// +/// Is used to convert EXT strings represented as special dictionaries. Never +/// actually used if #TYPVAL_ENCODE_ALLOW_SPECIALS is false, but still must be +/// defined. +/// +/// @param buf String to convert. Is a char[] buffer, not NUL-terminated. +/// @param len String length. +/// @param type EXT type. + +/// @def TYPVAL_ENCODE_CONV_FUNC +/// @brief Macros used to convert a function reference +/// +/// @param fun Function name. + +/// @def TYPVAL_ENCODE_CONV_EMPTY_LIST +/// @brief Macros used to convert an empty list +/// +/// Accepts no arguments, but still must be a function-like macros. + +/// @def TYPVAL_ENCODE_CONV_EMPTY_DICT +/// @brief Macros used to convert an empty dictionary +/// +/// Accepts no arguments, but still must be a function-like macros. + +/// @def TYPVAL_ENCODE_CONV_LIST_START +/// @brief Macros used before starting to convert non-empty list +/// +/// @param len List length. Is an expression which evaluates to an integer. + +/// @def TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS +/// @brief Macros used after finishing converting non-last list item +/// +/// Accepts no arguments, but still must be a function-like macros. + +/// @def TYPVAL_ENCODE_CONV_LIST_END +/// @brief Macros used after converting non-empty list +/// +/// Accepts no arguments, but still must be a function-like macros. + +/// @def TYPVAL_ENCODE_CONV_DICT_START +/// @brief Macros used before starting to convert non-empty dictionary +/// +/// @param len Dictionary length. Is an expression which evaluates to an +/// integer. + +/// @def TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK +/// @brief Macros used to check special dictionary key +/// +/// @param label Label for goto in case check was not successfull. +/// @param kv_pair List with two elements: key and value. + +/// @def TYPVAL_ENCODE_CONV_DICT_AFTER_KEY +/// @brief Macros used after finishing converting dictionary key +/// +/// Accepts no arguments, but still must be a function-like macros. + +/// @def TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS +/// @brief Macros used after finishing converting non-last dictionary value +/// +/// Accepts no arguments, but still must be a function-like macros. + +/// @def TYPVAL_ENCODE_CONV_DICT_END +/// @brief Macros used after converting non-empty dictionary +/// +/// Accepts no arguments, but still must be a function-like macros. + +/// @def TYPVAL_ENCODE_CONV_RECURSE +/// @brief Macros used when self-containing container is detected +/// +/// @param val Container for which this situation was detected. +/// @param conv_type Type of the stack entry, @see MPConvStackValType. + +/// @def TYPVAL_ENCODE_ALLOW_SPECIALS +/// @brief Macros that specifies whether special dictionaries are special +/// +/// Must be something that evaluates to boolean, most likely `true` or `false`. +/// If it is false then special dictionaries are not treated specially. +#ifndef NVIM_EVAL_TYPVAL_ENCODE_H +#define NVIM_EVAL_TYPVAL_ENCODE_H + +#include <stddef.h> +#include <inttypes.h> +#include <assert.h> + +#include "nvim/lib/kvec.h" +#include "nvim/eval_defs.h" +#include "nvim/eval/encode.h" +#include "nvim/func_attr.h" + +/// Type of the stack entry +typedef enum { + kMPConvDict, ///< Convert dict_T *dictionary. + kMPConvList, ///< Convert list_T *list. + kMPConvPairs, ///< Convert mapping represented as a list_T* of pairs. +} MPConvStackValType; + +/// Structure representing current VimL to messagepack conversion state +typedef struct { + MPConvStackValType type; ///< Type of the stack entry. + union { + struct { + dict_T *dict; ///< Currently converted dictionary. + hashitem_T *hi; ///< Currently converted dictionary item. + size_t todo; ///< Amount of items left to process. + } d; ///< State of dictionary conversion. + struct { + list_T *list; ///< Currently converted list. + listitem_T *li; ///< Currently converted list item. + } l; ///< State of list or generic mapping conversion. + } data; ///< Data to convert. +} MPConvStackVal; + +/// Stack used to convert VimL values to messagepack. +typedef kvec_t(MPConvStackVal) MPConvStack; + +// Defines for MPConvStack +#define _mp_size kv_size +#define _mp_init kv_init +#define _mp_destroy kv_destroy +#define _mp_push kv_push +#define _mp_pop kv_pop +#define _mp_last kv_last + +/// Code for checking whether container references itself +/// +/// @param[in,out] val Container to check. +/// @param copyID_attr Name of the container attribute that holds copyID. +/// After checking whether value of this attribute is +/// copyID (variable) it is set to copyID. +#define _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(val, copyID_attr, conv_type) \ + do { \ + if ((val)->copyID_attr == copyID) { \ + TYPVAL_ENCODE_CONV_RECURSE((val), conv_type); \ + } \ + (val)->copyID_attr = copyID; \ + } while (0) + +/// Length of the string stored in typval_T +/// +/// @param[in] tv String for which to compute length for. Must be typval_T +/// with VAR_STRING. +/// +/// @return Length of the string stored in typval_T, including 0 for NULL +/// string. +static inline size_t tv_strlen(const typval_T *const tv) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT + FUNC_ATTR_NONNULL_ALL +{ + assert(tv->v_type == VAR_STRING); + return (tv->vval.v_string == NULL + ? 0 + : strlen((char *) tv->vval.v_string)); +} + +/// Define functions which convert VimL value to something else +/// +/// Creates function `vim_to_{name}(firstargtype firstargname, typval_T *const +/// tv)` which returns OK or FAIL and helper functions. +/// +/// @param scope Scope of the main function: either nothing or `static`. +/// @param firstargtype Type of the first argument. It will be used to return +/// the results. +/// @param firstargname Name of the first argument. +/// @param name Name of the target converter. +#define TYPVAL_ENCODE_DEFINE_CONV_FUNCTIONS(scope, name, firstargtype, \ + firstargname) \ +static int name##_convert_one_value(firstargtype firstargname, \ + MPConvStack *const mpstack, \ + typval_T *const tv, \ + const int copyID, \ + const char *const objname) \ + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT \ +{ \ + switch (tv->v_type) { \ + case VAR_STRING: { \ + TYPVAL_ENCODE_CONV_STRING(tv->vval.v_string, tv_strlen(tv)); \ + break; \ + } \ + case VAR_NUMBER: { \ + TYPVAL_ENCODE_CONV_NUMBER(tv->vval.v_number); \ + break; \ + } \ + case VAR_FLOAT: { \ + TYPVAL_ENCODE_CONV_FLOAT(tv->vval.v_float); \ + break; \ + } \ + case VAR_FUNC: { \ + TYPVAL_ENCODE_CONV_FUNC(tv->vval.v_string); \ + break; \ + } \ + case VAR_LIST: { \ + if (tv->vval.v_list == NULL || tv->vval.v_list->lv_len == 0) { \ + TYPVAL_ENCODE_CONV_EMPTY_LIST(); \ + break; \ + } \ + _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(tv->vval.v_list, lv_copyID, \ + kMPConvList); \ + TYPVAL_ENCODE_CONV_LIST_START(tv->vval.v_list->lv_len); \ + _mp_push(*mpstack, ((MPConvStackVal) { \ + .type = kMPConvList, \ + .data = { \ + .l = { \ + .list = tv->vval.v_list, \ + .li = tv->vval.v_list->lv_first, \ + }, \ + }, \ + })); \ + break; \ + } \ + case VAR_SPECIAL: { \ + switch (tv->vval.v_special) { \ + case kSpecialVarNull: { \ + TYPVAL_ENCODE_CONV_NIL(); \ + break; \ + } \ + case kSpecialVarTrue: \ + case kSpecialVarFalse: { \ + TYPVAL_ENCODE_CONV_BOOL(tv->vval.v_special == kSpecialVarTrue); \ + break; \ + } \ + } \ + break; \ + } \ + case VAR_DICT: { \ + if (tv->vval.v_dict == NULL \ + || tv->vval.v_dict->dv_hashtab.ht_used == 0) { \ + TYPVAL_ENCODE_CONV_EMPTY_DICT(); \ + break; \ + } \ + const dictitem_T *type_di; \ + const dictitem_T *val_di; \ + if (TYPVAL_ENCODE_ALLOW_SPECIALS \ + && tv->vval.v_dict->dv_hashtab.ht_used == 2 \ + && (type_di = dict_find((dict_T *) tv->vval.v_dict, \ + (char_u *) "_TYPE", -1)) != NULL \ + && type_di->di_tv.v_type == VAR_LIST \ + && (val_di = dict_find((dict_T *) tv->vval.v_dict, \ + (char_u *) "_VAL", -1)) != NULL) { \ + size_t i; \ + for (i = 0; i < ARRAY_SIZE(eval_msgpack_type_lists); i++) { \ + if (type_di->di_tv.vval.v_list == eval_msgpack_type_lists[i]) { \ + break; \ + } \ + } \ + if (i == ARRAY_SIZE(eval_msgpack_type_lists)) { \ + goto name##_convert_one_value_regular_dict; \ + } \ + switch ((MessagePackType) i) { \ + case kMPNil: { \ + TYPVAL_ENCODE_CONV_NIL(); \ + break; \ + } \ + case kMPBoolean: { \ + if (val_di->di_tv.v_type != VAR_NUMBER) { \ + goto name##_convert_one_value_regular_dict; \ + } \ + TYPVAL_ENCODE_CONV_BOOL(val_di->di_tv.vval.v_number); \ + break; \ + } \ + case kMPInteger: { \ + const list_T *val_list; \ + varnumber_T sign; \ + varnumber_T highest_bits; \ + varnumber_T high_bits; \ + varnumber_T low_bits; \ + /* List of 4 integers; first is signed (should be 1 or -1, but */ \ + /* this is not checked), second is unsigned and have at most */ \ + /* one (sign is -1) or two (sign is 1) non-zero bits (number of */ \ + /* bits is not checked), other unsigned and have at most 31 */ \ + /* non-zero bits (number of bits is not checked).*/ \ + if (val_di->di_tv.v_type != VAR_LIST \ + || (val_list = val_di->di_tv.vval.v_list) == NULL \ + || val_list->lv_len != 4 \ + || val_list->lv_first->li_tv.v_type != VAR_NUMBER \ + || (sign = val_list->lv_first->li_tv.vval.v_number) == 0 \ + || val_list->lv_first->li_next->li_tv.v_type != VAR_NUMBER \ + || (highest_bits = \ + val_list->lv_first->li_next->li_tv.vval.v_number) < 0 \ + || val_list->lv_last->li_prev->li_tv.v_type != VAR_NUMBER \ + || (high_bits = \ + val_list->lv_last->li_prev->li_tv.vval.v_number) < 0 \ + || val_list->lv_last->li_tv.v_type != VAR_NUMBER \ + || (low_bits = val_list->lv_last->li_tv.vval.v_number) < 0) { \ + goto name##_convert_one_value_regular_dict; \ + } \ + uint64_t number = ((uint64_t) (((uint64_t) highest_bits) << 62) \ + | (uint64_t) (((uint64_t) high_bits) << 31) \ + | (uint64_t) low_bits); \ + if (sign > 0) { \ + TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(number); \ + } else { \ + TYPVAL_ENCODE_CONV_NUMBER(-number); \ + } \ + break; \ + } \ + case kMPFloat: { \ + if (val_di->di_tv.v_type != VAR_FLOAT) { \ + goto name##_convert_one_value_regular_dict; \ + } \ + TYPVAL_ENCODE_CONV_FLOAT(val_di->di_tv.vval.v_float); \ + break; \ + } \ + case kMPString: \ + case kMPBinary: { \ + const bool is_string = ((MessagePackType) i == kMPString); \ + if (val_di->di_tv.v_type != VAR_LIST) { \ + goto name##_convert_one_value_regular_dict; \ + } \ + size_t len; \ + char *buf; \ + if (!encode_vim_list_to_buf(val_di->di_tv.vval.v_list, &len, \ + &buf)) { \ + goto name##_convert_one_value_regular_dict; \ + } \ + if (is_string) { \ + TYPVAL_ENCODE_CONV_STR_STRING(buf, len); \ + } else { \ + TYPVAL_ENCODE_CONV_STRING(buf, len); \ + } \ + xfree(buf); \ + break; \ + } \ + case kMPArray: { \ + if (val_di->di_tv.v_type != VAR_LIST) { \ + goto name##_convert_one_value_regular_dict; \ + } \ + _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(val_di->di_tv.vval.v_list, \ + lv_copyID, kMPConvList); \ + TYPVAL_ENCODE_CONV_LIST_START(val_di->di_tv.vval.v_list->lv_len); \ + _mp_push(*mpstack, ((MPConvStackVal) { \ + .type = kMPConvList, \ + .data = { \ + .l = { \ + .list = val_di->di_tv.vval.v_list, \ + .li = val_di->di_tv.vval.v_list->lv_first, \ + }, \ + }, \ + })); \ + break; \ + } \ + case kMPMap: { \ + if (val_di->di_tv.v_type != VAR_LIST) { \ + goto name##_convert_one_value_regular_dict; \ + } \ + list_T *const val_list = val_di->di_tv.vval.v_list; \ + if (val_list == NULL || val_list->lv_len == 0) { \ + TYPVAL_ENCODE_CONV_EMPTY_DICT(); \ + break; \ + } \ + for (const listitem_T *li = val_list->lv_first; li != NULL; \ + li = li->li_next) { \ + if (li->li_tv.v_type != VAR_LIST \ + || li->li_tv.vval.v_list->lv_len != 2) { \ + goto name##_convert_one_value_regular_dict; \ + } \ + } \ + _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(val_list, lv_copyID, \ + kMPConvPairs); \ + TYPVAL_ENCODE_CONV_DICT_START(val_list->lv_len); \ + _mp_push(*mpstack, ((MPConvStackVal) { \ + .type = kMPConvPairs, \ + .data = { \ + .l = { \ + .list = val_list, \ + .li = val_list->lv_first, \ + }, \ + }, \ + })); \ + break; \ + } \ + case kMPExt: { \ + const list_T *val_list; \ + varnumber_T type; \ + if (val_di->di_tv.v_type != VAR_LIST \ + || (val_list = val_di->di_tv.vval.v_list) == NULL \ + || val_list->lv_len != 2 \ + || (val_list->lv_first->li_tv.v_type != VAR_NUMBER) \ + || (type = val_list->lv_first->li_tv.vval.v_number) > INT8_MAX \ + || type < INT8_MIN \ + || (val_list->lv_last->li_tv.v_type != VAR_LIST)) { \ + goto name##_convert_one_value_regular_dict; \ + } \ + size_t len; \ + char *buf; \ + if (!encode_vim_list_to_buf(val_list->lv_last->li_tv.vval.v_list, \ + &len, &buf)) { \ + goto name##_convert_one_value_regular_dict; \ + } \ + TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type); \ + xfree(buf); \ + break; \ + } \ + } \ + break; \ + } \ +name##_convert_one_value_regular_dict: \ + _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(tv->vval.v_dict, dv_copyID, \ + kMPConvDict); \ + TYPVAL_ENCODE_CONV_DICT_START(tv->vval.v_dict->dv_hashtab.ht_used); \ + _mp_push(*mpstack, ((MPConvStackVal) { \ + .type = kMPConvDict, \ + .data = { \ + .d = { \ + .dict = tv->vval.v_dict, \ + .hi = tv->vval.v_dict->dv_hashtab.ht_array, \ + .todo = tv->vval.v_dict->dv_hashtab.ht_used, \ + }, \ + }, \ + })); \ + break; \ + } \ + case VAR_UNKNOWN: { \ + EMSG2(_(e_intern2), #name "_convert_one_value()"); \ + return FAIL; \ + } \ + } \ + return OK; \ +} \ +\ +scope int encode_vim_to_##name(firstargtype firstargname, typval_T *const tv, \ + const char *const objname) \ + FUNC_ATTR_WARN_UNUSED_RESULT \ +{ \ + const int copyID = get_copyID(); \ + MPConvStack mpstack; \ + _mp_init(mpstack); \ + if (name##_convert_one_value(firstargname, &mpstack, tv, copyID, objname) \ + == FAIL) { \ + goto encode_vim_to_##name##_error_ret; \ + } \ + while (_mp_size(mpstack)) { \ + MPConvStackVal *cur_mpsv = &_mp_last(mpstack); \ + typval_T *cur_tv = NULL; \ + switch (cur_mpsv->type) { \ + case kMPConvDict: { \ + if (!cur_mpsv->data.d.todo) { \ + (void) _mp_pop(mpstack); \ + cur_mpsv->data.d.dict->dv_copyID = copyID - 1; \ + TYPVAL_ENCODE_CONV_DICT_END(); \ + continue; \ + } else if (cur_mpsv->data.d.todo \ + != cur_mpsv->data.d.dict->dv_hashtab.ht_used) { \ + TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(); \ + } \ + while (HASHITEM_EMPTY(cur_mpsv->data.d.hi)) { \ + cur_mpsv->data.d.hi++; \ + } \ + dictitem_T *const di = HI2DI(cur_mpsv->data.d.hi); \ + cur_mpsv->data.d.todo--; \ + cur_mpsv->data.d.hi++; \ + TYPVAL_ENCODE_CONV_STR_STRING(&di->di_key[0], \ + strlen((char *) &di->di_key[0])); \ + TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(); \ + cur_tv = &di->di_tv; \ + break; \ + } \ + case kMPConvList: { \ + if (cur_mpsv->data.l.li == NULL) { \ + (void) _mp_pop(mpstack); \ + cur_mpsv->data.l.list->lv_copyID = copyID - 1; \ + TYPVAL_ENCODE_CONV_LIST_END(); \ + continue; \ + } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { \ + TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(); \ + } \ + cur_tv = &cur_mpsv->data.l.li->li_tv; \ + cur_mpsv->data.l.li = cur_mpsv->data.l.li->li_next; \ + break; \ + } \ + case kMPConvPairs: { \ + if (cur_mpsv->data.l.li == NULL) { \ + (void) _mp_pop(mpstack); \ + cur_mpsv->data.l.list->lv_copyID = copyID - 1; \ + TYPVAL_ENCODE_CONV_DICT_END(); \ + continue; \ + } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { \ + TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(); \ + } \ + const list_T *const kv_pair = cur_mpsv->data.l.li->li_tv.vval.v_list; \ + TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK( \ + encode_vim_to_##name##_error_ret, kv_pair); \ + if (name##_convert_one_value(firstargname, &mpstack, \ + &kv_pair->lv_first->li_tv, copyID, \ + objname) == FAIL) { \ + goto encode_vim_to_##name##_error_ret; \ + } \ + TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(); \ + cur_tv = &kv_pair->lv_last->li_tv; \ + cur_mpsv->data.l.li = cur_mpsv->data.l.li->li_next; \ + break; \ + } \ + } \ + assert(cur_tv != NULL); \ + if (name##_convert_one_value(firstargname, &mpstack, cur_tv, copyID, \ + objname) == FAIL) { \ + goto encode_vim_to_##name##_error_ret; \ + } \ + } \ + _mp_destroy(mpstack); \ + return OK; \ +encode_vim_to_##name##_error_ret: \ + _mp_destroy(mpstack); \ + return FAIL; \ +} + +#endif // NVIM_EVAL_TYPVAL_ENCODE_H diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index 9bb62891c7..0a4cbe724e 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -9,7 +9,7 @@ #include "nvim/event/wstream.h" #include "nvim/event/process.h" #include "nvim/event/libuv_process.h" -#include "nvim/event/pty_process.h" +#include "nvim/os/pty_process.h" #include "nvim/globals.h" #include "nvim/log.h" diff --git a/src/nvim/event/time.c b/src/nvim/event/time.c index 7bf333bcea..f68a66345f 100644 --- a/src/nvim/event/time.c +++ b/src/nvim/event/time.c @@ -17,6 +17,7 @@ void time_watcher_init(Loop *loop, TimeWatcher *watcher, void *data) watcher->uv.data = watcher; watcher->data = data; watcher->events = loop->fast_events; + watcher->blockable = false; } void time_watcher_start(TimeWatcher *watcher, time_cb cb, uint64_t timeout, @@ -50,6 +51,10 @@ static void time_watcher_cb(uv_timer_t *handle) FUNC_ATTR_NONNULL_ALL { TimeWatcher *watcher = handle->data; + if (watcher->blockable && !queue_empty(watcher->events)) { + // the timer blocked and there already is an unprocessed event waiting + return; + } CREATE_EVENT(watcher->events, time_event, 1, watcher); } diff --git a/src/nvim/event/time.h b/src/nvim/event/time.h index 7882b2b627..14df176ea3 100644 --- a/src/nvim/event/time.h +++ b/src/nvim/event/time.h @@ -13,6 +13,7 @@ struct time_watcher { void *data; time_cb cb, close_cb; Queue *events; + bool blockable; }; #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index 04fd88cc8d..6c58879d58 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -88,7 +88,7 @@ return { }, { command='argadd', - flags=bit.bor(BANG, NEEDARG, RANGE, NOTADR, ZEROR, FILES, TRLBAR), + flags=bit.bor(BANG, RANGE, NOTADR, ZEROR, FILES, TRLBAR), addr_type=ADDR_ARGUMENTS, func='ex_argadd', }, diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 5fe6209a0a..df4a6d52c4 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -1616,9 +1616,15 @@ do_arglist ( char_u *p; int match; - /* - * Collect all file name arguments in "new_ga". - */ + // Set default argument for ":argadd" command. + if (what == AL_ADD && *str == NUL) { + if (curbuf->b_ffname == NULL) { + return FAIL; + } + str = curbuf->b_fname; + } + + // Collect all file name arguments in "new_ga". get_arglist(&new_ga, str); if (what == AL_DEL) { @@ -1990,11 +1996,17 @@ void ex_argdelete(exarg_T *eap) } else if (curwin->w_arg_idx > eap->line1) { curwin->w_arg_idx = (int)eap->line1; } + if (ARGCOUNT == 0) { + curwin->w_arg_idx = 0; + } else if (curwin->w_arg_idx >= ARGCOUNT) { + curwin->w_arg_idx = ARGCOUNT - 1; + } } - } else if (*eap->arg == NUL) + } else if (*eap->arg == NUL) { EMSG(_(e_argreq)); - else + } else { do_arglist(eap->arg, AL_DEL, 0); + } maketitle(); } @@ -2221,6 +2233,7 @@ alist_add_list ( int after /* where to add: 0 = before first one */ ) { + int old_argcount = ARGCOUNT; ga_grow(&ALIST(curwin)->al_ga, count); { if (after < 0) @@ -2235,8 +2248,9 @@ alist_add_list ( ARGLIST[after + i].ae_fnum = buflist_add(files[i], BLN_LISTED); } ALIST(curwin)->al_ga.ga_len += count; - if (curwin->w_arg_idx >= after) - ++curwin->w_arg_idx; + if (old_argcount > 0 && curwin->w_arg_idx >= after) { + curwin->w_arg_idx += count; + } return after; } } @@ -2481,32 +2495,31 @@ int source_level(void *cookie) return ((struct source_cookie *)cookie)->level; } - -#if (defined(WIN32) && defined(FEAT_CSCOPE)) || defined(HAVE_FD_CLOEXEC) -# define USE_FOPEN_NOINH -/* - * Special function to open a file without handle inheritance. - * When possible the handle is closed on exec(). - */ +/// Special function to open a file without handle inheritance. +/// If possible the handle is closed on exec(). static FILE *fopen_noinh_readbin(char *filename) { +#ifdef WIN32 + int fd_tmp = os_open(filename, O_RDONLY | O_BINARY | O_NOINHERIT, 0); +#else int fd_tmp = os_open(filename, O_RDONLY, 0); +#endif - if (fd_tmp < 0) + if (fd_tmp < 0) { return NULL; + } -# ifdef HAVE_FD_CLOEXEC +#ifdef HAVE_FD_CLOEXEC { int fdflags = fcntl(fd_tmp, F_GETFD); if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) { (void)fcntl(fd_tmp, F_SETFD, fdflags | FD_CLOEXEC); } } -# endif +#endif return fdopen(fd_tmp, READBIN); } -#endif /* @@ -2560,11 +2573,7 @@ do_source ( /* Apply SourcePre autocommands, they may get the file. */ apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf); -#ifdef USE_FOPEN_NOINH cookie.fp = fopen_noinh_readbin((char *)fname_exp); -#else - cookie.fp = mch_fopen((char *)fname_exp, READBIN); -#endif if (cookie.fp == NULL && check_other) { /* * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa, @@ -2573,15 +2582,8 @@ do_source ( p = path_tail(fname_exp); if ((*p == '.' || *p == '_') && (STRICMP(p + 1, "nvimrc") == 0 || STRICMP(p + 1, "exrc") == 0)) { - if (*p == '_') - *p = '.'; - else - *p = '_'; -#ifdef USE_FOPEN_NOINH + *p = (*p == '_') ? '.' : '_'; cookie.fp = fopen_noinh_readbin((char *)fname_exp); -#else - cookie.fp = mch_fopen((char *)fname_exp, READBIN); -#endif } } diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 870284a0f7..b66b5cf3a9 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6865,6 +6865,9 @@ void post_chdir(CdScope scope) curwin->w_localdir = vim_strsave(NameBuff); } break; + case kCdScopeInvalid: + // We should never get here + assert(false); } shorten_fnames(TRUE); @@ -6989,10 +6992,10 @@ static void ex_sleep(exarg_T *eap) */ void do_sleep(long msec) { - long done; ui_flush(); // flush before waiting - for (done = 0; !got_int && done < msec; done += 1000L) { - os_delay(msec - done > 1000L ? 1000L : msec - done, true); + for (long left = msec; !got_int && left > 0; left -= 1000L) { + int next = left > 1000l ? 1000 : (int)left; + LOOP_PROCESS_EVENTS_UNTIL(&main_loop, main_loop.events, (int)next, got_int); os_breakcheck(); } } @@ -7855,19 +7858,26 @@ static void ex_stopinsert(exarg_T *eap) */ void exec_normal_cmd(char_u *cmd, int remap, bool silent) { + // Stuff the argument into the typeahead buffer. + ins_typebuf(cmd, remap, 0, true, silent); + exec_normal(false); +} + +/// Execute normal_cmd() until there is no typeahead left. +/// +/// @param was_typed whether or not something was typed +void exec_normal(bool was_typed) +{ oparg_T oa; - /* - * Stuff the argument into the typeahead buffer. - * Execute normal_cmd() until there is no typeahead left. - */ clear_oparg(&oa); - finish_op = FALSE; - ins_typebuf(cmd, remap, 0, TRUE, silent); - while ((!stuff_empty() || (!typebuf_typed() && typebuf.tb_len > 0)) + finish_op = false; + while ((!stuff_empty() + || ((was_typed || !typebuf_typed()) + && typebuf.tb_len > 0)) && !got_int) { update_topline_cursor(); - normal_cmd(&oa, TRUE); /* execute a Normal mode cmd */ + normal_cmd(&oa, true); // execute a Normal mode cmd } } diff --git a/src/nvim/ex_docmd.h b/src/nvim/ex_docmd.h index dbfc64e2f1..bafad20169 100644 --- a/src/nvim/ex_docmd.h +++ b/src/nvim/ex_docmd.h @@ -26,6 +26,7 @@ /// `getcwd()`. When using scopes as limits (e.g. in loops) don't use the scopes /// directly, use `MIN_CD_SCOPE` and `MAX_CD_SCOPE` instead. typedef enum { + kCdScopeInvalid = -1, kCdScopeWindow, ///< Affects one window. kCdScopeTab, ///< Affects one tab page. kCdScopeGlobal, ///< Affects the entire instance of Neovim. diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index a4e5a4dcd7..65144dace8 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -358,7 +358,8 @@ static int command_line_execute(VimState *state, int key) s->c = key; if (s->c == K_EVENT) { - queue_process_events(loop.events); + queue_process_events(main_loop.events); + redrawcmdline(); return 1; } diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index beefc4238e..f7555c99fa 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -1378,7 +1378,7 @@ find_file_in_path_option ( /* copy file name into NameBuff, expanding environment variables */ save_char = ptr[len]; ptr[len] = NUL; - expand_env(ptr, NameBuff, MAXPATHL); + expand_env_esc(ptr, NameBuff, MAXPATHL, false, true, NULL); ptr[len] = save_char; xfree(ff_file_to_find); diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index db1469db97..4d9e10fb85 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -1749,8 +1749,9 @@ failed: #ifdef HAVE_FD_CLOEXEC else { int fdflags = fcntl(fd, F_GETFD); - if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) - fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC); + if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) { + (void)fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC); + } } #endif xfree(buffer); diff --git a/src/nvim/func_attr.h b/src/nvim/func_attr.h index c31d21ec6d..af8558d40d 100644 --- a/src/nvim/func_attr.h +++ b/src/nvim/func_attr.h @@ -179,7 +179,8 @@ #endif #ifdef DEFINE_FUNC_ATTRIBUTES - #define FUNC_ATTR_ASYNC + #define FUNC_API_ASYNC + #define FUNC_API_NOEXPORT #define FUNC_ATTR_MALLOC REAL_FATTR_MALLOC #define FUNC_ATTR_ALLOC_SIZE(x) REAL_FATTR_ALLOC_SIZE(x) #define FUNC_ATTR_ALLOC_SIZE_PROD(x,y) REAL_FATTR_ALLOC_SIZE_PROD(x,y) diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index dbf0322d78..ae1857f318 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1754,10 +1754,11 @@ static int vgetorpeek(int advance) || ((compl_cont_status & CONT_LOCAL) && (c1 == Ctrl_N || c1 == Ctrl_P))) ) { - if (c1 == K_SPECIAL) + if (c1 == K_SPECIAL) { nolmaplen = 2; - else { - LANGMAP_ADJUST(c1, (State & (CMDLINE | INSERT)) == 0); + } else { + LANGMAP_ADJUST(c1, (State & (CMDLINE | INSERT)) == 0 + && get_real_state() != SELECTMODE); nolmaplen = 0; } /* First try buffer-local mappings. */ diff --git a/src/nvim/globals.h b/src/nvim/globals.h index dafb75ca87..f618e5ffc4 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -1243,7 +1243,6 @@ EXTERN char *ignoredp; // If a msgpack-rpc channel should be started over stdin/stdout EXTERN bool embedded_mode INIT(= false); -EXTERN Loop loop; /// Used to track the status of external functions. /// Currently only used for iconv(). diff --git a/src/nvim/lib/kvec.h b/src/nvim/lib/kvec.h index b41ef0cc9f..36c91c86b2 100644 --- a/src/nvim/lib/kvec.h +++ b/src/nvim/lib/kvec.h @@ -1,59 +1,61 @@ -/* The MIT License - - Copyright (c) 2008, by Attractive Chaos <attractor@live.co.uk> - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - -/* - An example: - -#include "kvec.h" -int main() { - kvec_t(int) array; - kv_init(array); - kv_push(int, array, 10); // append - kv_a(int, array, 20) = 5; // dynamic - kv_A(array, 20) = 4; // static - kv_destroy(array); - return 0; -} -*/ - -/* - 2008-09-22 (0.1.0): +// The MIT License +// +// Copyright (c) 2008, by Attractive Chaos <attractor@live.co.uk> +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// An example: +// +// #include "kvec.h" +// int main() { +// kvec_t(int) array = KV_INITIAL_VALUE; +// kv_push(array, 10); // append +// kv_a(array, 20) = 5; // dynamic +// kv_A(array, 20) = 4; // static +// kv_destroy(array); +// return 0; +// } + +#ifndef NVIM_LIB_KVEC_H +#define NVIM_LIB_KVEC_H - * The initial version. +#include <stdlib.h> +#include <string.h> -*/ +#include "nvim/memory.h" -#ifndef AC_KVEC_H -#define AC_KVEC_H +#define kv_roundup32(x) \ + ((--(x)), \ + ((x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16), \ + (++(x))) -#include <stdlib.h> -#include "nvim/memory.h" +#define KV_INITIAL_VALUE { .size = 0, .capacity = 0, .items = NULL } -#define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) +#define kvec_t(type) \ + struct { \ + size_t size; \ + size_t capacity; \ + type *items; \ + } -#define kvec_t(type) struct { size_t size, capacity; type *items; } #define kv_init(v) ((v).size = (v).capacity = 0, (v).items = 0) #define kv_destroy(v) xfree((v).items) #define kv_A(v, i) ((v).items[(i)]) @@ -62,31 +64,130 @@ int main() { #define kv_max(v) ((v).capacity) #define kv_last(v) kv_A(v, kv_size(v) - 1) -#define kv_resize(type, v, s) ((v).capacity = (s), (v).items = (type*)xrealloc((v).items, sizeof(type) * (v).capacity)) - -#define kv_copy(type, v1, v0) do { \ - if ((v1).capacity < (v0).size) kv_resize(type, v1, (v0).size); \ - (v1).size = (v0).size; \ - memcpy((v1).items, (v0).items, sizeof(type) * (v0).size); \ - } while (0) \ - -#define kv_push(type, v, x) do { \ - if ((v).size == (v).capacity) { \ - (v).capacity = (v).capacity? (v).capacity<<1 : 8; \ - (v).items = (type*)xrealloc((v).items, sizeof(type) * (v).capacity); \ - } \ - (v).items[(v).size++] = (x); \ - } while (0) - -#define kv_pushp(type, v) ((((v).size == (v).capacity)? \ - ((v).capacity = ((v).capacity? (v).capacity<<1 : 8), \ - (v).items = (type*)xrealloc((v).items, sizeof(type) * (v).capacity), 0) \ - : 0), ((v).items + ((v).size++))) - -#define kv_a(type, v, i) (((v).capacity <= (size_t)(i)? \ - ((v).capacity = (v).size = (i) + 1, kv_roundup32((v).capacity), \ - (v).items = (type*)xrealloc((v).items, sizeof(type) * (v).capacity), 0) \ - : (v).size <= (size_t)(i)? (v).size = (i) + 1 \ - : 0), (v).items[(i)]) - -#endif +#define kv_resize(v, s) \ + ((v).capacity = (s), \ + (v).items = xrealloc((v).items, sizeof((v).items[0]) * (v).capacity)) + +#define kv_resize_full(v) \ + kv_resize(v, (v).capacity ? (v).capacity << 1 : 8) + +#define kv_copy(v1, v0) \ + do { \ + if ((v1).capacity < (v0).size) { \ + kv_resize(v1, (v0).size); \ + } \ + (v1).size = (v0).size; \ + memcpy((v1).items, (v0).items, sizeof((v1).items[0]) * (v0).size); \ + } while (0) \ + +#define kv_pushp(v) \ + ((((v).size == (v).capacity) ? (kv_resize_full(v), 0) : 0), \ + ((v).items + ((v).size++))) + +#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, \ + kv_roundup32((v).capacity), \ + kv_resize((v), (v).capacity), 0) \ + : ((v).size <= (size_t) (i) \ + ? (v).size = (i) + 1 \ + : 0)), \ + (v).items[(i)]) + +/// Type of a vector with a few first members allocated on stack +/// +/// Is compatible with #kv_A, #kv_pop, #kv_size, #kv_max, #kv_last. +/// Is not compatible with #kv_resize, #kv_resize_full, #kv_copy, #kv_push, +/// #kv_pushp, #kv_a, #kv_destroy. +/// +/// @param[in] type Type of vector elements. +/// @param[in] init_size Number of the elements in the initial array. +#define kvec_withinit_t(type, INIT_SIZE) \ + struct { \ + size_t size; \ + size_t capacity; \ + type *items; \ + type init_array[INIT_SIZE]; \ + } + +/// Initialize vector with preallocated array +/// +/// @param[out] v Vector to initialize. +#define kvi_init(v) \ + ((v).capacity = ARRAY_SIZE((v).init_array), \ + (v).size = 0, \ + (v).items = (v).init_array) + +/// Move data to a new destination and free source +static inline void *_memcpy_free(void *const restrict dest, + void *const restrict src, + const size_t size) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_ALWAYS_INLINE +{ + memcpy(dest, src, size); + xfree(src); + return dest; +} + +/// Resize vector with preallocated array +/// +/// @param[out] v Vector to resize. +/// @param[in] s New size. +#define kvi_resize(v, s) \ + ((v).capacity = ((s) > ARRAY_SIZE((v).init_array) \ + ? (s) \ + : ARRAY_SIZE((v).init_array)), \ + (v).items = ((v).capacity == ARRAY_SIZE((v).init_array) \ + ? ((v).items == (v).init_array \ + ? (v).items \ + : _memcpy_free((v).init_array, (v).items, \ + (v).size * sizeof((v).items[0]))) \ + : ((v).items == (v).init_array \ + ? memcpy(xmalloc((v).capacity * sizeof((v).items[0])), \ + (v).items, \ + (v).size * sizeof((v).items[0])) \ + : xrealloc((v).items, \ + (v).capacity * sizeof((v).items[0]))))) + +/// Resize vector with preallocated array when it is full +/// +/// @param[out] v Vector to resize. +#define kvi_resize_full(v) \ + /* ARRAY_SIZE((v).init_array) is the minimal capacity of this vector. */ \ + /* Thus when vector is full capacity may not be zero and it is safe */ \ + /* not to bother with checking whether (v).capacity is 0. But now */ \ + /* capacity is not guaranteed to have size that is a power of 2. */ \ + kvi_resize(v, ((v).capacity == ARRAY_SIZE((v).init_array) \ + ? ((v).capacity++, kv_roundup32((v).capacity)) \ + : (v).capacity << 1)) + +/// Get location where to store new element to a vector with preallocated array +/// +/// @param[in,out] v Vector to push to. +/// +/// @return Pointer to the place where new value should be stored. +#define kvi_pushp(v) \ + ((((v).size == (v).capacity) ? (kvi_resize_full(v), 0) : 0), \ + ((v).items + ((v).size++))) + +/// Push value to a vector with preallocated array +/// +/// @param[out] v Vector to push to. +/// @param[in] x Value to push. +#define kvi_push(v, x) \ + (*kvi_pushp(v) = (x)) + +/// Free array of elements of a vector with preallocated array if needed +/// +/// @param[out] v Vector to free. +#define kvi_destroy(v) \ + do { \ + if ((v).items != (v).init_array) { \ + xfree((v).items); \ + } \ + } while (0) + +#endif // NVIM_LIB_KVEC_H diff --git a/src/nvim/lib/queue.h b/src/nvim/lib/queue.h index fe02b454ea..fc322978b0 100644 --- a/src/nvim/lib/queue.h +++ b/src/nvim/lib/queue.h @@ -1,92 +1,94 @@ -/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ +// Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl> +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -#ifndef QUEUE_H_ -#define QUEUE_H_ +#ifndef NVIM_LIB_QUEUE_H +#define NVIM_LIB_QUEUE_H -typedef void *QUEUE[2]; +#include <stddef.h> -/* Private macros. */ -#define QUEUE_NEXT(q) (*(QUEUE **) &((*(q))[0])) -#define QUEUE_PREV(q) (*(QUEUE **) &((*(q))[1])) -#define QUEUE_PREV_NEXT(q) (QUEUE_NEXT(QUEUE_PREV(q))) -#define QUEUE_NEXT_PREV(q) (QUEUE_PREV(QUEUE_NEXT(q))) +#include "nvim/func_attr.h" -/* Public macros. */ -#define QUEUE_DATA(ptr, type, field) \ - ((type *) ((char *) (ptr) - ((char *) &((type *) 0)->field))) +typedef struct _queue { + struct _queue *next; + struct _queue *prev; +} QUEUE; -#define QUEUE_FOREACH(q, h) \ - for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q)) +// Public macros. +#define QUEUE_DATA(ptr, type, field) \ + ((type *)((char *)(ptr) - offsetof(type, field))) -#define QUEUE_EMPTY(q) \ - ((const QUEUE *) (q) == (const QUEUE *) QUEUE_NEXT(q)) +#define QUEUE_FOREACH(q, h) \ + for ( /* NOLINT(readability/braces) */ \ + (q) = (h)->next; (q) != (h); (q) = (q)->next) -#define QUEUE_HEAD(q) \ - (QUEUE_NEXT(q)) +// ffi.cdef is unable to swallow `bool` in place of `int` here. +static inline int QUEUE_EMPTY(const QUEUE *const q) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + return q == q->next; +} -#define QUEUE_INIT(q) \ - do { \ - QUEUE_NEXT(q) = (q); \ - QUEUE_PREV(q) = (q); \ - } \ - while (0) +#define QUEUE_HEAD(q) (q)->next -#define QUEUE_ADD(h, n) \ - do { \ - QUEUE_PREV_NEXT(h) = QUEUE_NEXT(n); \ - QUEUE_NEXT_PREV(n) = QUEUE_PREV(h); \ - QUEUE_PREV(h) = QUEUE_PREV(n); \ - QUEUE_PREV_NEXT(h) = (h); \ - } \ - while (0) +static inline void QUEUE_INIT(QUEUE *const q) FUNC_ATTR_ALWAYS_INLINE +{ + q->next = q; + q->prev = q; +} -#define QUEUE_SPLIT(h, q, n) \ - do { \ - QUEUE_PREV(n) = QUEUE_PREV(h); \ - QUEUE_PREV_NEXT(n) = (n); \ - QUEUE_NEXT(n) = (q); \ - QUEUE_PREV(h) = QUEUE_PREV(q); \ - QUEUE_PREV_NEXT(h) = (h); \ - QUEUE_PREV(q) = (n); \ - } \ - while (0) +static inline void QUEUE_ADD(QUEUE *const h, QUEUE *const n) + FUNC_ATTR_ALWAYS_INLINE +{ + h->prev->next = n->next; + n->next->prev = h->prev; + h->prev = n->prev; + h->prev->next = h; +} -#define QUEUE_INSERT_HEAD(h, q) \ - do { \ - QUEUE_NEXT(q) = QUEUE_NEXT(h); \ - QUEUE_PREV(q) = (h); \ - QUEUE_NEXT_PREV(q) = (q); \ - QUEUE_NEXT(h) = (q); \ - } \ - while (0) +static inline void QUEUE_SPLIT(QUEUE *const h, QUEUE *const q, QUEUE *const n) + FUNC_ATTR_ALWAYS_INLINE +{ + n->prev = h->prev; + n->prev->next = n; + n->next = q; + h->prev = q->prev; + h->prev->next = h; + q->prev = n; +} -#define QUEUE_INSERT_TAIL(h, q) \ - do { \ - QUEUE_NEXT(q) = (h); \ - QUEUE_PREV(q) = QUEUE_PREV(h); \ - QUEUE_PREV_NEXT(q) = (q); \ - QUEUE_PREV(h) = (q); \ - } \ - while (0) +static inline void QUEUE_INSERT_HEAD(QUEUE *const h, QUEUE *const q) + FUNC_ATTR_ALWAYS_INLINE +{ + q->next = h->next; + q->prev = h; + q->next->prev = q; + h->next = q; +} -#define QUEUE_REMOVE(q) \ - do { \ - QUEUE_PREV_NEXT(q) = QUEUE_NEXT(q); \ - QUEUE_NEXT_PREV(q) = QUEUE_PREV(q); \ - } \ - while (0) +static inline void QUEUE_INSERT_TAIL(QUEUE *const h, QUEUE *const q) + FUNC_ATTR_ALWAYS_INLINE +{ + q->next = h; + q->prev = h->prev; + q->prev->next = q; + h->prev = q; +} -#endif /* QUEUE_H_ */ +static inline void QUEUE_REMOVE(QUEUE *const q) FUNC_ATTR_ALWAYS_INLINE +{ + q->prev->next = q->next; + q->next->prev = q->prev; +} + +#endif // NVIM_LIB_QUEUE_H diff --git a/src/nvim/log.c b/src/nvim/log.c index 773d497881..c31af6b287 100644 --- a/src/nvim/log.c +++ b/src/nvim/log.c @@ -10,7 +10,14 @@ #include "nvim/os/os.h" #include "nvim/os/time.h" -#define USR_LOG_FILE "$HOME" _PATHSEPSTR ".nvimlog" +/// First location of the log file used by log_path_init() +#define USR_LOG_FILE "$NVIM_LOG_FILE" + +/// Fall back location of the log file used by log_path_init() +#define USR_LOG_FILE_2 "$HOME" _PATHSEPSTR ".nvimlog" + +/// Cached location of the log file set by log_path_init() +static char expanded_log_file_path[MAXPATHL + 1] = { 0 }; static uv_mutex_t mutex; @@ -18,6 +25,35 @@ static uv_mutex_t mutex; # include "log.c.generated.h" #endif +/// Initialize path to log file +/// +/// Tries to use #USR_LOG_FILE, then falls back #USR_LOG_FILE_2. Path to log +/// file is cached, so only the first call has effect, unless first call was not +/// successful. To make initialization not succeed either a bug in expand_env() +/// is needed or both `$NVIM_LOG_FILE` and `$HOME` environment variables +/// undefined. +/// +/// @return true if path was initialized, false otherwise. +static bool log_path_init(void) +{ + if (expanded_log_file_path[0]) { + return true; + } + expand_env((char_u *)USR_LOG_FILE, (char_u *)expanded_log_file_path, + sizeof(expanded_log_file_path) - 1); + // if the log file path expansion failed then fall back to stderr + if (strcmp(USR_LOG_FILE, expanded_log_file_path) == 0) { + memset(expanded_log_file_path, 0, sizeof(expanded_log_file_path)); + expand_env((char_u *)USR_LOG_FILE_2, (char_u *)expanded_log_file_path, + sizeof(expanded_log_file_path) - 1); + if (strcmp(USR_LOG_FILE_2, expanded_log_file_path) == 0) { + memset(expanded_log_file_path, 0, sizeof(expanded_log_file_path)); + return false; + } + } + return true; +} + void log_init(void) { uv_mutex_init(&mutex); @@ -73,30 +109,17 @@ FILE *open_log_file(void) return stderr; } - // expand USR_LOG_FILE and open the file - FILE *log_file; + // expand USR_LOG_FILE if needed and open the file + FILE *log_file = NULL; opening_log_file = true; - { - static char expanded_log_file_path[MAXPATHL + 1]; - - expand_env((char_u *)USR_LOG_FILE, (char_u *)expanded_log_file_path, - MAXPATHL); - // if the log file path expansion failed then fall back to stderr - if (strcmp(USR_LOG_FILE, expanded_log_file_path) == 0) { - goto open_log_file_error; - } - + if (log_path_init()) { log_file = fopen(expanded_log_file_path, "a"); - if (log_file == NULL) { - goto open_log_file_error; - } } opening_log_file = false; - return log_file; - -open_log_file_error: - opening_log_file = false; + if (log_file != NULL) { + return log_file; + } do_log_to_file(stderr, ERROR_LOG_LEVEL, __func__, __LINE__, true, "Couldn't open USR_LOG_FILE, logging to stderr! This may be " diff --git a/src/nvim/main.c b/src/nvim/main.c index 71a972e8f6..ba545c0815 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -120,6 +120,8 @@ typedef struct { # include "main.c.generated.h" #endif +Loop main_loop; + static char *argv0; // Error messages @@ -133,7 +135,7 @@ static const char *err_extra_cmd = void event_init(void) { - loop_init(&loop, NULL); + loop_init(&main_loop, NULL); // early msgpack-rpc initialization msgpack_rpc_init_method_table(); msgpack_rpc_helpers_init(); @@ -151,19 +153,20 @@ void event_init(void) void event_teardown(void) { - if (!loop.events) { + if (!main_loop.events) { return; } - queue_process_events(loop.events); + queue_process_events(main_loop.events); input_stop(); channel_teardown(); - process_teardown(&loop); + process_teardown(&main_loop); + timer_teardown(); server_teardown(); signal_teardown(); terminal_teardown(); - loop_close(&loop); + loop_close(&main_loop); } /// Performs early initialization. diff --git a/src/nvim/main.h b/src/nvim/main.h index 084e247b7e..86d25fe657 100644 --- a/src/nvim/main.h +++ b/src/nvim/main.h @@ -2,6 +2,9 @@ #define NVIM_MAIN_H #include "nvim/normal.h" +#include "nvim/event/loop.h" + +extern Loop main_loop; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "main.h.generated.h" diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c index 6599db787f..9fb03c4ac7 100644 --- a/src/nvim/memfile.c +++ b/src/nvim/memfile.c @@ -913,7 +913,7 @@ static bool mf_do_open(memfile_T *mfp, char_u *fname, int flags) #ifdef HAVE_FD_CLOEXEC int fdflags = fcntl(mfp->mf_fd, F_GETFD); if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) { - fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC); + (void)fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC); } #endif #ifdef HAVE_SELINUX diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 4e35dd481f..9c20f15727 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -443,8 +443,9 @@ void ml_setname(buf_T *buf) #ifdef HAVE_FD_CLOEXEC { int fdflags = fcntl(mfp->mf_fd, F_GETFD); - if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) - fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC); + if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) { + (void)fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC); + } } #endif } diff --git a/src/nvim/message.c b/src/nvim/message.c index 47f246fc76..521db85cf0 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -785,11 +785,13 @@ void wait_return(int redraw) State = HITRETURN; setmouse(); - /* Avoid the sequence that the user types ":" at the hit-return prompt - * to start an Ex command, but the file-changed dialog gets in the - * way. */ - if (need_check_timestamps) - check_timestamps(FALSE); + cmdline_row = msg_row; + // Avoid the sequence that the user types ":" at the hit-return prompt + // to start an Ex command, but the file-changed dialog gets in the + // way. + if (need_check_timestamps) { + check_timestamps(false); + } hit_return_msg(); @@ -1970,6 +1972,7 @@ static void msg_puts_printf(char *str, int maxlen) */ static int do_more_prompt(int typed_char) { + static bool entered = false; int used_typed_char = typed_char; int oldState = State; int c; @@ -1979,6 +1982,13 @@ static int do_more_prompt(int typed_char) msgchunk_T *mp; int i; + // We get called recursively when a timer callback outputs a message. In + // that case don't show another prompt. Also when at the hit-Enter prompt. + if (entered || State == HITRETURN) { + return false; + } + entered = true; + if (typed_char == 'G') { /* "g<": Find first line on the last page. */ mp_last = msg_sb_start(last_msgchunk); @@ -2153,9 +2163,11 @@ static int do_more_prompt(int typed_char) if (quit_more) { msg_row = Rows - 1; msg_col = 0; - } else if (cmdmsg_rl) + } else if (cmdmsg_rl) { msg_col = Columns - 1; + } + entered = false; return retval; } diff --git a/src/nvim/misc2.c b/src/nvim/misc2.c index 4b64de1be0..368f83cfb5 100644 --- a/src/nvim/misc2.c +++ b/src/nvim/misc2.c @@ -467,11 +467,12 @@ bool put_bytes(FILE *fd, uintmax_t number, size_t len) } /// Writes time_t to file "fd" in 8 bytes. -void put_time(FILE *fd, time_t time_) +/// @returns FAIL when the write failed. +int put_time(FILE *fd, time_t time_) { uint8_t buf[8]; time_to_bytes(time_, buf); - (void)fwrite(buf, sizeof(uint8_t), ARRAY_SIZE(buf), fd); + return fwrite(buf, sizeof(uint8_t), ARRAY_SIZE(buf), fd) == 1 ? OK : FAIL; } /// Writes time_t to "buf[8]". diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 34ff7c6374..0d7d5a247e 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -7,8 +7,8 @@ #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" +#include "nvim/api/ui.h" #include "nvim/msgpack_rpc/channel.h" -#include "nvim/msgpack_rpc/remote_ui.h" #include "nvim/event/loop.h" #include "nvim/event/libuv_process.h" #include "nvim/event/rstream.h" @@ -16,6 +16,7 @@ #include "nvim/event/socket.h" #include "nvim/msgpack_rpc/helpers.h" #include "nvim/vim.h" +#include "nvim/main.h" #include "nvim/ascii.h" #include "nvim/memory.h" #include "nvim/os_unix.h" @@ -119,7 +120,7 @@ void channel_teardown(void) uint64_t channel_from_process(char **argv) { Channel *channel = register_channel(kChannelTypeProc); - channel->data.process.uvproc = libuv_process_init(&loop, channel); + channel->data.process.uvproc = libuv_process_init(&main_loop, channel); Process *proc = &channel->data.process.uvproc.process; proc->argv = argv; proc->in = &channel->data.process.in; @@ -127,7 +128,7 @@ uint64_t channel_from_process(char **argv) proc->err = &channel->data.process.err; proc->cb = process_exit; if (!process_spawn(proc)) { - loop_poll_events(&loop, 0); + loop_poll_events(&main_loop, 0); decref(channel); return 0; } @@ -179,7 +180,7 @@ bool channel_send_event(uint64_t id, char *name, Array args) // Pending request, queue the notification for later sending. String method = cstr_as_string(name); WBuffer *buffer = serialize_request(id, 0, method, args, &out_buffer, 1); - kv_push(WBuffer *, channel->delayed_notifications, buffer); + kv_push(channel->delayed_notifications, buffer); } else { send_event(channel, name, args); } @@ -217,10 +218,10 @@ Object channel_send_call(uint64_t id, send_request(channel, request_id, method_name, args); // Push the frame - ChannelCallFrame frame = {request_id, false, false, NIL}; - kv_push(ChannelCallFrame *, channel->call_stack, &frame); + ChannelCallFrame frame = { request_id, false, false, NIL }; + kv_push(channel->call_stack, &frame); channel->pending_requests++; - LOOP_PROCESS_EVENTS_UNTIL(&loop, channel->events, -1, frame.returned); + LOOP_PROCESS_EVENTS_UNTIL(&main_loop, channel->events, -1, frame.returned); (void)kv_pop(channel->call_stack); channel->pending_requests--; @@ -316,11 +317,11 @@ void channel_from_stdio(void) Channel *channel = register_channel(kChannelTypeStdio); incref(channel); // stdio channels are only closed on exit // read stream - rstream_init_fd(&loop, &channel->data.std.in, 0, CHANNEL_BUFFER_SIZE, - channel); + rstream_init_fd(&main_loop, &channel->data.std.in, 0, CHANNEL_BUFFER_SIZE, + channel); rstream_start(&channel->data.std.in, parse_msgpack); // write stream - wstream_init_fd(&loop, &channel->data.std.out, 1, 0, NULL); + wstream_init_fd(&main_loop, &channel->data.std.out, 1, 0, NULL); } static void forward_stderr(Stream *stream, RBuffer *rbuf, size_t count, @@ -574,13 +575,12 @@ static void send_event(Channel *channel, static void broadcast_event(char *name, Array args) { - kvec_t(Channel *) subscribed; - kv_init(subscribed); + kvec_t(Channel *) subscribed = KV_INITIAL_VALUE; Channel *channel; map_foreach_value(channels, channel, { if (pmap_has(cstr_t)(channel->subscribed_events, name)) { - kv_push(Channel *, subscribed, channel); + kv_push(subscribed, channel); } }); @@ -600,7 +600,7 @@ static void broadcast_event(char *name, Array args) for (size_t i = 0; i < kv_size(subscribed); i++) { Channel *channel = kv_A(subscribed, i); if (channel->pending_requests) { - kv_push(WBuffer *, channel->delayed_notifications, buffer); + kv_push(channel->delayed_notifications, buffer); } else { channel_write(channel, buffer); } @@ -647,7 +647,7 @@ static void close_channel(Channel *channel) case kChannelTypeStdio: stream_close(&channel->data.std.in, NULL); stream_close(&channel->data.std.out, NULL); - queue_put(loop.fast_events, exit_event, 1, channel); + queue_put(main_loop.fast_events, exit_event, 1, channel); return; default: abort(); @@ -692,7 +692,7 @@ static void close_cb(Stream *stream, void *data) static Channel *register_channel(ChannelType type) { Channel *rv = xmalloc(sizeof(Channel)); - rv->events = queue_new_child(loop.events); + rv->events = queue_new_child(main_loop.events); rv->type = type; rv->refcount = 1; rv->closed = false; diff --git a/src/nvim/msgpack_rpc/remote_ui.h b/src/nvim/msgpack_rpc/remote_ui.h deleted file mode 100644 index 8af86dc1b8..0000000000 --- a/src/nvim/msgpack_rpc/remote_ui.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef NVIM_MSGPACK_RPC_REMOTE_UI_H -#define NVIM_MSGPACK_RPC_REMOTE_UI_H - -#include "nvim/ui.h" - -#ifdef INCLUDE_GENERATED_DECLARATIONS -# include "msgpack_rpc/remote_ui.h.generated.h" -#endif -#endif // NVIM_MSGPACK_RPC_REMOTE_UI_H diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index 6cc56ba3dd..abbd3e8aff 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -12,6 +12,7 @@ #include "nvim/eval.h" #include "nvim/garray.h" #include "nvim/vim.h" +#include "nvim/main.h" #include "nvim/memory.h" #include "nvim/log.h" #include "nvim/fileio.h" @@ -108,7 +109,7 @@ int server_start(const char *endpoint) } SocketWatcher *watcher = xmalloc(sizeof(SocketWatcher)); - socket_watcher_init(&loop, watcher, endpoint, NULL); + socket_watcher_init(&main_loop, watcher, endpoint, NULL); // Check if a watcher for the endpoint already exists for (int i = 0; i < watchers.ga_len; i++) { diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 382c4943ff..d4055ac1ef 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -974,7 +974,7 @@ static int normal_execute(VimState *state, int key) s->old_col = curwin->w_curswant; s->c = key; - LANGMAP_ADJUST(s->c, true); + LANGMAP_ADJUST(s->c, get_real_state() != SELECTMODE); // If a mapping was started in Visual or Select mode, remember the length // of the mapping. This is used below to not return to Insert mode for as @@ -7879,7 +7879,7 @@ static void nv_event(cmdarg_T *cap) // not safe to perform garbage collection because there could be unreferenced // lists or dicts being used. may_garbage_collect = false; - queue_process_events(loop.events); + queue_process_events(main_loop.events); cap->retval |= CA_COMMAND_BUSY; // don't call edit() now } diff --git a/src/nvim/ops.c b/src/nvim/ops.c index eda963ff77..adfd0424f0 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -5372,11 +5372,10 @@ void cursor_pos_info(dict_T *dict) } } - // Don't shorten this message, the user asked for it. bom_count = bomb_size(); if (bom_count > 0) { vim_snprintf((char *)IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff), - _("(+%" PRId64 " for BOM)"), (int64_t)byte_count); + _("(+%" PRId64 " for BOM)"), (int64_t)bom_count); } if (dict == NULL) { p = p_shm; @@ -5387,20 +5386,18 @@ void cursor_pos_info(dict_T *dict) } if (dict != NULL) { + // Don't shorten this message, the user asked for it. dict_add_nr_str(dict, "words", word_count, NULL); dict_add_nr_str(dict, "chars", char_count, NULL); dict_add_nr_str(dict, "bytes", byte_count + bom_count, NULL); - if (l_VIsual_active) { - dict_add_nr_str(dict, "visual_bytes", byte_count_cursor, NULL); - dict_add_nr_str(dict, "visual_chars", char_count_cursor, NULL); - dict_add_nr_str(dict, "visual_words", word_count_cursor, NULL); - } else { - dict_add_nr_str(dict, "cursor_bytes", byte_count_cursor, NULL); - dict_add_nr_str(dict, "cursor_chars", char_count_cursor, NULL); - dict_add_nr_str(dict, "cursor_words", word_count_cursor, NULL); + dict_add_nr_str(dict, l_VIsual_active ? "visual_bytes" : "cursor_bytes", + byte_count_cursor, NULL); + dict_add_nr_str(dict, l_VIsual_active ? "visual_chars" : "cursor_chars", + char_count_cursor, NULL); + dict_add_nr_str(dict, l_VIsual_active ? "visual_words" : "cursor_words", + word_count_cursor, NULL); } - } } /// Check if the default register (used in an unnamed paste) should be a diff --git a/src/nvim/option.c b/src/nvim/option.c index 45ebb4fa4c..c8a25e8b75 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2129,6 +2129,7 @@ void check_buf_options(buf_T *buf) check_string_option(&buf->b_p_nf); check_string_option(&buf->b_p_qe); check_string_option(&buf->b_p_syn); + check_string_option(&buf->b_s.b_syn_isk); check_string_option(&buf->b_s.b_p_spc); check_string_option(&buf->b_s.b_p_spf); check_string_option(&buf->b_s.b_p_spl); @@ -5606,6 +5607,7 @@ void buf_copy_options(buf_T *buf, int flags) /* Don't copy 'syntax', it must be set */ buf->b_p_syn = empty_option; buf->b_p_smc = p_smc; + buf->b_s.b_syn_isk = empty_option; buf->b_s.b_p_spc = vim_strsave(p_spc); (void)compile_cap_prog(&buf->b_s); buf->b_s.b_p_spf = vim_strsave(p_spf); diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 49a74cf0d1..143a7160b0 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -111,8 +111,8 @@ int os_nodetype(const char *name) #endif uv_stat_t statbuf; - if (os_stat(name, &statbuf) == 0) { - return NODE_NORMAL; + if (0 != os_stat(name, &statbuf)) { + return NODE_NORMAL; // File doesn't exist. } #ifndef WIN32 diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index 7687b14f02..0c46dc96ee 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -60,7 +60,7 @@ void input_start(int fd) } global_fd = fd; - rstream_init_fd(&loop, &read_stream, fd, READ_BUFFER_SIZE, NULL); + rstream_init_fd(&main_loop, &read_stream, fd, READ_BUFFER_SIZE, NULL); rstream_start(&read_stream, read_cb); } @@ -87,8 +87,8 @@ static void create_cursorhold_event(void) // have been called(inbuf_poll would return kInputAvail) // TODO(tarruda): Cursorhold should be implemented as a timer set during the // `state_check` callback for the states where it can be triggered. - assert(!events_enabled || queue_empty(loop.events)); - queue_put(loop.events, cursorhold_event, 0); + assert(!events_enabled || queue_empty(main_loop.events)); + queue_put(main_loop.events, cursorhold_event, 0); } // Low level input function @@ -147,7 +147,7 @@ bool os_char_avail(void) void os_breakcheck(void) { if (!got_int) { - loop_poll_events(&loop, 0); + loop_poll_events(&main_loop, 0); } } @@ -322,7 +322,7 @@ static bool input_poll(int ms) prof_inchar_enter(); } - LOOP_PROCESS_EVENTS_UNTIL(&loop, NULL, ms, input_ready() || input_eof); + LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, ms, input_ready() || input_eof); if (do_profiling == PROF_YES && ms) { prof_inchar_exit(); @@ -419,5 +419,5 @@ static void read_error_exit(void) static bool pending_events(void) { - return events_enabled && !queue_empty(loop.events); + return events_enabled && !queue_empty(main_loop.events); } diff --git a/src/nvim/os/pty_process.h b/src/nvim/os/pty_process.h new file mode 100644 index 0000000000..94923499ca --- /dev/null +++ b/src/nvim/os/pty_process.h @@ -0,0 +1,9 @@ +#ifndef NVIM_OS_PTY_PROCESS_H +#define NVIM_OS_PTY_PROCESS_H + +#ifdef WIN32 +# include "nvim/os/pty_process_win.h" +#else +# include "nvim/os/pty_process_unix.h" +#endif +#endif // NVIM_OS_PTY_PROCESS_H diff --git a/src/nvim/event/pty_process.c b/src/nvim/os/pty_process_unix.c index 8eef72f12f..d0a38e663b 100644 --- a/src/nvim/event/pty_process.c +++ b/src/nvim/os/pty_process_unix.c @@ -26,11 +26,11 @@ #include "nvim/event/rstream.h" #include "nvim/event/wstream.h" #include "nvim/event/process.h" -#include "nvim/event/pty_process.h" +#include "nvim/os/pty_process_unix.h" #include "nvim/log.h" #ifdef INCLUDE_GENERATED_DECLARATIONS -# include "event/pty_process.c.generated.h" +# include "os/pty_process_unix.c.generated.h" #endif bool pty_process_spawn(PtyProcess *ptyproc) @@ -44,7 +44,7 @@ bool pty_process_spawn(PtyProcess *ptyproc) Process *proc = (Process *)ptyproc; assert(!proc->err); uv_signal_start(&proc->loop->children_watcher, chld_handler, SIGCHLD); - ptyproc->winsize = (struct winsize){ptyproc->height, ptyproc->width, 0, 0}; + ptyproc->winsize = (struct winsize){ ptyproc->height, ptyproc->width, 0, 0 }; uv_disable_stdio_inheritance(); int master; int pid = forkpty(&master, NULL, &termios, &ptyproc->winsize); @@ -86,11 +86,10 @@ error: return false; } -void pty_process_resize(PtyProcess *ptyproc, uint16_t width, - uint16_t height) +void pty_process_resize(PtyProcess *ptyproc, uint16_t width, uint16_t height) FUNC_ATTR_NONNULL_ALL { - ptyproc->winsize = (struct winsize){height, width, 0, 0}; + ptyproc->winsize = (struct winsize){ height, width, 0, 0 }; ioctl(ptyproc->tty_fd, TIOCSWINSZ, &ptyproc->winsize); } diff --git a/src/nvim/event/pty_process.h b/src/nvim/os/pty_process_unix.h index 446d7fd3c8..f7c57b3839 100644 --- a/src/nvim/event/pty_process.h +++ b/src/nvim/os/pty_process_unix.h @@ -1,5 +1,5 @@ -#ifndef NVIM_EVENT_PTY_PROCESS_H -#define NVIM_EVENT_PTY_PROCESS_H +#ifndef NVIM_OS_PTY_PROCESS_UNIX_H +#define NVIM_OS_PTY_PROCESS_UNIX_H #include <sys/ioctl.h> @@ -25,6 +25,7 @@ static inline PtyProcess pty_process_init(Loop *loop, void *data) } #ifdef INCLUDE_GENERATED_DECLARATIONS -# include "event/pty_process.h.generated.h" +# include "os/pty_process_unix.h.generated.h" #endif -#endif // NVIM_EVENT_PTY_PROCESS_H + +#endif // NVIM_OS_PTY_PROCESS_UNIX_H diff --git a/src/nvim/os/pty_process_win.h b/src/nvim/os/pty_process_win.h new file mode 100644 index 0000000000..20cc589925 --- /dev/null +++ b/src/nvim/os/pty_process_win.h @@ -0,0 +1,28 @@ +#ifndef NVIM_OS_PTY_PROCESS_WIN_H +#define NVIM_OS_PTY_PROCESS_WIN_H + +#include "nvim/event/libuv_process.h" + +typedef struct pty_process { + Process process; + char *term_name; + uint16_t width, height; +} PtyProcess; + +#define pty_process_spawn(job) libuv_process_spawn((LibuvProcess *)job) +#define pty_process_close(job) libuv_process_close((LibuvProcess *)job) +#define pty_process_close_master(job) libuv_process_close((LibuvProcess *)job) +#define pty_process_resize(job, width, height) +#define pty_process_teardown(loop) + +static inline PtyProcess pty_process_init(Loop *loop, void *data) +{ + PtyProcess rv; + rv.process = process_init(loop, kProcessTypePty, data); + rv.term_name = NULL; + rv.width = 80; + rv.height = 24; + return rv; +} + +#endif // NVIM_OS_PTY_PROCESS_WIN_H diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index f5a1637c94..988620b145 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -14,6 +14,7 @@ #include "nvim/os/shell.h" #include "nvim/os/signal.h" #include "nvim/types.h" +#include "nvim/main.h" #include "nvim/vim.h" #include "nvim/message.h" #include "nvim/memory.h" @@ -205,16 +206,16 @@ static int do_os_system(char **argv, xstrlcpy(prog, argv[0], MAXPATHL); Stream in, out, err; - LibuvProcess uvproc = libuv_process_init(&loop, &buf); + LibuvProcess uvproc = libuv_process_init(&main_loop, &buf); Process *proc = &uvproc.process; - Queue *events = queue_new_child(loop.events); + Queue *events = queue_new_child(main_loop.events); proc->events = events; proc->argv = argv; proc->in = input != NULL ? &in : NULL; proc->out = &out; proc->err = &err; if (!process_spawn(proc)) { - loop_poll_events(&loop, 0); + loop_poll_events(&main_loop, 0); // Failed, probably due to `sh` not being executable if (!silent) { MSG_PUTS(_("\nCannot execute ")); diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c index 0ff6016e32..4abc9cfc36 100644 --- a/src/nvim/os/signal.c +++ b/src/nvim/os/signal.c @@ -8,6 +8,7 @@ #include "nvim/globals.h" #include "nvim/memline.h" #include "nvim/eval.h" +#include "nvim/main.h" #include "nvim/memory.h" #include "nvim/misc1.h" #include "nvim/misc2.h" @@ -28,10 +29,10 @@ static bool rejecting_deadly; void signal_init(void) { - signal_watcher_init(&loop, &spipe, NULL); - signal_watcher_init(&loop, &shup, NULL); - signal_watcher_init(&loop, &squit, NULL); - signal_watcher_init(&loop, &sterm, NULL); + signal_watcher_init(&main_loop, &spipe, NULL); + signal_watcher_init(&main_loop, &shup, NULL); + signal_watcher_init(&main_loop, &squit, NULL); + signal_watcher_init(&main_loop, &sterm, NULL); #ifdef SIGPIPE signal_watcher_start(&spipe, on_signal, SIGPIPE); #endif @@ -41,7 +42,7 @@ void signal_init(void) #endif signal_watcher_start(&sterm, on_signal, SIGTERM); #ifdef SIGPWR - signal_watcher_init(&loop, &spwr, NULL); + signal_watcher_init(&main_loop, &spwr, NULL); signal_watcher_start(&spwr, on_signal, SIGPWR); #endif } diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c index 188f0802c9..2205ad0958 100644 --- a/src/nvim/os/time.c +++ b/src/nvim/os/time.c @@ -9,6 +9,7 @@ #include "nvim/os/time.h" #include "nvim/event/loop.h" #include "nvim/vim.h" +#include "nvim/main.h" static uv_mutex_t delay_mutex; static uv_cond_t delay_cond; @@ -43,7 +44,7 @@ void os_delay(uint64_t milliseconds, bool ignoreinput) if (milliseconds > INT_MAX) { milliseconds = INT_MAX; } - LOOP_PROCESS_EVENTS_UNTIL(&loop, NULL, (int)milliseconds, got_int); + LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, (int)milliseconds, got_int); } else { os_microdelay(milliseconds * 1000); } diff --git a/src/nvim/po/eo.po b/src/nvim/po/eo.po index 5b0cb2260b..6bc76506ae 100644 --- a/src/nvim/po/eo.po +++ b/src/nvim/po/eo.po @@ -23,8 +23,8 @@ msgid "" msgstr "" "Project-Id-Version: Vim(Esperanto)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-07-30 17:54+0200\n" -"PO-Revision-Date: 2015-07-30 18:00+0200\n" +"POT-Creation-Date: 2016-02-13 23:42+0100\n" +"PO-Revision-Date: 2016-02-13 23:45+0100\n" "Last-Translator: Dominique PELLÉ <dominique.pelle@gmail.com>\n" "Language-Team: \n" "Language: eo\n" @@ -504,10 +504,6 @@ msgstr "E686: Argumento de %s devas esti Listo" msgid "E712: Argument of %s must be a List or Dictionary" msgstr "E712: Argumento de %s devas esti Listo aŭ Vortaro" -#: ../eval.c:144 -msgid "E713: Cannot use empty key for Dictionary" -msgstr "E713: Ne eblas uzi malplenan ŝlosilon de Vortaro" - #: ../eval.c:145 msgid "E714: List required" msgstr "E714: Listo bezonata" @@ -657,6 +653,9 @@ msgstr "E110: Mankas ')'" msgid "E695: Cannot index a Funcref" msgstr "E695: Ne eblas indeksi Funcref" +msgid "E909: Cannot index a special variable" +msgstr "E909: Ne eblas indeksi specialan variablon" + #: ../eval.c:4839 #, c-format msgid "E112: Option name missing: %s" @@ -689,7 +688,7 @@ msgstr "E697: Mankas fino de Listo ']': %s" #: ../eval.c:5750 msgid "Not enough memory to set references, garbage collection aborted!" -msgstr "Ne sufiĉa memory por valorigi referencojn, senrubigado ĉesigita!" +msgstr "Ne sufiĉa memoro por valorigi referencojn, senrubigado ĉesigita!" #: ../eval.c:6475 #, c-format @@ -874,6 +873,18 @@ msgstr "E745: Uzo de Listo kiel Nombro" msgid "E728: Using a Dictionary as a Number" msgstr "E728: Uzo de Vortaro kiel Nombro" +msgid "E891: Using a Funcref as a Float" +msgstr "E891: Uzo de Funcref kiel Glitpunktnombro" + +msgid "E892: Using a String as a Float" +msgstr "E892: Uzo de Ĉeno kiel Glitpunktnombro" + +msgid "E893: Using a List as a Float" +msgstr "E893: Uzo de Listo kiel Glitpunktnombro" + +msgid "E894: Using a Dictionary as a Float" +msgstr "E894: Uzo de Vortaro kiel Glitpunktnombro" + #: ../eval.c:16259 msgid "E729: using Funcref as a String" msgstr "E729: uzo de Funcref kiel Ĉeno" @@ -886,6 +897,9 @@ msgstr "E730: uzo de Listo kiel Ĉeno" msgid "E731: using Dictionary as a String" msgstr "E731: uzo de Vortaro kiel Ĉeno" +msgid "E908: using an invalid value as a String" +msgstr "E908: uzo de nevalida valoro kiel Ĉeno" + #: ../eval.c:16619 #, c-format msgid "E706: Variable type mismatch for: %s" @@ -1391,6 +1405,13 @@ msgstr "linio %<PRId64>: %s" msgid "cmd: %s" msgstr "kmd: %s" +msgid "frame is zero" +msgstr "kadro estas nul" + +#, c-format +msgid "frame at highest level: %d" +msgstr "kadro je la plej alta nivelo: %d" + #: ../ex_cmds2.c:322 #, c-format msgid "Breakpoint in \"%s%s\" line %<PRId64>" @@ -2861,6 +2882,9 @@ msgstr "E46: Ne eblas ŝanĝi nurlegeblan variablon \"%s\"" msgid "E794: Cannot set variable in the sandbox: \"%s\"" msgstr "E794: Ne eblas agordi variablon en la sabloludejo: \"%s\"" +msgid "E713: Cannot use empty key for Dictionary" +msgstr "E713: Ne eblas uzi malplenan ŝlosilon de Vortaro" + #: ../globals.h:1076 msgid "E47: Error while reading errorfile" msgstr "E47: Eraro dum legado de erardosiero" @@ -4090,12 +4114,12 @@ msgid "" "\n" "(1) Another program may be editing the same file. If this is the case,\n" " be careful not to end up with two different instances of the same\n" -" file when making changes." +" file when making changes. Quit, or continue with caution.\n" msgstr "" "\n" -"(1) Alia programo eble redaktas la saman dosieron.\n" -" Se jes, estu singarda por ne havi du malsamajn\n" -" aperojn de la sama dosiero, kiam vi faros ŝanĝojn." +"(1) Alia programo eble redaktas la saman dosieron. Se jes, estu singarda\n" +" por ne havi du malsamajn aperojn de la sama dosiero, kiam vi faros\n" +" ŝanĝojn. Eliru aŭ daŭrigu singarde.\n" #: ../memline.c:3245 msgid " Quit, or continue with caution.\n" @@ -4792,6 +4816,15 @@ msgstr "" "\n" "Ne povis ŝalti kuntekston de sekureco por " +#, c-format +msgid "Could not set security context %s for %s" +msgstr "Ne povis ŝalti kuntekston de sekureco %s por %s" + +#, c-format +msgid "Could not get security context %s for %s. Removing it!" +msgstr "" +"Ne povis akiri kuntekston de sekureco %s por %s. Gi nun estas forigata!" + #: ../os_unix.c:1558 ../os_unix.c:1647 #, c-format msgid "dlerror = \"%s\"" @@ -5717,6 +5750,9 @@ msgstr "Neniu sintaksa elemento difinita por tiu bufro" msgid "E390: Illegal argument: %s" msgstr "E390: Nevalida argumento: %s" +msgid "syntax iskeyword " +msgstr "sintakso iskeyword " + #: ../syntax.c:3299 #, c-format msgid "E391: No such syntax cluster: %s" @@ -5813,6 +5849,10 @@ msgstr "E847: Tro da sintaksaj inkluzivoj" msgid "E789: Missing ']': %s" msgstr "E789: Mankas ']': %s" +#, c-format +msgid "E890: trailing char after ']': %s]%s" +msgstr "E890: vosta signo post ']': %s]%s" + #: ../syntax.c:4531 #, c-format msgid "E398: Missing '=': %s" diff --git a/src/nvim/po/it.po b/src/nvim/po/it.po index 171e155689..084102da60 100644 --- a/src/nvim/po/it.po +++ b/src/nvim/po/it.po @@ -13,13 +13,13 @@ msgid "" msgstr "" "Project-Id-Version: vim 7.4\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-08-11 20:58+0200\n" -"PO-Revision-Date: 2015-08-11 22:02+0200\n" -"Last-Translator: Vlad Sandrini <vlad.gently@gmail.com>\n" -"Language-Team: Italian Antonio Colombo <azc100@gmail." -"com> Vlad Sandrini <vlad.gently@gmail." -"com> Luciano Montanaro <mikelima@cirulla.net>\n" -"Language: \n" +"POT-Creation-Date: 2016-02-11 12:10+0100\n" +"PO-Revision-Date: 2016-02-11 14:42+0200\n" +"Last-Translator: Antonio Colombo <azc100@gmail.com>\n" +"Language-Team: Antonio Colombo <azc100@gmail.com>" +" Vlad Sandrini <vlad.gently@gmail.com" +" Luciano Montanaro <mikelima@cirulla.net>\n" +"Language: Italian\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO_8859-1\n" "Content-Transfer-Encoding: 8-bit\n" @@ -491,10 +491,6 @@ msgstr "E686: L'argomento di %s deve essere una Lista" msgid "E712: Argument of %s must be a List or Dictionary" msgstr "E712: L'argomento di %s deve essere una Lista o un Dizionario" -#: ../eval.c:144 -msgid "E713: Cannot use empty key for Dictionary" -msgstr "E713: Non posso usare una chiave nulla per il Dizionario" - #: ../eval.c:145 msgid "E714: List required" msgstr "E714: necessaria una Lista" @@ -548,7 +544,7 @@ msgstr "E461: Nome di variabile non ammesso: %s" # nuovo #: ../eval.c:157 msgid "E806: using Float as a String" -msgstr "E806: uso di un numero con virgola come stringa" +msgstr "E806: uso di un Numero-a-virgola-mobile come Stringa" #: ../eval.c:1830 msgid "E687: Less targets than List items" @@ -635,7 +631,7 @@ msgstr "E694: Operazione non valida per Funcref" #: ../eval.c:4277 msgid "E804: Cannot use '%' with Float" -msgstr "E804: Non si pu usare '%' con un numero con virgola" +msgstr "E804: Non si pu usare '%' con un Numero-a-virgola-mobile" #: ../eval.c:4478 msgid "E110: Missing ')'" @@ -645,6 +641,9 @@ msgstr "E110: Manca ')'" msgid "E695: Cannot index a Funcref" msgstr "E695: Non posso indicizzare un Funcref" +msgid "E909: Cannot index a special variable" +msgstr "E909: Non posso indicizzare una variabile speciale" + #: ../eval.c:4839 #, c-format msgid "E112: Option name missing: %s" @@ -736,7 +735,7 @@ msgstr "E725: Chiamata di funzione dict in assenza di Dizionario: %s" #: ../eval.c:7453 msgid "E808: Number or Float required" -msgstr "E808: Ci vuole un numero intero o con virgola" +msgstr "E808: Ci vuole un Numero o un Numero-a-virgola-mobile" #: ../eval.c:7503 msgid "add() argument" @@ -847,7 +846,7 @@ msgstr "E677: Errore in scrittura su file temporaneo" #: ../eval.c:16159 msgid "E805: Using a Float as a Number" -msgstr "E805: Uso di un numero con virgola come intero" +msgstr "E805: Uso di un Numero-a-virgola-mobile come Numero" #: ../eval.c:16162 msgid "E703: Using a Funcref as a Number" @@ -861,6 +860,18 @@ msgstr "E745: Uso di Lista come Numero" msgid "E728: Using a Dictionary as a Number" msgstr "E728: Uso di Dizionario come Numero" +msgid "E891: Using a Funcref as a Float" +msgstr "E891: Uso di Funcref come Numero-a-virgola-mobile" + +msgid "E892: Using a String as a Float" +msgstr "E892: Uso di Stringa come Numero-a-virgola-mobile" + +msgid "E893: Using a List as a Float" +msgstr "E893: Uso di Lista come Numero-a-virgola-mobile" + +msgid "E894: Using a Dictionary as a Float" +msgstr "E894: Uso di Dizionario come Numero-a-virgola-mobile" + #: ../eval.c:16259 msgid "E729: using Funcref as a String" msgstr "E729: uso di Funcref come Stringa" @@ -873,6 +884,10 @@ msgstr "E730: uso di Lista come Stringa" msgid "E731: using Dictionary as a String" msgstr "E731: uso di Dizionario come Stringa" +# nuovo +msgid "E908: using an invalid value as a String" +msgstr "E908: uso di un valore non valido come Stringa" + #: ../eval.c:16619 #, c-format msgid "E706: Variable type mismatch for: %s" @@ -960,12 +975,14 @@ msgid "E129: Function name required" msgstr "E129: Nome funzione necessario" #: ../eval.c:17824 +#, c-format msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "E128: Il nome funzione deve iniziare con una maiuscola o \"s:\": %s" +msgstr "E128: Il nome funzione deve iniziare con maiuscola o \"s:\": %s" #: ../eval.c:17833 +#, c-format msgid "E884: Function name cannot contain a colon: %s" -msgstr "E884: Il nome funzione non pu contenere una virgola: %s" +msgstr "E884: Il nome della funzione non pu contenere un due punti: %s" #: ../eval.c:18336 #, c-format @@ -1382,6 +1399,13 @@ msgstr "riga %<PRId64>: %s" msgid "cmd: %s" msgstr "com: %s" +msgid "frame is zero" +msgstr "al livello zero" + +#, c-format +msgid "frame at highest level: %d" +msgstr "al livello pi alto: %d" + #: ../ex_cmds2.c:322 #, c-format msgid "Breakpoint in \"%s%s\" line %<PRId64>" @@ -1422,8 +1446,7 @@ msgstr "E162: Buffer \"%s\" non salvato dopo modifica" #: ../ex_cmds2.c:1480 msgid "Warning: Entered other buffer unexpectedly (check autocommands)" msgstr "" -"Avviso: Entrato in altro buffer inaspettatamente (controllare " -"autocomandi)" +"Avviso: Entrato in altro buffer inaspettatamente (controllare autocomandi)" #: ../ex_cmds2.c:1826 msgid "E163: There is only one file to edit" @@ -2301,19 +2324,19 @@ msgstr "[in formato DOS]" #: ../fileio.c:3801 msgid "[mac]" -msgstr "[MAC]" +msgstr "[Mac]" #: ../fileio.c:3801 msgid "[mac format]" -msgstr "[in formato MAC]" +msgstr "[in formato Mac]" #: ../fileio.c:3807 msgid "[unix]" -msgstr "[UNIX]" +msgstr "[Unix]" #: ../fileio.c:3807 msgid "[unix format]" -msgstr "[in formato UNIX]" +msgstr "[in formato Unix]" #: ../fileio.c:3831 msgid "1 line, " @@ -2864,6 +2887,9 @@ msgstr "E46: Non posso cambiare la variabile read-only \"%s\"" msgid "E794: Cannot set variable in the sandbox: \"%s\"" msgstr "E794: Non posso impostare la variabile read-only in ambiente protetto: \"%s\"" +msgid "E713: Cannot use empty key for Dictionary" +msgstr "E713: Non posso usare una chiave nulla per il Dizionario" + #: ../globals.h:1076 msgid "E47: Error while reading errorfile" msgstr "E47: Errore leggendo il file errori" @@ -4087,12 +4113,12 @@ msgid "" "\n" "(1) Another program may be editing the same file. If this is the case,\n" " be careful not to end up with two different instances of the same\n" -" file when making changes." +" file when making changes. Quit, or continue with caution.\n" msgstr "" "\n" -"(1) Un altro programma pu essere in edit sullo stesso file.\n" -" Se cos, attenzione a non trovarti con due versioni\n" -" differenti dello stesso file a cui vengono apportate modifiche." +"(1) Un altro programma pu essere in edit sullo stesso file. Se cos,\n" +" attenzione a non finire con due sessioni differenti che modificano lo\n" +" stesso file. Uscire da Vim, o continuare con cautela.\n" #: ../memline.c:3245 msgid " Quit, or continue with caution.\n" @@ -4335,7 +4361,7 @@ msgstr "E766: Argomenti non sufficienti per printf()" #: ../message.c:3119 msgid "E807: Expected Float argument for printf()" -msgstr "E807: Numero con virgola atteso come argomento per printf()" +msgstr "E807: Numero-a-virgola-mobile atteso come argomento per printf()" #: ../message.c:3873 msgid "E767: Too many arguments to printf()" @@ -4526,7 +4552,8 @@ msgstr "E574: Tipo di registro sconosciuto: %d" msgid "" "E883: search pattern and expression register may not contain two or more " "lines" -msgstr "E883: espressione di ricerca e registro dell'espressione non possono " +msgstr "" +"E883: espressione di ricerca e registro dell'espressione non possono " "contenere due o pi righe" #: ../ops.c:5089 @@ -4794,6 +4821,14 @@ msgstr "" "\n" "Non posso impostare il contesto di sicurezza per " +#, c-format +msgid "Could not set security context %s for %s" +msgstr "Non posso impostare il contesto di sicurezza %s per %s" + +#, c-format +msgid "Could not get security context %s for %s. Removing it!" +msgstr "Non posso ottenere il contesto di sicurezza %s per %s. Lo rimuovo!" + #: ../os_unix.c:1558 ../os_unix.c:1647 #, c-format msgid "dlerror = \"%s\"" @@ -4890,6 +4925,7 @@ msgid "E777: String or List expected" msgstr "E777: aspettavo Stringa o Lista" #: ../regexp.c:359 +#, c-format msgid "E369: invalid item in %s%%[]" msgstr "E369: elemento non valido in %s%%[]" @@ -5005,6 +5041,7 @@ msgid "External submatches:\n" msgstr "Sotto-corrispondenze esterne:\n" #: ../regexp.c:2470 +#, c-format msgid "E888: (NFA regexp) cannot repeat %s" msgstr "E888: (NFA regexp) non riesco a ripetere %s" @@ -5399,8 +5436,7 @@ msgstr "Valore errato per CHECKCOMPOUNDPATTERN in %s riga %d: %s" #: ../spell.c:4847 #, c-format msgid "Different combining flag in continued affix block in %s line %d: %s" -msgstr "" -"Flag combinazione diverso in blocco affissi continuo in %s riga %d: %s" +msgstr "Flag combinazione diverso in blocco affissi continuo in %s riga %d: %s" #: ../spell.c:4850 #, c-format @@ -5639,10 +5675,12 @@ msgid "E765: 'spellfile' does not have %<PRId64> entries" msgstr "E765: 'spellfile' non ha %<PRId64> elementi" #: ../spell.c:8074 +#, c-format msgid "Word '%.*s' removed from %s" msgstr "Parola '%.*s' rimossa da %s" #: ../spell.c:8117 +#, c-format msgid "Word '%.*s' added to %s" msgstr "Parola '%.*s' aggiunta a %s" @@ -5720,6 +5758,9 @@ msgstr "Nessun elemento sintattico definito per questo buffer" msgid "E390: Illegal argument: %s" msgstr "E390: Argomento non ammesso: %s" +msgid "syntax iskeyword " +msgstr "syntax iskeyword " + #: ../syntax.c:3299 #, c-format msgid "E391: No such syntax cluster: %s" @@ -5816,6 +5857,9 @@ msgstr "E847: Troppe inclusioni di sintassi" msgid "E789: Missing ']': %s" msgstr "E789: Manca ']': %s" +msgid "E890: trailing char after ']': %s]%s" +msgstr "E890: Caratteri in pi dopo ']': %s]%s" + #: ../syntax.c:4531 #, c-format msgid "E398: Missing '=': %s" diff --git a/src/nvim/po/ja.euc-jp.po b/src/nvim/po/ja.euc-jp.po index d3061d3c5a..85042e3506 100644 --- a/src/nvim/po/ja.euc-jp.po +++ b/src/nvim/po/ja.euc-jp.po @@ -1,11 +1,11 @@ -# Japanese translation for Vim vim:set foldmethod=marker: +# Japanese translation for Vim # # Do ":help uganda" in Vim to read copying and usage conditions. # Do ":help credits" in Vim to see a list of people who contributed. # -# Last Change: 2013 Jul 06 +# Copyright (C) 2001-2016 MURAOKA Taro <koron.kaoriya@gmail.com>, +# vim-jp (http://vim-jp.org/) # -# Copyright (C) 2001-13 MURAOKA Taro <koron.kaoriya@gmail.com> # THIS FILE IS DISTRIBUTED UNDER THE VIM LICENSE. # # Generated from ja.po, DO NOT EDIT. @@ -14,10 +14,10 @@ msgid "" msgstr "" "Project-Id-Version: Vim 7.4\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-05-26 14:21+0200\n" -"PO-Revision-Date: 2013-07-06 15:00+0900\n" +"POT-Creation-Date: 2016-02-01 09:02+0900\n" +"PO-Revision-Date: 2016-02-01 09:08+0900\n" "Last-Translator: MURAOKA Taro <koron.kaoriya@gmail.com>\n" -"Language-Team: MURAOKA Taro <koron.kaoriya@gmail.com>\n" +"Language-Team: vim-jp (https://github.com/vim-jp/lang-ja)\n" "Language: Japanese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=euc-jp\n" @@ -34,7 +34,7 @@ msgstr "顼: ̤ΤΥץǤ" #: ../buffer.c:92 msgid "[Location List]" -msgstr "[ꥹ]" +msgstr "[ꥹ]" #: ../buffer.c:93 msgid "[Quickfix List]" @@ -277,7 +277,7 @@ msgstr "E810: եɹ⤷ϽǤޤ" #: ../diff.c:755 msgid "E97: Cannot create diffs" -msgstr "E97: ʬǤޤ " +msgstr "E97: ʬǤޤ" #: ../diff.c:966 msgid "E816: Cannot read patch output" @@ -293,7 +293,7 @@ msgstr "E99: ߤΥХåեϺʬ⡼ɤǤϤޤ" #: ../diff.c:2100 msgid "E793: No other buffer in diff mode is modifiable" -msgstr "E793: ʬ⡼ɤǤ¾ΥХåեѹǽǤ" +msgstr "E793: ʬ⡼ɤǤ¾ΥХåեѹǤޤ" #: ../diff.c:2102 msgid "E100: No other buffer in diff mode" @@ -349,7 +349,7 @@ msgstr " ()䴰 (^L^N^P)" #: ../edit.c:86 msgid " File name completion (^F^N^P)" -msgstr "ե̾䴰 (^F^N^P)" +msgstr " ե̾䴰 (^F^N^P)" #: ../edit.c:87 msgid " Tag completion (^]^N^P)" @@ -377,7 +377,7 @@ msgstr " ޥɥ饤䴰 (^V^N^P)" #: ../edit.c:94 msgid " User defined completion (^U^N^P)" -msgstr " 桼䴰 (^U^N^P)" +msgstr " 桼䴰 (^U^N^P)" #: ../edit.c:95 msgid " Omni completion (^O^N^P)" @@ -679,6 +679,11 @@ msgstr "E696: ꥹȷ˥ޤޤ: %s" msgid "E697: Missing end of List ']': %s" msgstr "E697: ꥹȷκǸ ']' ޤ: %s" +#: ../eval.c:5807 +msgid "Not enough memory to set references, garbage collection aborted!" +msgstr "" +"٥å쥯ߤޤ! ȤΤ˥꤬ޤ" + #: ../eval.c:6475 #, c-format msgid "E720: Missing colon in Dictionary: %s" @@ -721,7 +726,7 @@ msgstr "E117: ̤ΤδؿǤ: %s" #: ../eval.c:7383 #, c-format msgid "E119: Not enough arguments for function: %s" -msgstr "E119: ؿΰʲޤ: %s" +msgstr "E119: ؿΰޤ: %s" #: ../eval.c:7387 #, c-format @@ -826,18 +831,16 @@ msgid "sort() argument" msgstr "sort() ΰ" #: ../eval.c:13721 -#, fuzzy msgid "uniq() argument" -msgstr "add() ΰ" +msgstr "uniq() ΰ" #: ../eval.c:13776 msgid "E702: Sort compare function failed" msgstr "E702: ȤӴؿԤޤ" #: ../eval.c:13806 -#, fuzzy msgid "E882: Uniq compare function failed" -msgstr "E702: ȤӴؿԤޤ" +msgstr "E882: Uniq ӴؿԤޤ" #: ../eval.c:14085 msgid "(Invalid)" @@ -863,6 +866,18 @@ msgstr "E745: ꥹȷͤȤưäƤޤ" msgid "E728: Using a Dictionary as a Number" msgstr "E728: ͤȤưäƤޤ" +msgid "E891: Using a Funcref as a Float" +msgstr "E891: ؿȷưȤưäƤޤ" + +msgid "E892: Using a String as a Float" +msgstr "E892: ʸưȤưäƤޤ" + +msgid "E893: Using a List as a Float" +msgstr "E893: ꥹȷưȤưäƤޤ" + +msgid "E894: Using a Dictionary as a Float" +msgstr "E894: ưȤưäƤޤ" + #: ../eval.c:16259 msgid "E729: using Funcref as a String" msgstr "E729: ؿȷʸȤưäƤޤ" @@ -961,14 +976,14 @@ msgid "E129: Function name required" msgstr "E129: ؿ̾ᤵޤ" #: ../eval.c:17824 -#, fuzzy, c-format +#, c-format msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "E128: ؿ̾ʸǻϤޤ뤫ޤޤʤФʤޤ: %s" +msgstr "E128: ؿ̾ʸ \"s:\" ǻϤޤʤФʤޤ: %s" #: ../eval.c:17833 -#, fuzzy, c-format +#, c-format msgid "E884: Function name cannot contain a colon: %s" -msgstr "E128: ؿ̾ʸǻϤޤ뤫ޤޤʤФʤޤ: %s" +msgstr "E884: ؿ̾ˤϥϴޤޤ: %s" #: ../eval.c:18336 #, c-format @@ -1081,7 +1096,7 @@ msgstr "E136: viminfo: 顼¿Τ, ʹߤϥåפޤ" #: ../ex_cmds.c:1458 #, c-format msgid "Reading viminfo file \"%s\"%s%s%s" -msgstr "viminfoե \"%s\"%s%s%s ɹ " +msgstr "viminfoե \"%s\"%s%s%s ɹ" #: ../ex_cmds.c:1460 msgid " info" @@ -1357,6 +1372,10 @@ msgstr "E158: ̵ʥХåե̾Ǥ: %s" msgid "E157: Invalid sign ID: %<PRId64>" msgstr "E157: ̵sign̻ҤǤ: %<PRId64>" +#, c-format +msgid "E885: Not possible to change sign %s" +msgstr "E885: ѹǤʤ sign Ǥ: %s" + #: ../ex_cmds.c:6066 msgid " (not supported)" msgstr " (ݡ)" @@ -1379,6 +1398,13 @@ msgstr " %<PRId64>: %s" msgid "cmd: %s" msgstr "ޥ: %s" +msgid "frame is zero" +msgstr "ե졼ब 0 Ǥ" + +#, c-format +msgid "frame at highest level: %d" +msgstr "ǹ٥Υե졼: %d" + #: ../ex_cmds2.c:322 #, c-format msgid "Breakpoint in \"%s%s\" line %<PRId64>" @@ -1528,7 +1554,8 @@ msgstr "E197: \"%s\" Ǥޤ" #. don't wait for return #: ../ex_docmd.c:387 msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." -msgstr "Ex⡼ɤޤ. Ρޥˤ\"visual\"ϤƤ." +msgstr "" +"Ex⡼ɤޤ. Ρޥ⡼ɤˤ\"visual\"ϤƤ." #: ../ex_docmd.c:428 msgid "E501: At end-of-file" @@ -1553,7 +1580,7 @@ msgstr "ؿκǸǤ" #: ../ex_docmd.c:1628 msgid "E464: Ambiguous use of user-defined command" -msgstr "E464: 桼ޥɤΤޤʻѤǤ" +msgstr "E464: 桼ޥɤΤޤʻѤǤ" #: ../ex_docmd.c:1638 msgid "E492: Not an editor command" @@ -1606,14 +1633,14 @@ msgstr "E174: ޥɤˤޤ: ˤ ! ɲäƤ" #: ../ex_docmd.c:4432 msgid "" "\n" -" Name Args Range Complete Definition" +" Name Args Address Complete Definition" msgstr "" "\n" -" ̾ ϰ 䴰 " +" ̾ ɥ쥹 䴰 " #: ../ex_docmd.c:4516 msgid "No user-defined commands found" -msgstr "桼ޥɤĤޤǤ" +msgstr "桼ޥɤĤޤǤ" #: ../ex_docmd.c:4538 msgid "E175: No attribute specified" @@ -1633,7 +1660,10 @@ msgstr "E178: Ȥξά̵ͤǤ" #: ../ex_docmd.c:4625 msgid "E179: argument required for -complete" -msgstr "E179: -䴰ΤΰɬפǤ" +msgstr "E179: -complete ˤϰɬפǤ" + +msgid "E179: argument required for -addr" +msgstr "E179: -addr ˤϰɬפǤ" #: ../ex_docmd.c:4635 #, c-format @@ -1650,12 +1680,16 @@ msgstr "E183: 桼ޥɤϱʸǻϤޤʤФʤޤ" #: ../ex_docmd.c:4696 msgid "E841: Reserved name, cannot be used for user defined command" -msgstr "E841: ͽ̾ʤΤ, 桼ޥɤѤǤޤ" +msgstr "E841: ͽ̾ʤΤ, 桼ޥɤѤǤޤ" #: ../ex_docmd.c:4751 #, c-format msgid "E184: No such user-defined command: %s" -msgstr "E184: Υ桼ޥɤϤޤ: %s" +msgstr "E184: Υ桼ޥɤϤޤ: %s" + +#, c-format +msgid "E180: Invalid address type value: %s" +msgstr "E180: ̵ʥɥ쥹ͤǤ: %s" #: ../ex_docmd.c:5219 #, c-format @@ -2019,11 +2053,11 @@ msgstr "ʥե̾" #: ../fileio.c:395 ../fileio.c:476 ../fileio.c:2543 ../fileio.c:2578 msgid "is a directory" -msgstr " ϥǥ쥯ȥǤ" +msgstr "ϥǥ쥯ȥǤ" #: ../fileio.c:397 msgid "is not a file" -msgstr " ϥեǤϤޤ" +msgstr "ϥեǤϤޤ" #: ../fileio.c:508 ../fileio.c:3522 msgid "[New File]" @@ -2039,7 +2073,7 @@ msgstr "[ե]" #: ../fileio.c:534 msgid "[Permission Denied]" -msgstr "[ǧĤޤ]" +msgstr "[¤ޤ]" #: ../fileio.c:653 msgid "E200: *ReadPre autocommands made the file unreadable" @@ -2210,7 +2244,7 @@ msgstr " Ѵ顼" #: ../fileio.c:3509 #, c-format msgid " in line %<PRId64>;" -msgstr " %<PRId64>;" +msgstr " %<PRId64>;" #: ../fileio.c:3519 msgid "[Device]" @@ -2766,9 +2800,8 @@ msgid "E37: No write since last change (add ! to override)" msgstr "E37: Ǹѹ¸Ƥޤ (! ɲäѹ˴)" #: ../globals.h:1055 -#, fuzzy msgid "E37: No write since last change" -msgstr "[Ǹѹ¸Ƥޤ]\n" +msgstr "E37: Ǹѹ¸Ƥޤ" #: ../globals.h:1056 msgid "E38: Null argument" @@ -2810,7 +2843,7 @@ msgstr "E42: 顼Ϥޤ" #: ../globals.h:1067 msgid "E776: No location list" -msgstr "E776: ꥹȤϤޤ" +msgstr "E776: ꥹȤϤޤ" #: ../globals.h:1068 msgid "E43: Damaged match string" @@ -3831,7 +3864,7 @@ msgid "" "\n" msgstr "" "\n" -"줫.swpեƤ\n" +".swpեϺƤޤ\n" "\n" #. use msg() to start the scrolling properly @@ -3845,7 +3878,7 @@ msgstr " ߤΥǥ쥯ȥ:\n" #: ../memline.c:1448 msgid " Using specified name:\n" -msgstr " ̾:\n" +msgstr " ʲ̾:\n" #: ../memline.c:1450 msgid " In directory " @@ -3901,7 +3934,7 @@ msgid "" " user name: " msgstr "" "\n" -" 桼̾: " +" 桼̾: " #: ../memline.c:1568 msgid " host name: " @@ -4050,12 +4083,12 @@ msgid "" msgstr "" "\n" "(1) ̤ΥץबƱեԽƤ뤫⤷ޤ.\n" -" ξˤ, ѹݤ˺ǽŪ, Ʊեΰۤʤ\n" -" 2ĤΥǤƤޤȤդƤ." +" ξˤ, ѹƤޤ1ĤΥեФưۤʤ2Ĥ\n" +" ǤƤޤΤ, ʤ褦˵ĤƤ." #: ../memline.c:3245 msgid " Quit, or continue with caution.\n" -msgstr " λ뤫, դʤ³Ƥ.\n" +msgstr " λ뤫, դʤ³Ƥ.\n" #: ../memline.c:3246 msgid "(2) An edit session for this file crashed.\n" @@ -4479,6 +4512,11 @@ msgstr "" msgid "E574: Unknown register type %d" msgstr "E574: ̤ΤΥ쥸 %d Ǥ" +msgid "" +"E883: search pattern and expression register may not contain two or more " +"lines" +msgstr "E883: ѥȼ쥸ˤ2ʾޤޤ" + #: ../ops.c:5089 #, c-format msgid "%<PRId64> Cols; " @@ -4563,6 +4601,10 @@ msgstr "E522: termcap ˸Ĥޤ" msgid "E539: Illegal character <%s>" msgstr "E539: ʸǤ <%s>" +#, c-format +msgid "For option %s" +msgstr "ץ: %s" + #: ../option.c:3862 msgid "E529: Cannot set 'term' to empty string" msgstr "E529: 'term' ˤ϶ʸǤޤ" @@ -4740,6 +4782,14 @@ msgstr "" "\n" "ƥƥȤǤޤ " +#, c-format +msgid "Could not set security context %s for %s" +msgstr "ƥƥ %s %s Ǥޤ" + +#, c-format +msgid "Could not get security context %s for %s. Removing it!" +msgstr "ƥƥ %s %s Ǥޤ. ޤ!" + #: ../os_unix.c:1558 ../os_unix.c:1647 #, c-format msgid "dlerror = \"%s\"" @@ -4960,6 +5010,10 @@ msgstr "E554: %s{...} ʸˡ顼ޤ" msgid "External submatches:\n" msgstr "ʬ:\n" +#, c-format +msgid "E888: (NFA regexp) cannot repeat %s" +msgstr "E888: (NFA ɽ) ֤ޤ %s" + #: ../regexp.c:7022 msgid "" "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be " @@ -4968,6 +5022,9 @@ msgstr "" "E864: \\%#= ˤ 0, 1 ⤷ 2 Τߤ³ޤɽϼư" "ޤ" +msgid "Switching to backtracking RE engine for pattern: " +msgstr "Υѥ˥Хåȥå RE ŬѤޤ: " + #: ../regexp_nfa.c:239 msgid "E865: (NFA) Regexp end encountered prematurely" msgstr "E865: (NFA) Ԥɽνüãޤ" @@ -4980,7 +5037,7 @@ msgstr "E866: (NFA ɽ) ֤äƤޤ: %c" #: ../regexp_nfa.c:242 #, c-format msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "" +msgstr "E877: (NFA ɽ) ̵ʸ饹: %<PRId64>" #: ../regexp_nfa.c:1261 #, c-format @@ -5590,14 +5647,14 @@ msgid "E765: 'spellfile' does not have %<PRId64> entries" msgstr "E765: 'spellfile' ˤ %<PRId64> ĤΥȥϤޤ" #: ../spell.c:8074 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' removed from %s" -msgstr "%s ñ줬ޤ" +msgstr "ñ '%.*s' %s ޤ" #: ../spell.c:8117 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' added to %s" -msgstr "%s ñ줬ɲäޤ" +msgstr "ñ '%.*s' %s ɲäޤ" #: ../spell.c:8381 msgid "E763: Word characters differ between spell files" @@ -5673,6 +5730,9 @@ msgstr "ΥХåե줿ʸǤϤޤ" msgid "E390: Illegal argument: %s" msgstr "E390: ʰǤ: %s" +msgid "syntax iskeyword " +msgstr "å iskeyword " + #: ../syntax.c:3299 #, c-format msgid "E391: No such syntax cluster: %s" @@ -5769,6 +5829,10 @@ msgstr "E847: ʸμ(include)¿ޤ" msgid "E789: Missing ']': %s" msgstr "E789: ']' ޤ: %s" +#, c-format +msgid "E890: trailing char after ']': %s]%s" +msgstr "E890: ']' θ;ʬʸޤ: %s]%s" + #: ../syntax.c:4531 #, c-format msgid "E398: Missing '=': %s" @@ -5874,7 +5938,7 @@ msgstr "E415: ͽǤ: %s" #: ../syntax.c:6395 #, c-format msgid "E416: missing equal sign: %s" -msgstr "E416: 椬ޤ: %s" +msgstr "E416: 椬ޤ: %s" #: ../syntax.c:6418 #, c-format @@ -6078,9 +6142,8 @@ msgstr "Vim: ϤɹΥ顼ˤ꽪λޤ...\n" #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. #: ../undo.c:379 -#, fuzzy msgid "E881: Line count changed unexpectedly" -msgstr "E834: ͽԥȤѤޤ" +msgstr "E881: ͽԥȤѤޤ" #: ../undo.c:627 #, c-format @@ -6287,23 +6350,23 @@ msgstr " ƥ vimrc: \"" #: ../version.c:672 msgid " user vimrc file: \"" -msgstr " 桼 vimrc: \"" +msgstr " 桼 vimrc: \"" #: ../version.c:677 msgid " 2nd user vimrc file: \"" -msgstr " 2桼 vimrc: \"" +msgstr " 2桼 vimrc: \"" #: ../version.c:682 msgid " 3rd user vimrc file: \"" -msgstr " 3桼 vimrc: \"" +msgstr " 3桼 vimrc: \"" #: ../version.c:687 msgid " user exrc file: \"" -msgstr " 桼 exrc: \"" +msgstr " 桼 exrc: \"" #: ../version.c:692 msgid " 2nd user exrc file: \"" -msgstr " 2桼 exrc: \"" +msgstr " 2桼 exrc: \"" #: ../version.c:699 msgid " fall-back for $VIM: \"" @@ -6379,7 +6442,7 @@ msgstr "Vimγȯ礷Ƥ!" #: ../version.c:828 msgid "Become a registered Vim user!" -msgstr "VimϿ桼ˤʤäƤ!" +msgstr "VimϿ桼ˤʤäƤ!" #: ../version.c:831 msgid "type :help sponsor<Enter> for information " @@ -6391,7 +6454,7 @@ msgstr "ܺ٤ʾ :help register<Enter> " #: ../version.c:834 msgid "menu Help->Sponsor/Register for information " -msgstr "ܺ٤ϥ˥塼 إעݥ/Ͽ ȤƲ " +msgstr "ܺ٤ϥ˥塼 إ->ݥ/Ͽ ȤƲ" #: ../window.c:119 msgid "Already only one window" @@ -6429,6 +6492,9 @@ msgstr "E445: ¾Υɥˤѹޤ" msgid "E446: No file name under cursor" msgstr "E446: β˥ե̾ޤ" +msgid "List or number required" +msgstr "ꥹȤͤɬפǤ" + #~ msgid "E831: bf_key_init() called with empty password" #~ msgstr "E831: bf_key_init() ѥɤǸƤӽФޤ" diff --git a/src/nvim/po/ja.po b/src/nvim/po/ja.po index 6bdfcb426f..8a3fcb8f78 100644 --- a/src/nvim/po/ja.po +++ b/src/nvim/po/ja.po @@ -1,11 +1,11 @@ -# Japanese translation for Vim vim:set foldmethod=marker: +# Japanese translation for Vim # # Do ":help uganda" in Vim to read copying and usage conditions. # Do ":help credits" in Vim to see a list of people who contributed. # -# Last Change: 2013 Jul 06 +# Copyright (C) 2001-2016 MURAOKA Taro <koron.kaoriya@gmail.com>, +# vim-jp (http://vim-jp.org/) # -# Copyright (C) 2001-13 MURAOKA Taro <koron.kaoriya@gmail.com> # THIS FILE IS DISTRIBUTED UNDER THE VIM LICENSE. # # Original translations. @@ -14,10 +14,10 @@ msgid "" msgstr "" "Project-Id-Version: Vim 7.4\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-05-26 14:21+0200\n" -"PO-Revision-Date: 2013-07-06 15:00+0900\n" +"POT-Creation-Date: 2016-02-01 09:02+0900\n" +"PO-Revision-Date: 2013-06-02-01 09:08+09n" "Last-Translator: MURAOKA Taro <koron.kaoriya@gmail.com>\n" -"Language-Team: MURAOKA Taro <koron.kaoriya@gmail.com>\n" +"Language-Team: vim-jp (https://github.com/vim-jp/lang-ja)\n" "Language: Japanese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" @@ -34,7 +34,7 @@ msgstr "内部エラー: 未知のオプション型です" #: ../buffer.c:92 msgid "[Location List]" -msgstr "[場所リスト]" +msgstr "[ロケーションリスト]" #: ../buffer.c:93 msgid "[Quickfix List]" @@ -277,7 +277,7 @@ msgstr "E810: 一時ファイルの読込もしくは書込ができません" #: ../diff.c:755 msgid "E97: Cannot create diffs" -msgstr "E97: 差分を作成できません " +msgstr "E97: 差分を作成できません" #: ../diff.c:966 msgid "E816: Cannot read patch output" @@ -293,7 +293,7 @@ msgstr "E99: 現在のバッファは差分モードではありません" #: ../diff.c:2100 msgid "E793: No other buffer in diff mode is modifiable" -msgstr "E793: 差分モードである他のバッファは変更可能です" +msgstr "E793: 差分モードである他のバッファは変更できません" #: ../diff.c:2102 msgid "E100: No other buffer in diff mode" @@ -349,7 +349,7 @@ msgstr " 行(全体)補完 (^L^N^P)" #: ../edit.c:86 msgid " File name completion (^F^N^P)" -msgstr "ファイル名補完 (^F^N^P)" +msgstr " ファイル名補完 (^F^N^P)" #: ../edit.c:87 msgid " Tag completion (^]^N^P)" @@ -377,7 +377,7 @@ msgstr " コマンドライン補完 (^V^N^P)" #: ../edit.c:94 msgid " User defined completion (^U^N^P)" -msgstr " ユーザ定義補完 (^U^N^P)" +msgstr " ユーザー定義補完 (^U^N^P)" #: ../edit.c:95 msgid " Omni completion (^O^N^P)" @@ -679,6 +679,10 @@ msgstr "E696: リスト型にカンマがありません: %s" msgid "E697: Missing end of List ']': %s" msgstr "E697: リスト型の最後に ']' がありません: %s" +msgid "Not enough memory to set references, garbage collection aborted!" +msgstr "" +"ガーベッジコレクションを中止しました! 参照を作成するのにメモリが不足しました" + #: ../eval.c:6475 #, c-format msgid "E720: Missing colon in Dictionary: %s" @@ -721,7 +725,7 @@ msgstr "E117: 未知の関数です: %s" #: ../eval.c:7383 #, c-format msgid "E119: Not enough arguments for function: %s" -msgstr "E119: 関数の引数が少な過ぎます: %s" +msgstr "E119: 関数の引数が足りません: %s" #: ../eval.c:7387 #, c-format @@ -826,18 +830,16 @@ msgid "sort() argument" msgstr "sort() の引数" #: ../eval.c:13721 -#, fuzzy msgid "uniq() argument" -msgstr "add() の引数" +msgstr "uniq() の引数" #: ../eval.c:13776 msgid "E702: Sort compare function failed" msgstr "E702: ソートの比較関数が失敗しました" #: ../eval.c:13806 -#, fuzzy msgid "E882: Uniq compare function failed" -msgstr "E702: ソートの比較関数が失敗しました" +msgstr "E882: Uniq の比較関数が失敗しました" #: ../eval.c:14085 msgid "(Invalid)" @@ -863,6 +865,18 @@ msgstr "E745: リスト型を数値として扱っています" msgid "E728: Using a Dictionary as a Number" msgstr "E728: 辞書型を数値として扱っています" +msgid "E891: Using a Funcref as a Float" +msgstr "E891: 関数参照型を浮動小数点数として扱っています。" + +msgid "E892: Using a String as a Float" +msgstr "E892: 文字列を浮動小数点数として扱っています" + +msgid "E893: Using a List as a Float" +msgstr "E893: リスト型を浮動小数点数として扱っています" + +msgid "E894: Using a Dictionary as a Float" +msgstr "E894: 辞書型を浮動小数点数として扱っています" + #: ../eval.c:16259 msgid "E729: using Funcref as a String" msgstr "E729: 関数参照型を文字列として扱っています" @@ -961,14 +975,14 @@ msgid "E129: Function name required" msgstr "E129: 関数名が要求されます" #: ../eval.c:17824 -#, fuzzy, c-format +#, c-format msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "E128: 関数名は大文字で始まるかコロンを含まなければなりません: %s" +msgstr "E128: 関数名は大文字か \"s:\" で始まらなければなりません: %s" #: ../eval.c:17833 -#, fuzzy, c-format +#, c-format msgid "E884: Function name cannot contain a colon: %s" -msgstr "E128: 関数名は大文字で始まるかコロンを含まなければなりません: %s" +msgstr "E884: 関数名にはコロンは含められません: %s" #: ../eval.c:18336 #, c-format @@ -1081,7 +1095,7 @@ msgstr "E136: viminfo: エラーが多過ぎるので, 以降はスキップし #: ../ex_cmds.c:1458 #, c-format msgid "Reading viminfo file \"%s\"%s%s%s" -msgstr "viminfoファイル \"%s\"%s%s%s を読込み中 " +msgstr "viminfoファイル \"%s\"%s%s%s を読込み中" #: ../ex_cmds.c:1460 msgid " info" @@ -1357,6 +1371,10 @@ msgstr "E158: 無効なバッファ名です: %s" msgid "E157: Invalid sign ID: %<PRId64>" msgstr "E157: 無効なsign識別子です: %<PRId64>" +#, c-format +msgid "E885: Not possible to change sign %s" +msgstr "E885: 変更できない sign です: %s" + #: ../ex_cmds.c:6066 msgid " (not supported)" msgstr " (非サポート)" @@ -1379,6 +1397,13 @@ msgstr "行 %<PRId64>: %s" msgid "cmd: %s" msgstr "コマンド: %s" +msgid "frame is zero" +msgstr "フレームが 0 です" + +#, c-format +msgid "frame at highest level: %d" +msgstr "最高レベルのフレーム: %d" + #: ../ex_cmds2.c:322 #, c-format msgid "Breakpoint in \"%s%s\" line %<PRId64>" @@ -1528,7 +1553,8 @@ msgstr "E197: 言語を \"%s\" に設定できません" #. don't wait for return #: ../ex_docmd.c:387 msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." -msgstr "Exモードに入ります. ノーマルに戻るには\"visual\"と入力してください." +msgstr "" +"Exモードに入ります. ノーマルモードに戻るには\"visual\"と入力してください." #: ../ex_docmd.c:428 msgid "E501: At end-of-file" @@ -1553,7 +1579,7 @@ msgstr "関数の最後です" #: ../ex_docmd.c:1628 msgid "E464: Ambiguous use of user-defined command" -msgstr "E464: ユーザ定義コマンドのあいまいな使用です" +msgstr "E464: ユーザー定義コマンドのあいまいな使用です" #: ../ex_docmd.c:1638 msgid "E492: Not an editor command" @@ -1606,14 +1632,14 @@ msgstr "E174: コマンドが既にあります: 再定義するには ! を追 #: ../ex_docmd.c:4432 msgid "" "\n" -" Name Args Range Complete Definition" +" Name Args Address Complete Definition" msgstr "" "\n" -" 名前 引数 範囲 補完 定義" +" 名前 引数 アドレス 補完 定義" #: ../ex_docmd.c:4516 msgid "No user-defined commands found" -msgstr "ユーザ定義コマンドが見つかりませんでした" +msgstr "ユーザー定義コマンドが見つかりませんでした" #: ../ex_docmd.c:4538 msgid "E175: No attribute specified" @@ -1633,7 +1659,10 @@ msgstr "E178: カウントの省略値が無効です" #: ../ex_docmd.c:4625 msgid "E179: argument required for -complete" -msgstr "E179: -補完のための引数が必要です" +msgstr "E179: -complete には引数が必要です" + +msgid "E179: argument required for -addr" +msgstr "E179: -addr には引数が必要です" #: ../ex_docmd.c:4635 #, c-format @@ -1646,16 +1675,20 @@ msgstr "E182: 無効なコマンド名です" #: ../ex_docmd.c:4691 msgid "E183: User defined commands must start with an uppercase letter" -msgstr "E183: ユーザ定義コマンドは英大文字で始まらなければなりません" +msgstr "E183: ユーザー定義コマンドは英大文字で始まらなければなりません" #: ../ex_docmd.c:4696 msgid "E841: Reserved name, cannot be used for user defined command" -msgstr "E841: 予約名なので, ユーザ定義コマンドに利用できません" +msgstr "E841: 予約名なので, ユーザー定義コマンドに利用できません" #: ../ex_docmd.c:4751 #, c-format msgid "E184: No such user-defined command: %s" -msgstr "E184: そのユーザ定義コマンドはありません: %s" +msgstr "E184: そのユーザー定義コマンドはありません: %s" + +#, c-format +msgid "E180: Invalid address type value: %s" +msgstr "E180: 無効なアドレスタイプ値です: %s" #: ../ex_docmd.c:5219 #, c-format @@ -2019,11 +2052,11 @@ msgstr "不正なファイル名" #: ../fileio.c:395 ../fileio.c:476 ../fileio.c:2543 ../fileio.c:2578 msgid "is a directory" -msgstr " はディレクトリです" +msgstr "はディレクトリです" #: ../fileio.c:397 msgid "is not a file" -msgstr " はファイルではありません" +msgstr "はファイルではありません" #: ../fileio.c:508 ../fileio.c:3522 msgid "[New File]" @@ -2039,7 +2072,7 @@ msgstr "[ファイル過大]" #: ../fileio.c:534 msgid "[Permission Denied]" -msgstr "[認可がありません]" +msgstr "[権限がありません]" #: ../fileio.c:653 msgid "E200: *ReadPre autocommands made the file unreadable" @@ -2210,7 +2243,7 @@ msgstr " 変換エラー" #: ../fileio.c:3509 #, c-format msgid " in line %<PRId64>;" -msgstr "行 %<PRId64>;" +msgstr " 行 %<PRId64>;" #: ../fileio.c:3519 msgid "[Device]" @@ -2766,9 +2799,8 @@ msgid "E37: No write since last change (add ! to override)" msgstr "E37: 最後の変更が保存されていません (! を追加で変更を破棄)" #: ../globals.h:1055 -#, fuzzy msgid "E37: No write since last change" -msgstr "[最後の変更が保存されていません]\n" +msgstr "E37: 最後の変更が保存されていません" #: ../globals.h:1056 msgid "E38: Null argument" @@ -2810,7 +2842,7 @@ msgstr "E42: エラーはありません" #: ../globals.h:1067 msgid "E776: No location list" -msgstr "E776: 場所リストはありません" +msgstr "E776: ロケーションリストはありません" #: ../globals.h:1068 msgid "E43: Damaged match string" @@ -3831,7 +3863,7 @@ msgid "" "\n" msgstr "" "\n" -"それから.swpファイルを削除してください\n" +"元の.swpファイルは削除しても構いません\n" "\n" #. use msg() to start the scrolling properly @@ -3845,7 +3877,7 @@ msgstr " 現在のディレクトリ:\n" #: ../memline.c:1448 msgid " Using specified name:\n" -msgstr " ある名前を使用中:\n" +msgstr " 以下の名前を使用中:\n" #: ../memline.c:1450 msgid " In directory " @@ -3901,7 +3933,7 @@ msgid "" " user name: " msgstr "" "\n" -" ユーザ名: " +" ユーザー名: " #: ../memline.c:1568 msgid " host name: " @@ -4050,12 +4082,12 @@ msgid "" msgstr "" "\n" "(1) 別のプログラムが同じファイルを編集しているかもしれません.\n" -" この場合には, 変更をした際に最終的に, 同じファイルの異なる\n" -" 2つのインスタンスができてしまうことに注意してください." +" この場合には, 変更をしてしまうと1つのファイルに対して異なる2つの\n" +" インスタンスができてしまうので, そうしないように気をつけてください." #: ../memline.c:3245 msgid " Quit, or continue with caution.\n" -msgstr " 終了するか, 注意しながら続けてください.\n" +msgstr " 終了するか, 注意しながら続けてください.\n" #: ../memline.c:3246 msgid "(2) An edit session for this file crashed.\n" @@ -4479,6 +4511,11 @@ msgstr "" msgid "E574: Unknown register type %d" msgstr "E574: 未知のレジスタ型 %d です" +msgid "" +"E883: search pattern and expression register may not contain two or more " +"lines" +msgstr "E883: 検索パターンと式レジスタには2行以上を含められません" + #: ../ops.c:5089 #, c-format msgid "%<PRId64> Cols; " @@ -4563,6 +4600,10 @@ msgstr "E522: termcap 内に見つかりません" msgid "E539: Illegal character <%s>" msgstr "E539: 不正な文字です <%s>" +#, c-format +msgid "For option %s" +msgstr "オプション: %s" + #: ../option.c:3862 msgid "E529: Cannot set 'term' to empty string" msgstr "E529: 'term' には空文字列を設定できません" @@ -4740,6 +4781,14 @@ msgstr "" "\n" "セキュリティコンテキストを設定できません " +#, c-format +msgid "Could not set security context %s for %s" +msgstr "セキュリティコンテキスト %s を %s に設定できません" + +#, c-format +msgid "Could not get security context %s for %s. Removing it!" +msgstr "セキュリティコンテキスト %s を %s から取得できません. 削除します!" + #: ../os_unix.c:1558 ../os_unix.c:1647 #, c-format msgid "dlerror = \"%s\"" @@ -4960,6 +5009,10 @@ msgstr "E554: %s{...} 内に文法エラーがあります" msgid "External submatches:\n" msgstr "外部の部分該当:\n" +#, c-format +msgid "E888: (NFA regexp) cannot repeat %s" +msgstr "E888: (NFA 正規表現) 繰り返せません %s" + #: ../regexp.c:7022 msgid "" "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be " @@ -4968,6 +5021,9 @@ msgstr "" "E864: \\%#= には 0, 1 もしくは 2 のみが続けられます。正規表現エンジンは自動選" "択されます。" +msgid "Switching to backtracking RE engine for pattern: " +msgstr "次のパターンにバックトラッキング RE エンジンを適用します: " + #: ../regexp_nfa.c:239 msgid "E865: (NFA) Regexp end encountered prematurely" msgstr "E865: (NFA) 期待より早く正規表現の終端に到達しました" @@ -4980,7 +5036,7 @@ msgstr "E866: (NFA 正規表現) 位置が誤っています: %c" #: ../regexp_nfa.c:242 #, c-format msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "" +msgstr "E877: (NFA 正規表現) 無効な文字クラス: %<PRId64>" #: ../regexp_nfa.c:1261 #, c-format @@ -5590,12 +5646,12 @@ msgid "E765: 'spellfile' does not have %<PRId64> entries" msgstr "E765: 'spellfile' には %<PRId64> 個のエントリはありません" #: ../spell.c:8074 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' removed from %s" -msgstr "%s から単語が削除されました" +msgstr "単語 '%.*s' が %s から削除されました" #: ../spell.c:8117 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' added to %s" msgstr "%s に単語が追加されました" @@ -5673,6 +5729,9 @@ msgstr "このバッファに定義された構文要素はありません" msgid "E390: Illegal argument: %s" msgstr "E390: 不正な引数です: %s" +msgid "syntax iskeyword " +msgstr "シンタックス用 iskeyword " + #: ../syntax.c:3299 #, c-format msgid "E391: No such syntax cluster: %s" @@ -5769,6 +5828,10 @@ msgstr "E847: 構文の取り込み(include)が多過ぎます" msgid "E789: Missing ']': %s" msgstr "E789: ']' がありません: %s" +#, c-format +msgid "E890: trailing char after ']': %s]%s" +msgstr "E890: ']' の後ろに余分な文字があります: %s]%s" + #: ../syntax.c:4531 #, c-format msgid "E398: Missing '=': %s" @@ -5874,7 +5937,7 @@ msgstr "E415: 予期せぬ等号です: %s" #: ../syntax.c:6395 #, c-format msgid "E416: missing equal sign: %s" -msgstr "E416: 等号ががありません: %s" +msgstr "E416: 等号がありません: %s" #: ../syntax.c:6418 #, c-format @@ -6078,9 +6141,8 @@ msgstr "Vim: 入力を読込み中のエラーにより終了します...\n" #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. #: ../undo.c:379 -#, fuzzy msgid "E881: Line count changed unexpectedly" -msgstr "E834: 予期せず行カウントが変わりました" +msgstr "E881: 予期せず行カウントが変わりました" #: ../undo.c:627 #, c-format @@ -6287,23 +6349,23 @@ msgstr " システム vimrc: \"" #: ../version.c:672 msgid " user vimrc file: \"" -msgstr " ユーザ vimrc: \"" +msgstr " ユーザー vimrc: \"" #: ../version.c:677 msgid " 2nd user vimrc file: \"" -msgstr " 第2ユーザ vimrc: \"" +msgstr " 第2ユーザー vimrc: \"" #: ../version.c:682 msgid " 3rd user vimrc file: \"" -msgstr " 第3ユーザ vimrc: \"" +msgstr " 第3ユーザー vimrc: \"" #: ../version.c:687 msgid " user exrc file: \"" -msgstr " ユーザ exrc: \"" +msgstr " ユーザー exrc: \"" #: ../version.c:692 msgid " 2nd user exrc file: \"" -msgstr " 第2ユーザ exrc: \"" +msgstr " 第2ユーザー exrc: \"" #: ../version.c:699 msgid " fall-back for $VIM: \"" @@ -6379,7 +6441,7 @@ msgstr "Vimの開発を応援してください!" #: ../version.c:828 msgid "Become a registered Vim user!" -msgstr "Vimの登録ユーザになってください!" +msgstr "Vimの登録ユーザーになってください!" #: ../version.c:831 msgid "type :help sponsor<Enter> for information " @@ -6391,7 +6453,7 @@ msgstr "詳細な情報は :help register<Enter> " #: ../version.c:834 msgid "menu Help->Sponsor/Register for information " -msgstr "詳細はメニューの ヘルプ→スポンサー/登録 を参照して下さい " +msgstr "詳細はメニューの ヘルプ->スポンサー/登録 を参照して下さい" #: ../window.c:119 msgid "Already only one window" @@ -6429,6 +6491,9 @@ msgstr "E445: 他のウィンドウには変更があります" msgid "E446: No file name under cursor" msgstr "E446: カーソルの下にファイル名がありません" +msgid "List or number required" +msgstr "リストか数値が必要です" + #~ msgid "E831: bf_key_init() called with empty password" #~ msgstr "E831: bf_key_init() が空パスワードで呼び出されました" diff --git a/src/nvim/po/ja.sjis.po b/src/nvim/po/ja.sjis.po index 7dac89e172..16a5d2ce36 100644 --- a/src/nvim/po/ja.sjis.po +++ b/src/nvim/po/ja.sjis.po @@ -1,11 +1,11 @@ -# Japanese translation for Vim vim:set foldmethod=marker: +# Japanese translation for Vim # # Do ":help uganda" in Vim to read copying and usage conditions. # Do ":help credits" in Vim to see a list of people who contributed. # -# Last Change: 2013 Jul 06 +# Copyright (C) 2001-2016 MURAOKA Taro <koron.kaoriya@gmail.com>, +# vim-jp (http://vim-jp.org/) # -# Copyright (C) 2001-13 MURAOKA Taro <koron.kaoriya@gmail.com> # THIS FILE IS DISTRIBUTED UNDER THE VIM LICENSE. # # Original translations. @@ -14,10 +14,10 @@ msgid "" msgstr "" "Project-Id-Version: Vim 7.4\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-05-26 14:21+0200\n" -"PO-Revision-Date: 2013-07-06 15:00+0900\n" +"POT-Creation-Date: 2016-02-01 09:02+0900\n" +"PO-Revision-Date: 2016-02-01 09:08+0900\n" "Last-Translator: MURAOKA Taro <koron.kaoriya@gmail.com>\n" -"Language-Team: MURAOKA Taro <koron.kaoriya@gmail.com>\n" +"Language-Team: vim-jpj (https://github.com/vim-jp/lang-ja)\n" "Language: Japanese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=cp932\n" @@ -34,7 +34,7 @@ msgstr "G[: m̃IvV^ł" #: ../buffer.c:92 msgid "[Location List]" -msgstr "[ꏊXg]" +msgstr "[P[VXg]" #: ../buffer.c:93 msgid "[Quickfix List]" @@ -277,7 +277,7 @@ msgstr "E810: ꎞt@C̓Ǎ͏ł܂" #: ../diff.c:755 msgid "E97: Cannot create diffs" -msgstr "E97: 쐬ł܂ " +msgstr "E97: 쐬ł܂" #: ../diff.c:966 msgid "E816: Cannot read patch output" @@ -293,7 +293,7 @@ msgstr "E99: ݂̃obt@͍[hł͂܂" #: ../diff.c:2100 msgid "E793: No other buffer in diff mode is modifiable" -msgstr "E793: [hł鑼̃obt@͕ύX\\ł" +msgstr "E793: [hł鑼̃obt@͕ύXł܂" #: ../diff.c:2102 msgid "E100: No other buffer in diff mode" @@ -349,7 +349,7 @@ msgstr " s(S)⊮ (^L^N^P)" #: ../edit.c:86 msgid " File name completion (^F^N^P)" -msgstr "t@C⊮ (^F^N^P)" +msgstr " t@C⊮ (^F^N^P)" #: ../edit.c:87 msgid " Tag completion (^]^N^P)" @@ -377,7 +377,7 @@ msgstr " R}hC⊮ (^V^N^P)" #: ../edit.c:94 msgid " User defined completion (^U^N^P)" -msgstr " [U`⊮ (^U^N^P)" +msgstr " [U[`⊮ (^U^N^P)" #: ../edit.c:95 msgid " Omni completion (^O^N^P)" @@ -679,6 +679,10 @@ msgstr "E696: Xg^ɃJ}܂: %s" msgid "E697: Missing end of List ']': %s" msgstr "E697: Xg^̍Ō ']' ܂: %s" +msgid "Not enough memory to set references, garbage collection aborted!" +msgstr "" +"K[xbWRNV𒆎~܂! QƂ쐬̂Ƀs܂" + #: ../eval.c:6475 #, c-format msgid "E720: Missing colon in Dictionary: %s" @@ -721,7 +725,7 @@ msgstr "E117: m̊ł: %s" #: ../eval.c:7383 #, c-format msgid "E119: Not enough arguments for function: %s" -msgstr "E119: ̈ȉ߂܂: %s" +msgstr "E119: ̈܂: %s" #: ../eval.c:7387 #, c-format @@ -826,18 +830,16 @@ msgid "sort() argument" msgstr "sort() ̈" #: ../eval.c:13721 -#, fuzzy msgid "uniq() argument" -msgstr "add() ̈" +msgstr "uniq() ̈" #: ../eval.c:13776 msgid "E702: Sort compare function failed" msgstr "E702: \\[g̔rs܂" #: ../eval.c:13806 -#, fuzzy msgid "E882: Uniq compare function failed" -msgstr "E702: \\[g̔rs܂" +msgstr "E882: Uniq ̔rs܂" #: ../eval.c:14085 msgid "(Invalid)" @@ -863,6 +865,18 @@ msgstr "E745: Xg^𐔒lƂĈĂ܂" msgid "E728: Using a Dictionary as a Number" msgstr "E728: ^𐔒lƂĈĂ܂" +msgid "E891: Using a Funcref as a Float" +msgstr "E891: Qƌ^_ƂĈĂ܂B" + +msgid "E892: Using a String as a Float" +msgstr "E892: _ƂĈĂ܂" + +msgid "E893: Using a List as a Float" +msgstr "E893: Xg^_ƂĈĂ܂" + +msgid "E894: Using a Dictionary as a Float" +msgstr "E894: ^_ƂĈĂ܂" + #: ../eval.c:16259 msgid "E729: using Funcref as a String" msgstr "E729: Qƌ^ƂĈĂ܂" @@ -961,14 +975,14 @@ msgid "E129: Function name required" msgstr "E129: v܂" #: ../eval.c:17824 -#, fuzzy, c-format +#, c-format msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "E128: ͑啶Ŏn܂邩R܂܂ȂȂ܂: %s" +msgstr "E128: ͑啶 \"s:\" Ŏn܂ȂȂ܂: %s" #: ../eval.c:17833 -#, fuzzy, c-format +#, c-format msgid "E884: Function name cannot contain a colon: %s" -msgstr "E128: ͑啶Ŏn܂邩R܂܂ȂȂ܂: %s" +msgstr "E884: ɂ̓R͊܂߂܂: %s" #: ../eval.c:18336 #, c-format @@ -1081,7 +1095,7 @@ msgstr "E136: viminfo: G[߂̂, ȍ~̓XLbv܂" #: ../ex_cmds.c:1458 #, c-format msgid "Reading viminfo file \"%s\"%s%s%s" -msgstr "viminfot@C \"%s\"%s%s%s Ǎݒ " +msgstr "viminfot@C \"%s\"%s%s%s Ǎݒ" #: ../ex_cmds.c:1460 msgid " info" @@ -1357,6 +1371,10 @@ msgstr "E158: ȃobt@ł: %s" msgid "E157: Invalid sign ID: %<PRId64>" msgstr "E157: signʎqł: %<PRId64>" +#, c-format +msgid "E885: Not possible to change sign %s" +msgstr "E885: ύXłȂ sign ł: %s" + #: ../ex_cmds.c:6066 msgid " (not supported)" msgstr " (T|[g)" @@ -1379,6 +1397,13 @@ msgstr "s %<PRId64>: %s" msgid "cmd: %s" msgstr "R}h: %s" +msgid "frame is zero" +msgstr "t[ 0 ł" + +#, c-format +msgid "frame at highest level: %d" +msgstr "ōx̃t[: %d" + #: ../ex_cmds2.c:322 #, c-format msgid "Breakpoint in \"%s%s\" line %<PRId64>" @@ -1528,7 +1553,8 @@ msgstr "E197: \"%s\" ɐݒł܂" #. don't wait for return #: ../ex_docmd.c:387 msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." -msgstr "Ex[hɓ܂. m[}ɖ߂ɂ\"visual\"Ɠ͂Ă." +msgstr "" +"Ex[hɓ܂. m[}[hɖ߂ɂ\"visual\"Ɠ͂Ă." #: ../ex_docmd.c:428 msgid "E501: At end-of-file" @@ -1553,7 +1579,7 @@ msgstr "̍Ōł" #: ../ex_docmd.c:1628 msgid "E464: Ambiguous use of user-defined command" -msgstr "E464: [U`R}ĥ܂Ȏgpł" +msgstr "E464: [U[`R}ĥ܂Ȏgpł" #: ../ex_docmd.c:1638 msgid "E492: Not an editor command" @@ -1606,14 +1632,14 @@ msgstr "E174: R}hɂ܂: Ē`ɂ ! ljĂ" #: ../ex_docmd.c:4432 msgid "" "\n" -" Name Args Range Complete Definition" +" Name Args Address Complete Definition" msgstr "" "\n" -" O ͈ ⊮ `" +" O AhX ⊮ `" #: ../ex_docmd.c:4516 msgid "No user-defined commands found" -msgstr "[U`R}h܂ł" +msgstr "[U[`R}h܂ł" #: ../ex_docmd.c:4538 msgid "E175: No attribute specified" @@ -1633,7 +1659,10 @@ msgstr "E178: JEg̏ȗlł" #: ../ex_docmd.c:4625 msgid "E179: argument required for -complete" -msgstr "E179: -⊮̂߂̈Kvł" +msgstr "E179: -complete ɂ͈Kvł" + +msgid "E179: argument required for -addr" +msgstr "E179: -addr ɂ͈Kvł" #: ../ex_docmd.c:4635 #, c-format @@ -1646,16 +1675,20 @@ msgstr "E182: ȃR}hł" #: ../ex_docmd.c:4691 msgid "E183: User defined commands must start with an uppercase letter" -msgstr "E183: [U`R}h͉p啶Ŏn܂ȂȂ܂" +msgstr "E183: [U[`R}h͉p啶Ŏn܂ȂȂ܂" #: ../ex_docmd.c:4696 msgid "E841: Reserved name, cannot be used for user defined command" -msgstr "E841: \\Ȃ̂, [U`R}hɗpł܂" +msgstr "E841: \\Ȃ̂, [U[`R}hɗpł܂" #: ../ex_docmd.c:4751 #, c-format msgid "E184: No such user-defined command: %s" -msgstr "E184: ̃[U`R}h͂܂: %s" +msgstr "E184: ̃[U[`R}h͂܂: %s" + +#, c-format +msgid "E180: Invalid address type value: %s" +msgstr "E180: ȃAhX^Cvlł: %s" #: ../ex_docmd.c:5219 #, c-format @@ -2019,11 +2052,11 @@ msgstr "sȃt@C" #: ../fileio.c:395 ../fileio.c:476 ../fileio.c:2543 ../fileio.c:2578 msgid "is a directory" -msgstr " ̓fBNgł" +msgstr "̓fBNgł" #: ../fileio.c:397 msgid "is not a file" -msgstr " ̓t@Cł͂܂" +msgstr "̓t@Cł͂܂" #: ../fileio.c:508 ../fileio.c:3522 msgid "[New File]" @@ -2039,7 +2072,7 @@ msgstr "[t@Cߑ]" #: ../fileio.c:534 msgid "[Permission Denied]" -msgstr "[F܂]" +msgstr "[܂]" #: ../fileio.c:653 msgid "E200: *ReadPre autocommands made the file unreadable" @@ -2210,7 +2243,7 @@ msgstr " ϊG[" #: ../fileio.c:3509 #, c-format msgid " in line %<PRId64>;" -msgstr "s %<PRId64>;" +msgstr " s %<PRId64>;" #: ../fileio.c:3519 msgid "[Device]" @@ -2766,9 +2799,8 @@ msgid "E37: No write since last change (add ! to override)" msgstr "E37: Ō̕ύXۑĂ܂ (! ljŕύXj)" #: ../globals.h:1055 -#, fuzzy msgid "E37: No write since last change" -msgstr "[Ō̕ύXۑĂ܂]\n" +msgstr "E37: Ō̕ύXۑĂ܂" #: ../globals.h:1056 msgid "E38: Null argument" @@ -2810,7 +2842,7 @@ msgstr "E42: G[͂܂" #: ../globals.h:1067 msgid "E776: No location list" -msgstr "E776: ꏊXg͂܂" +msgstr "E776: P[VXg͂܂" #: ../globals.h:1068 msgid "E43: Damaged match string" @@ -2931,6 +2963,10 @@ msgstr "E363: p^[ 'maxmempattern' ȏ̃gp܂" msgid "E749: empty buffer" msgstr "E749: obt@ł" +#, c-format +msgid "E86: Buffer %ld does not exist" +msgstr "E86: obt@ %ld ͂܂" + #: ../globals.h:1108 msgid "E682: Invalid search pattern or delimiter" msgstr "E682: p^[Lsł" @@ -3831,7 +3867,7 @@ msgid "" "\n" msgstr "" "\n" -"ꂩ.swpt@C폜Ă\n" +".swpt@C͍폜Ă\\܂\n" "\n" #. use msg() to start the scrolling properly @@ -3845,7 +3881,7 @@ msgstr " ݂̃fBNg:\n" #: ../memline.c:1448 msgid " Using specified name:\n" -msgstr " 閼Ogp:\n" +msgstr " ȉ̖Ogp:\n" #: ../memline.c:1450 msgid " In directory " @@ -3901,7 +3937,7 @@ msgid "" " user name: " msgstr "" "\n" -" [U: " +" [U[: " #: ../memline.c:1568 msgid " host name: " @@ -4050,12 +4086,12 @@ msgid "" msgstr "" "\n" "(1) ʂ̃vOt@CҏWĂ邩܂.\n" -" ̏ꍇɂ, ύXۂɍŏII, t@C̈قȂ\n" -" 2̃CX^XłĂ܂ƂɒӂĂ." +" ̏ꍇɂ, ύXĂ܂1̃t@CɑĈقȂ2\n" +" CX^XłĂ܂̂, Ȃ悤ɋCĂ." #: ../memline.c:3245 msgid " Quit, or continue with caution.\n" -msgstr " I邩, ӂȂ瑱Ă.\n" +msgstr " I邩, ӂȂ瑱Ă.\n" #: ../memline.c:3246 msgid "(2) An edit session for this file crashed.\n" @@ -4479,6 +4515,11 @@ msgstr "" msgid "E574: Unknown register type %d" msgstr "E574: m̃WX^^ %d ł" +msgid "" +"E883: search pattern and expression register may not contain two or more " +"lines" +msgstr "E883: p^[ƎWX^ɂ2sȏ܂߂܂" + #: ../ops.c:5089 #, c-format msgid "%<PRId64> Cols; " @@ -4563,6 +4604,10 @@ msgstr "E522: termcap Ɍ܂" msgid "E539: Illegal character <%s>" msgstr "E539: sȕł <%s>" +#, c-format +msgid "For option %s" +msgstr "IvV: %s" + #: ../option.c:3862 msgid "E529: Cannot set 'term' to empty string" msgstr "E529: 'term' ɂ͋ݒł܂" @@ -4740,6 +4785,14 @@ msgstr "" "\n" "ZLeBReLXgݒł܂ " +#, c-format +msgid "Could not set security context %s for %s" +msgstr "ZLeBReLXg %s %s ɐݒł܂" + +#, c-format +msgid "Could not get security context %s for %s. Removing it!" +msgstr "ZLeBReLXg %s %s 擾ł܂. 폜܂!" + #: ../os_unix.c:1558 ../os_unix.c:1647 #, c-format msgid "dlerror = \"%s\"" @@ -4960,6 +5013,10 @@ msgstr "E554: %s{...} ɕ@G[܂" msgid "External submatches:\n" msgstr "O̕Y:\n" +#, c-format +msgid "E888: (NFA regexp) cannot repeat %s" +msgstr "E888: (NFA K\\) JԂ܂ %s" + #: ../regexp.c:7022 msgid "" "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be " @@ -4968,7 +5025,9 @@ msgstr "" "E864: \\%#= ɂ 0, 1 2 ݂̂܂BK\\GW͎I" "܂B" -#: ../regexp_nfa.c:239 +msgid "Switching to backtracking RE engine for pattern: " +msgstr "̃p^[ɃobNgbLO RE GWKp܂: " + msgid "E865: (NFA) Regexp end encountered prematurely" msgstr "E865: (NFA) ҂葁K\\̏I[ɓB܂" @@ -4980,7 +5039,7 @@ msgstr "E866: (NFA K\\) ʒuĂ܂: %c" #: ../regexp_nfa.c:242 #, c-format msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "" +msgstr "E877: (NFA K\\) ȕNX: %<PRId64>" #: ../regexp_nfa.c:1261 #, c-format @@ -5590,14 +5649,14 @@ msgid "E765: 'spellfile' does not have %<PRId64> entries" msgstr "E765: 'spellfile' ɂ %<PRId64> ̃Gg͂܂" #: ../spell.c:8074 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' removed from %s" -msgstr "%s Pꂪ폜܂" +msgstr "P '%.*s' %s 폜܂" #: ../spell.c:8117 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' added to %s" -msgstr "%s ɒPꂪlj܂" +msgstr "P '%.*s' %s ֒lj܂" #: ../spell.c:8381 msgid "E763: Word characters differ between spell files" @@ -5673,6 +5732,9 @@ msgstr "̃obt@ɒ`ꂽ\\vf͂܂" msgid "E390: Illegal argument: %s" msgstr "E390: sȈł: %s" +msgid "syntax iskeyword " +msgstr "V^bNXp iskeyword " + #: ../syntax.c:3299 #, c-format msgid "E391: No such syntax cluster: %s" @@ -5769,6 +5831,10 @@ msgstr "E847: \\̎荞(include)߂܂" msgid "E789: Missing ']': %s" msgstr "E789: ']' ܂: %s" +#, c-format +msgid "E890: trailing char after ']': %s]%s" +msgstr "E890: ']' ̌ɗ]ȕ܂: %s]%s" + #: ../syntax.c:4531 #, c-format msgid "E398: Missing '=': %s" @@ -5874,7 +5940,7 @@ msgstr "E415: \\ʓł: %s" #: ../syntax.c:6395 #, c-format msgid "E416: missing equal sign: %s" -msgstr "E416: ܂: %s" +msgstr "E416: ܂: %s" #: ../syntax.c:6418 #, c-format @@ -6078,9 +6144,8 @@ msgstr "Vim: ͂Ǎݒ̃G[ɂI܂...\n" #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. #: ../undo.c:379 -#, fuzzy msgid "E881: Line count changed unexpectedly" -msgstr "E834: \\sJEgς܂" +msgstr "E881: \\sJEgς܂" #: ../undo.c:627 #, c-format @@ -6287,23 +6352,23 @@ msgstr " VXe vimrc: \"" #: ../version.c:672 msgid " user vimrc file: \"" -msgstr " [U vimrc: \"" +msgstr " [U[ vimrc: \"" #: ../version.c:677 msgid " 2nd user vimrc file: \"" -msgstr " 2[U vimrc: \"" +msgstr " 2[U[ vimrc: \"" #: ../version.c:682 msgid " 3rd user vimrc file: \"" -msgstr " 3[U vimrc: \"" +msgstr " 3[U[ vimrc: \"" #: ../version.c:687 msgid " user exrc file: \"" -msgstr " [U exrc: \"" +msgstr " [U[ exrc: \"" #: ../version.c:692 msgid " 2nd user exrc file: \"" -msgstr " 2[U exrc: \"" +msgstr " 2[U[ exrc: \"" #: ../version.c:699 msgid " fall-back for $VIM: \"" @@ -6379,7 +6444,7 @@ msgstr "Vim̊JĂ!" #: ../version.c:828 msgid "Become a registered Vim user!" -msgstr "Vim̓o^[UɂȂĂ!" +msgstr "Vim̓o^[U[ɂȂĂ!" #: ../version.c:831 msgid "type :help sponsor<Enter> for information " @@ -6391,7 +6456,7 @@ msgstr "ڍׂȏ :help register<Enter> " #: ../version.c:834 msgid "menu Help->Sponsor/Register for information " -msgstr "ڍׂ̓j[ wvX|T[/o^ QƂĉ " +msgstr "ڍׂ̓j[ wv->X|T[/o^ QƂĉ" #: ../window.c:119 msgid "Already only one window" @@ -6429,6 +6494,9 @@ msgstr "E445: ̃EBhEɂ͕ύX܂" msgid "E446: No file name under cursor" msgstr "E446: J[\\̉Ƀt@C܂" +msgid "List or number required" +msgstr "XglKvł" + #~ msgid "E831: bf_key_init() called with empty password" #~ msgstr "E831: bf_key_init() pX[hŌĂяo܂" diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 0acaa9ae2b..d2401b6776 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -45,6 +45,9 @@ // Use SPELL_PRINTTREE for debugging: dump the word tree after adding a word. // Only use it for small word lists! +// Use SPELL_COMPRESS_ALLWAYS for debugging: compress the word tree after +// adding a word. Only use it for small word lists! + // Use DEBUG_TRIEWALK to print the changes made in suggest_trie_walk() for a // specific word. @@ -156,6 +159,8 @@ // // sectionID == SN_NOSPLITSUGS: nothing // +// sectionID == SN_NOCOMPOUNDSUGS: nothing +// // sectionID == SN_WORDS: <word> ... // <word> N bytes NUL terminated common word // @@ -482,7 +487,7 @@ struct slang_S { regprog_T **sl_prefprog; // table with regprogs for prefixes garray_T sl_rep; // list of fromto_T entries from REP lines - short sl_rep_first[256]; // indexes where byte first appears, -1 if + int16_t sl_rep_first[256]; // indexes where byte first appears, -1 if // there is none garray_T sl_sal; // list of salitem_T entries from SAL lines salfirst_T sl_sal_first[256]; // indexes where byte first appears, -1 if @@ -494,8 +499,9 @@ struct slang_S { // "sl_sal_first" maps chars, when has_mbyte // "sl_sal" is a list of wide char lists. garray_T sl_repsal; // list of fromto_T entries from REPSAL lines - short sl_repsal_first[256]; // sl_rep_first for REPSAL lines - bool sl_nosplitsugs; // don't suggest splitting a word + int16_t sl_repsal_first[256]; // sl_rep_first for REPSAL lines + bool sl_nosplitsugs; // don't suggest splitting a word + bool sl_nocompoundsugs; // don't suggest compounding // Info from the .sug file. Loaded on demand. time_t sl_sugtime; // timestamp for .sug file @@ -558,6 +564,7 @@ typedef struct langp_S { #define SN_WORDS 13 // common words #define SN_NOSPLITSUGS 14 // don't split word for suggestions #define SN_INFO 15 // info section +#define SN_NOCOMPOUNDSUGS 16 // don't compound for suggestions #define SN_END 255 // end of sections #define SNF_REQUIRED 1 // <sectionflags>: required section @@ -948,6 +955,7 @@ typedef struct spellinfo_S { char_u *si_sofoto; // SOFOTO text int si_nosugfile; // NOSUGFILE item found int si_nosplitsugs; // NOSPLITSUGS item found + int si_nocompoundsugs; // NOCOMPOUNDSUGS item found int si_followup; // soundsalike: ? int si_collapse; // soundsalike: ? hashtab_T si_commonwords; // hashtable for common words @@ -2666,7 +2674,11 @@ spell_load_file ( break; case SN_NOSPLITSUGS: - lp->sl_nosplitsugs = true; // <timestamp> + lp->sl_nosplitsugs = true; + break; + + case SN_NOCOMPOUNDSUGS: + lp->sl_nocompoundsugs = true; break; case SN_COMPOUND: @@ -2868,7 +2880,7 @@ static int read_prefcond_section(FILE *fd, slang_T *lp) // Read REP or REPSAL items section from "fd": <repcount> <rep> ... // Return SP_*ERROR flags. -static int read_rep_section(FILE *fd, garray_T *gap, short *first) +static int read_rep_section(FILE *fd, garray_T *gap, int16_t *first) { int cnt; fromto_T *ftp; @@ -4266,9 +4278,9 @@ static void spell_print_node(wordnode_T *node, int depth) PRINTSOME(line1, depth, "(%d)", node->wn_nr, 0); PRINTSOME(line2, depth, " ", 0, 0); PRINTSOME(line3, depth, " ", 0, 0); - msg(line1); - msg(line2); - msg(line3); + msg((char_u *)line1); + msg((char_u *)line2); + msg((char_u *)line3); } else { node->wn_u1.index = TRUE; @@ -4289,9 +4301,9 @@ static void spell_print_node(wordnode_T *node, int depth) PRINTSOME(line3, depth, " ", 0, 0); if (node->wn_byte == NUL) { - msg(line1); - msg(line2); - msg(line3); + msg((char_u *)line1); + msg((char_u *)line2); + msg((char_u *)line3); } // do the children @@ -4633,6 +4645,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) spin->si_nobreak = true; } else if (is_aff_rule(items, itemcnt, "NOSPLITSUGS", 1)) { spin->si_nosplitsugs = true; + } else if (is_aff_rule(items, itemcnt, "NOCOMPOUNDSUGS", 1)) { + spin->si_nocompoundsugs = true; } else if (is_aff_rule(items, itemcnt, "NOSUGFILE", 1)) { spin->si_nosugfile = true; } else if (is_aff_rule(items, itemcnt, "PFXPOSTPONE", 1)) { @@ -6289,7 +6303,7 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int node = *prev; } #ifdef SPELL_PRINTTREE - smsg("Added \"%s\"", word); + smsg((char_u *)"Added \"%s\"", word); spell_print_tree(root->wn_sibling); #endif @@ -6312,8 +6326,8 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int // 3. When compressed before, added "compress_added" words // (si_compress_cnt == 1) and the number of free nodes drops below the // maximum word length. -#ifndef SPELL_PRINTTREE - if (spin->si_compress_cnt == 1 +#ifndef SPELL_COMPRESS_ALLWAYS + if (spin->si_compress_cnt == 1 // NOLINT(readability/braces) ? spin->si_free_count < MAXWLEN : spin->si_blocks_cnt >= compress_start) #endif @@ -6857,6 +6871,15 @@ static int write_vim_spell(spellinfo_T *spin, char_u *fname) put_bytes(fd, 0, 4); // <sectionlen> } + // SN_NOCOMPUNDSUGS: nothing + // This is used to notify that no suggestions with compounds are to be + // made. + if (spin->si_nocompoundsugs) { + putc(SN_NOCOMPOUNDSUGS, fd); // <sectionID> + putc(0, fd); // <sectionflags> + put_bytes(fd, 0, 4); // <sectionlen> + } + // SN_COMPOUND: compound info. // We don't mark it required, when not supported all compound words will // be bad words. @@ -9296,7 +9319,56 @@ static void suggest_try_special(suginfo_T *su) } } +// Measure how much time is spent in each state. +// Output is dumped in "suggestprof". + +#ifdef SUGGEST_PROFILE +proftime_T current; +proftime_T total; +proftime_T times[STATE_FINAL + 1]; +long counts[STATE_FINAL + 1]; + + static void +prof_init(void) +{ + for (int i = 0; i <= STATE_FINAL; i++) { + profile_zero(×[i]); + counts[i] = 0; + } + profile_start(¤t); + profile_start(&total); +} + +// call before changing state + static void +prof_store(state_T state) +{ + profile_end(¤t); + profile_add(×[state], ¤t); + counts[state]++; + profile_start(¤t); +} +# define PROF_STORE(state) prof_store(state); + + static void +prof_report(char *name) +{ + FILE *fd = fopen("suggestprof", "a"); + + profile_end(&total); + fprintf(fd, "-----------------------\n"); + fprintf(fd, "%s: %s\n", name, profile_msg(&total)); + for (int i = 0; i <= STATE_FINAL; i++) { + fprintf(fd, "%d: %s ("%" PRId64)\n", i, profile_msg(×[i]), counts[i]); + } + fclose(fd); +} +#else +# define PROF_STORE(state) +#endif + // Try finding suggestions by adding/removing/swapping letters. + static void suggest_try_change(suginfo_T *su) { char_u fword[MAXWLEN]; // copy of the bad word, case-folded @@ -9321,7 +9393,14 @@ static void suggest_try_change(suginfo_T *su) continue; // Try it for this language. Will add possible suggestions. + // +#ifdef SUGGEST_PROFILE + prof_init(); +#endif suggest_trie_walk(su, lp, fword, false); +#ifdef SUGGEST_PROFILE + prof_report("try_change"); +#endif } } @@ -9455,6 +9534,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // Always past NUL bytes now. n = (int)sp->ts_state; + PROF_STORE(sp->ts_state) sp->ts_state = STATE_ENDNUL; sp->ts_save_badflags = su->su_badflags; @@ -9494,6 +9574,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so if (sp->ts_curi > len || byts[arridx] != 0) { // Past bytes in node and/or past NUL bytes. + PROF_STORE(sp->ts_state) sp->ts_state = STATE_ENDNUL; sp->ts_save_badflags = su->su_badflags; break; @@ -9771,6 +9852,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // be possible to compound another (short) word. try_compound = false; if (!soundfold + && !slang->sl_nocompoundsugs && slang->sl_compprog != NULL && ((unsigned)flags >> 24) != 0 && sp->ts_twordlen - sp->ts_splitoff @@ -9791,21 +9873,21 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // For NOBREAK we never try splitting, it won't make any word // valid. - if (slang->sl_nobreak) + if (slang->sl_nobreak && !slang->sl_nocompoundsugs) { try_compound = true; - - // If we could add a compound word, and it's also possible to - // split at this point, do the split first and set - // TSF_DIDSPLIT to avoid doing it again. - else if (!fword_ends - && try_compound - && (sp->ts_flags & TSF_DIDSPLIT) == 0) { + } else if (!fword_ends + && try_compound + && (sp->ts_flags & TSF_DIDSPLIT) == 0) { + // If we could add a compound word, and it's also possible to + // split at this point, do the split first and set + // TSF_DIDSPLIT to avoid doing it again. try_compound = false; sp->ts_flags |= TSF_DIDSPLIT; --sp->ts_curi; // do the same NUL again compflags[sp->ts_complen] = NUL; - } else + } else { sp->ts_flags &= ~TSF_DIDSPLIT; + } if (try_split || try_compound) { if (!try_compound && (!fword_ends || !goodword_ends)) { @@ -9846,6 +9928,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so #endif // Save things to be restored at STATE_SPLITUNDO. sp->ts_save_badflags = su->su_badflags; + PROF_STORE(sp->ts_state) sp->ts_state = STATE_SPLITUNDO; ++depth; @@ -9912,6 +9995,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so byts = pbyts; idxs = pidxs; sp->ts_prefixdepth = PFD_PREFIXTREE; + PROF_STORE(sp->ts_state) sp->ts_state = STATE_NOPREFIX; } } @@ -9924,6 +10008,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so su->su_badflags = sp->ts_save_badflags; // Continue looking for NUL bytes. + PROF_STORE(sp->ts_state) sp->ts_state = STATE_START; // In case we went into the prefix tree. @@ -9938,9 +10023,11 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so && sp->ts_tcharlen == 0 ) { // The badword ends, can't use STATE_PLAIN. + PROF_STORE(sp->ts_state) sp->ts_state = STATE_DEL; break; } + PROF_STORE(sp->ts_state) sp->ts_state = STATE_PLAIN; // FALLTHROUGH @@ -9951,10 +10038,12 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so if (sp->ts_curi > byts[arridx]) { // Done all bytes at this node, do next state. When still at // already changed bytes skip the other tricks. - if (sp->ts_fidx >= sp->ts_fidxtry) + PROF_STORE(sp->ts_state) + if (sp->ts_fidx >= sp->ts_fidxtry) { sp->ts_state = STATE_DEL; - else + } else { sp->ts_state = STATE_FINAL; + } } else { arridx += sp->ts_curi++; c = byts[arridx]; @@ -10086,10 +10175,12 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // When past the first byte of a multi-byte char don't try // delete/insert/swap a character. if (has_mbyte && sp->ts_tcharlen > 0) { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_FINAL; break; } // Try skipping one character in the bad word (delete it). + PROF_STORE(sp->ts_state) sp->ts_state = STATE_INS_PREP; sp->ts_curi = 1; if (soundfold && sp->ts_fidx == 0 && fword[sp->ts_fidx] == '*') @@ -10137,6 +10228,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so if (sp->ts_flags & TSF_DIDDEL) { // If we just deleted a byte then inserting won't make sense, // a substitute is always cheaper. + PROF_STORE(sp->ts_state) sp->ts_state = STATE_SWAP; break; } @@ -10146,11 +10238,13 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so for (;; ) { if (sp->ts_curi > byts[n]) { // Only NUL bytes at this node, go to next state. + PROF_STORE(sp->ts_state) sp->ts_state = STATE_SWAP; break; } if (byts[n + sp->ts_curi] != NUL) { // Found a byte to insert. + PROF_STORE(sp->ts_state) sp->ts_state = STATE_INS; break; } @@ -10166,6 +10260,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so n = sp->ts_arridx; if (sp->ts_curi > byts[n]) { // Done all bytes at this node, go to next state. + PROF_STORE(sp->ts_state) sp->ts_state = STATE_SWAP; break; } @@ -10226,6 +10321,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so c = *p; if (c == NUL) { // End of word, can't swap or replace. + PROF_STORE(sp->ts_state) sp->ts_state = STATE_FINAL; break; } @@ -10233,6 +10329,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // Don't swap if the first character is not a word character. // SWAP3 etc. also don't make sense then. if (!soundfold && !spell_iswordp(p, curwin)) { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; break; } @@ -10257,6 +10354,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // When the second character is NUL we can't swap. if (c2 == NUL) { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; break; } @@ -10264,6 +10362,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // When characters are identical, swap won't do anything. // Also get here if the second char is not a word character. if (c == c2) { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_SWAP3; break; } @@ -10274,6 +10373,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so sp->ts_twordlen, tword, fword + sp->ts_fidx, c, c2); #endif + PROF_STORE(sp->ts_state) sp->ts_state = STATE_UNSWAP; ++depth; if (has_mbyte) { @@ -10288,6 +10388,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so } } else // If this swap doesn't work then SWAP3 won't either. + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; break; @@ -10335,6 +10436,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // Also get here when the third character is not a word character. // Second character may any char: "a.b" -> "b.a" if (c == c3 || c3 == NUL) { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; break; } @@ -10345,6 +10447,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so sp->ts_twordlen, tword, fword + sp->ts_fidx, c, c3); #endif + PROF_STORE(sp->ts_state) sp->ts_state = STATE_UNSWAP3; ++depth; if (has_mbyte) { @@ -10358,8 +10461,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so p[2] = c; stack[depth].ts_fidxtry = sp->ts_fidx + 3; } - } else + } else { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; + } break; case STATE_UNSWAP3: @@ -10385,6 +10490,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so if (!soundfold && !spell_iswordp(p, curwin)) { // Middle char is not a word char, skip the rotate. First and // third char were already checked at swap and swap3. + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; break; } @@ -10399,6 +10505,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so sp->ts_twordlen, tword, fword + sp->ts_fidx, p[0], p[1], p[2]); #endif + PROF_STORE(sp->ts_state) sp->ts_state = STATE_UNROT3L; ++depth; p = fword + sp->ts_fidx; @@ -10417,8 +10524,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so p[2] = c; stack[depth].ts_fidxtry = sp->ts_fidx + 3; } - } else + } else { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; + } break; case STATE_UNROT3L: @@ -10448,6 +10557,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so sp->ts_twordlen, tword, fword + sp->ts_fidx, p[0], p[1], p[2]); #endif + PROF_STORE(sp->ts_state) sp->ts_state = STATE_UNROT3R; ++depth; p = fword + sp->ts_fidx; @@ -10466,8 +10576,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so *p = c; stack[depth].ts_fidxtry = sp->ts_fidx + 3; } - } else + } else { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; + } break; case STATE_UNROT3R: @@ -10497,6 +10609,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so if ((lp->lp_replang == NULL && !soundfold) || sp->ts_score + SCORE_REP >= su->su_maxscore || sp->ts_fidx < sp->ts_fidxtry) { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_FINAL; break; } @@ -10509,10 +10622,12 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so sp->ts_curi = lp->lp_replang->sl_rep_first[fword[sp->ts_fidx]]; if (sp->ts_curi < 0) { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_FINAL; break; } + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP; // FALLTHROUGH @@ -10542,6 +10657,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so ftp->ft_from, ftp->ft_to); #endif // Need to undo this afterwards. + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_UNDO; // Change the "from" to the "to" string. @@ -10561,6 +10677,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so if (sp->ts_curi >= gap->ga_len && sp->ts_state == STATE_REP) // No (more) matches. + PROF_STORE(sp->ts_state) sp->ts_state = STATE_FINAL; break; @@ -10580,6 +10697,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so repextra -= tl - fl; } memmove(p, ftp->ft_from, fl); + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP; break; @@ -10990,7 +11108,13 @@ static void suggest_try_soundalike(suginfo_T *su) // try all kinds of inserts/deletes/swaps/etc. // TODO: also soundfold the next words, so that we can try joining // and splitting +#ifdef SUGGEST_PROFILE + prof_init(); +#endif suggest_trie_walk(su, lp, salword, true); +#ifdef SUGGEST_PROFILE + prof_report("soundalike"); +#endif } } } @@ -13340,3 +13464,4 @@ int expand_spelling(linenr_T lnum, char_u *pat, char_u ***matchp) return ga.ga_len; } + diff --git a/src/nvim/state.c b/src/nvim/state.c index b2f3f0bebe..30133e2201 100644 --- a/src/nvim/state.c +++ b/src/nvim/state.c @@ -4,6 +4,7 @@ #include "nvim/state.h" #include "nvim/vim.h" +#include "nvim/main.h" #include "nvim/getchar.h" #include "nvim/ui.h" #include "nvim/os/input.h" @@ -32,7 +33,7 @@ getkey: // processing. Characters can come from mappings, scripts and other // sources, so this scenario is very common. key = safe_vgetc(); - } else if (!queue_empty(loop.events)) { + } else if (!queue_empty(main_loop.events)) { // Event was made available after the last queue_process_events call key = K_EVENT; } else { @@ -45,7 +46,7 @@ getkey: // directly. (void)os_inchar(NULL, 0, -1, 0); input_disable_events(); - key = !queue_empty(loop.events) ? K_EVENT : safe_vgetc(); + key = !queue_empty(main_loop.events) ? K_EVENT : safe_vgetc(); } if (key == K_EVENT) { diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 9a5484704e..9e4dc0204f 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -812,19 +812,39 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid) validate_current_state(); } +static void save_chartab(char_u *chartab) +{ + if (syn_block->b_syn_isk != empty_option) { + memmove(chartab, syn_buf->b_chartab, (size_t)32); + memmove(syn_buf->b_chartab, syn_win->w_s->b_syn_chartab, (size_t)32); + } +} + +static void restore_chartab(char_u *chartab) +{ + if (syn_win->w_s->b_syn_isk != empty_option) { + memmove(syn_buf->b_chartab, chartab, (size_t)32); + } +} + /* * Return TRUE if the line-continuation pattern matches in line "lnum". */ static int syn_match_linecont(linenr_T lnum) { - regmmatch_T regmatch; - if (syn_block->b_syn_linecont_prog != NULL) { + regmmatch_T regmatch; + // chartab array for syn iskeyword + char_u buf_chartab[32]; + save_chartab(buf_chartab); + regmatch.rmm_ic = syn_block->b_syn_linecont_ic; regmatch.regprog = syn_block->b_syn_linecont_prog; int r = syn_regexec(®match, lnum, (colnr_T)0, IF_SYN_TIME(&syn_block->b_syn_linecont_time)); syn_block->b_syn_linecont_prog = regmatch.regprog; + + restore_chartab(buf_chartab); return r; } return FALSE; @@ -1617,8 +1637,9 @@ syn_current_attr ( lpos_T pos; int lc_col; reg_extmatch_T *cur_extmatch = NULL; - char_u *line; /* current line. NOTE: becomes invalid after - looking for a pattern match! */ + char_u buf_chartab[32]; // chartab array for syn iskeyword + char_u *line; // current line. NOTE: becomes invalid after + // looking for a pattern match! /* variables for zero-width matches that have a "nextgroup" argument */ int keep_next_list; @@ -1668,6 +1689,9 @@ syn_current_attr ( * avoid matching the same item in the same position twice. */ ga_init(&zero_width_next_ga, (int)sizeof(int), 10); + // use syntax iskeyword option + save_chartab(buf_chartab); + /* * Repeat matching keywords and patterns, to find contained items at the * same column. This stops when there are no extra matches at the current @@ -1992,6 +2016,8 @@ syn_current_attr ( } while (found_match); + restore_chartab(buf_chartab); + /* * Use attributes from the current state, if within its highlighting. * If not, use attributes from the current-but-one state, etc. @@ -2522,7 +2548,8 @@ find_endpos ( regmmatch_T best_regmatch; /* startpos/endpos of best match */ lpos_T pos; char_u *line; - int had_match = FALSE; + int had_match = false; + char_u buf_chartab[32]; // chartab array for syn option iskeyword /* just in case we are invoked for a keyword */ if (idx < 0) @@ -2562,9 +2589,13 @@ find_endpos ( unref_extmatch(re_extmatch_in); re_extmatch_in = ref_extmatch(start_ext); - matchcol = startpos->col; /* start looking for a match at sstart */ - start_idx = idx; /* remember the first END pattern. */ - best_regmatch.startpos[0].col = 0; /* avoid compiler warning */ + matchcol = startpos->col; // start looking for a match at sstart + start_idx = idx; // remember the first END pattern. + best_regmatch.startpos[0].col = 0; // avoid compiler warning + + // use syntax iskeyword option + save_chartab(buf_chartab); + for (;; ) { /* * Find end pattern that matches first after "matchcol". @@ -2707,6 +2738,8 @@ find_endpos ( if (!had_match) m_endpos->lnum = 0; + restore_chartab(buf_chartab); + /* Remove external matches. */ unref_extmatch(re_extmatch_in); re_extmatch_in = NULL; @@ -3027,6 +3060,46 @@ static void syn_cmd_spell(exarg_T *eap, int syncing) redraw_win_later(curwin, NOT_VALID); } +/// Handle ":syntax iskeyword" command. +static void syn_cmd_iskeyword(exarg_T *eap, int syncing) +{ + char_u *arg = eap->arg; + char_u save_chartab[32]; + char_u *save_isk; + + if (eap->skip) { + return; + } + + arg = skipwhite(arg); + if (*arg == NUL) { + MSG_PUTS("\n"); + MSG_PUTS(_("syntax iskeyword ")); + if (curwin->w_s->b_syn_isk != empty_option) { + msg_outtrans(curwin->w_s->b_syn_isk); + } else { + msg_outtrans((char_u *)"not set"); + } + } else { + if (STRNICMP(arg, "clear", 5) == 0) { + memmove(curwin->w_s->b_syn_chartab, curbuf->b_chartab, (size_t)32); + clear_string_option(&curwin->w_s->b_syn_isk); + } else { + memmove(save_chartab, curbuf->b_chartab, (size_t)32); + save_isk = curbuf->b_p_isk; + curbuf->b_p_isk = vim_strsave(arg); + + buf_init_chartab(curbuf, false); + memmove(curwin->w_s->b_syn_chartab, curbuf->b_chartab, (size_t)32); + memmove(curbuf->b_chartab, save_chartab, (size_t)32); + clear_string_option(&curwin->w_s->b_syn_isk); + curwin->w_s->b_syn_isk = curbuf->b_p_isk; + curbuf->b_p_isk = save_isk; + } + } + redraw_win_later(curwin, NOT_VALID); +} + /* * Clear all syntax info for one buffer. */ @@ -3065,6 +3138,7 @@ void syntax_clear(synblock_T *block) xfree(block->b_syn_linecont_pat); block->b_syn_linecont_pat = NULL; block->b_syn_folditems = 0; + clear_string_option(&block->b_syn_isk); /* free the stored states */ syn_stack_free_all(block); @@ -3107,6 +3181,7 @@ static void syntax_sync_clear(void) curwin->w_s->b_syn_linecont_prog = NULL; xfree(curwin->w_s->b_syn_linecont_pat); curwin->w_s->b_syn_linecont_pat = NULL; + clear_string_option(&curwin->w_s->b_syn_isk); syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ } @@ -3266,6 +3341,7 @@ static void syn_cmd_enable(exarg_T *eap, int syncing) /* * Handle ":syntax reset" command. + * It actually resets highlighting, not syntax. */ static void syn_cmd_reset(exarg_T *eap, int syncing) { @@ -5363,24 +5439,25 @@ struct subcommand { static struct subcommand subcommands[] = { - {"case", syn_cmd_case}, - {"clear", syn_cmd_clear}, - {"cluster", syn_cmd_cluster}, - {"conceal", syn_cmd_conceal}, - {"enable", syn_cmd_enable}, - {"include", syn_cmd_include}, - {"keyword", syn_cmd_keyword}, - {"list", syn_cmd_list}, - {"manual", syn_cmd_manual}, - {"match", syn_cmd_match}, - {"on", syn_cmd_on}, - {"off", syn_cmd_off}, - {"region", syn_cmd_region}, - {"reset", syn_cmd_reset}, - {"spell", syn_cmd_spell}, - {"sync", syn_cmd_sync}, - {"", syn_cmd_list}, - {NULL, NULL} + { "case", syn_cmd_case }, + { "clear", syn_cmd_clear }, + { "cluster", syn_cmd_cluster }, + { "conceal", syn_cmd_conceal }, + { "enable", syn_cmd_enable }, + { "include", syn_cmd_include }, + { "iskeyword", syn_cmd_iskeyword }, + { "keyword", syn_cmd_keyword }, + { "list", syn_cmd_list }, + { "manual", syn_cmd_manual }, + { "match", syn_cmd_match }, + { "on", syn_cmd_on }, + { "off", syn_cmd_off }, + { "region", syn_cmd_region }, + { "reset", syn_cmd_reset }, + { "spell", syn_cmd_spell }, + { "sync", syn_cmd_sync }, + { "", syn_cmd_list }, + { NULL, NULL } }; /* @@ -5434,6 +5511,7 @@ void ex_ownsyntax(exarg_T *eap) clear_string_option(&curwin->w_s->b_p_spc); clear_string_option(&curwin->w_s->b_p_spf); clear_string_option(&curwin->w_s->b_p_spl); + clear_string_option(&curwin->w_s->b_syn_isk); } /* save value of b:current_syntax */ @@ -6972,6 +7050,9 @@ set_hl_attr ( || at_en.rgb_sp_color != -1 || at_en.cterm_ae_attr != 0 || at_en.rgb_ae_attr != 0) { sgp->sg_attr = get_attr_entry(&at_en); + } else { + // If all the fields are cleared, clear the attr field back to default value + sgp->sg_attr = 0; } } diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 104cc47cda..df5e03880a 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -63,6 +63,7 @@ #include "nvim/map.h" #include "nvim/misc1.h" #include "nvim/move.h" +#include "nvim/main.h" #include "nvim/state.h" #include "nvim/ex_docmd.h" #include "nvim/ex_cmds.h" @@ -163,9 +164,9 @@ static VTermColor default_vt_bg_rgb; void terminal_init(void) { invalidated_terminals = pmap_new(ptr_t)(); - time_watcher_init(&loop, &refresh_timer, NULL); + time_watcher_init(&main_loop, &refresh_timer, NULL); // refresh_timer_cb will redraw the screen which can call vimscript - refresh_timer.events = queue_new_child(loop.events); + refresh_timer.events = queue_new_child(main_loop.events); // initialize a rgb->color index map for cterm attributes(VTermScreenCell // only has RGB information and we need color indexes for terminal UIs) @@ -452,7 +453,7 @@ static int terminal_execute(VimState *state, int key) case K_EVENT: // We cannot let an event free the terminal yet. It is still needed. s->term->refcount++; - queue_process_events(loop.events); + queue_process_events(main_loop.events); s->term->refcount--; if (s->term->buf_handle == 0) { s->close = true; diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 936add4e90..4b0b5e8d26 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -9,7 +9,6 @@ SCRIPTSOURCE := ../../../runtime SCRIPTS := \ test8.out \ - test10.out \ test12.out \ test13.out \ test14.out \ @@ -17,7 +16,6 @@ SCRIPTS := \ test24.out \ test30.out \ test32.out \ - test34.out \ test37.out \ test40.out \ test42.out \ @@ -26,13 +24,10 @@ SCRIPTS := \ test49.out \ test52.out \ test53.out \ - test55.out \ test64.out \ test69.out \ test73.out \ test79.out \ - test_listlbr.out \ - test_close_count.out \ test_marks.out \ # Tests using runtest.vim.vim. @@ -41,7 +36,11 @@ NEW_TESTS = \ test_cursor_func.res \ test_hardcopy.res \ test_help_tagjump.res \ + test_langmap.res \ test_menu.res \ + test_syntax.res \ + test_timers.res \ + test_unlet.res \ test_viml.res \ test_alot.res @@ -61,7 +60,7 @@ ifdef USE_VALGRIND TOOL := valgrind -q \ -q \ $(VALGRIND_TOOL) \ - --suppressions=../../../.valgrind.supp \ + --suppressions=../../.valgrind.supp \ --error-exitcode=123 \ --log-file=valgrind.\%p.$* \ $(VGDB) \ @@ -99,7 +98,7 @@ test1.out: $(VIMPROG) $(SCRIPTS) $(SCRIPTS_GUI): $(VIMPROG) test1.out RM_ON_RUN := test.out X* viminfo -RM_ON_START := tiny.vim small.vim mbyte.vim test.ok +RM_ON_START := test.ok RUN_VIM := VIMRUNTIME=$(SCRIPTSOURCE); export VIMRUNTIME; $(TOOL) $(VIMPROG) -u unix.vim -U NONE -i viminfo --noplugin -s dotest.in clean: diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim index 6601dcf52f..2712fb9371 100644 --- a/src/nvim/testdir/runtest.vim +++ b/src/nvim/testdir/runtest.vim @@ -20,9 +20,6 @@ " If cleanup after each Test_ function is needed, define a TearDown function. " It will be called after each Test_ function. -" Without the +eval feature we can't run these tests, bail out. -so small.vim - " Check that the screen size is at least 24 x 80 characters. if &lines < 24 || &columns < 80 let error = 'Screen size too small! Tests require at least 24 lines with 80 characters' @@ -68,7 +65,8 @@ function /^Test_ redir END let tests = split(substitute(@q, 'function \(\k*()\)', '\1', 'g')) -for test in tests +" Execute the tests in alphabetical order. +for test in sort(tests) if exists("*SetUp") call SetUp() endif diff --git a/src/nvim/testdir/test1.in b/src/nvim/testdir/test1.in index 85ff1b4db2..272500cd25 100644 --- a/src/nvim/testdir/test1.in +++ b/src/nvim/testdir/test1.in @@ -1,20 +1,5 @@ - First a simple test to check if the test script works. -If Vim was not compiled with the +eval feature, the small.vim script will be -set to copy the test.ok file to test.out, so that it looks like the test -succeeded. Otherwise an empty small.vim is written. small.vim is sourced by -tests that require the +eval feature or other features that are missing in the -small version. - -If Vim was not compiled with the +windows feature, the tiny.vim script will be -set like small.vim above. tiny.vim is sourced by tests that require the -+windows feature or other features that are missing in the tiny version. - -If Vim was not compiled with the +multi_byte feature, the mbyte.vim script will -be set like small.vim above. mbyte.vim is sourced by tests that require the -+multi_byte feature. - STARTTEST :" If columns or lines are too small, create wrongtermsize. :" (Some tests will fail. When columns and/or lines are small) @@ -23,25 +8,6 @@ STARTTEST :" Write a single line to test.out to check if testing works at all. :%d athis is a test:w! test.out -:" Create small.vim and tiny.vim empty, create mbyte.vim to skip the test. -0D:w! small.vim -:w! tiny.vim -ae! test.ok -w! test.out -qa! -:w! mbyte.vim -:" -:" If +multi_byte feature supported, make mbyte.vim empty. -:if has("multi_byte") | sp another | w! mbyte.vim | q | endif -:" -:" If +eval feature supported quit here, leaving tiny.vim and small.vim empty. -:" Otherwise write small.vim to skip the test. -:if 1 | q! | endif -:w! small.vim -:" If +windows feature not supported :sp will fail and tiny.vim will be -:" written to skip the test. -:sp another -:wq! tiny.vim :qa! ENDTEST diff --git a/src/nvim/testdir/test10.in b/src/nvim/testdir/test10.in deleted file mode 100644 index 769d690acb..0000000000 --- a/src/nvim/testdir/test10.in +++ /dev/null @@ -1,113 +0,0 @@ -Test for 'errorformat'. This will fail if the quickfix feature was disabled. - -STARTTEST -:so small.vim -:" Also test a BOM is ignored. -:so mbyte.vim -:7/start of errorfile/,/end of errorfile/w! Xerrorfile1 -:7/start of errorfile/,/end of errorfile/-1w! Xerrorfile2 -:/start of testfile/,/end of testfile/w! Xtestfile -:set efm+==%f=\\,\ line\ %l%*\\D%v%*[^\ ]\ %m -:set efm^=%AError\ in\ \"%f\"\ at\ line\ %l:,%Z%p^,%C%m -:cf Xerrorfile2 -:clast -:copen -:let a=w:quickfix_title -:wincmd p -lgR=a
-:cf Xerrorfile1 -grA -:cn -gRLINE 6, COL 19 -:cn -gRNO COLUMN SPECIFIED -:cn -gRAGAIN NO COLUMN -:cn -gRCOL 1 -:cn -gRCOL 2 -:cn -gRCOL 10 -:cn -gRVCOL 10 -:cn -grI -:cn -gR. SPACE POINTER -:cn -gR. DOT POINTER -:cn -gR. DASH POINTER -:cn -gR. TAB-SPACE POINTER -:clast -:cprev -:cprev -:wincmd w -:let a=w:quickfix_title -:wincmd p -lgR=a
-:w! test.out " Write contents of this file -:qa! -ENDTEST - -start of errorfile -"Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set. -"Xtestfile", line 6 col 19; this is an error -gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include version.c -Xtestfile:9: parse error before `asd' -make: *** [vim] Error 1 -in file "Xtestfile" linenr 10: there is an error - -2 returned -"Xtestfile", line 11 col 1; this is an error -"Xtestfile", line 12 col 2; this is another error -"Xtestfile", line 14:10; this is an error in column 10 -=Xtestfile=, line 15:10; this is another error, but in vcol 10 this time -"Xtestfile", linenr 16: yet another problem -Error in "Xtestfile" at line 17: -x should be a dot - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17 - ^ -Error in "Xtestfile" at line 18: -x should be a dot - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18 -.............^ -Error in "Xtestfile" at line 19: -x should be a dot - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19 ---------------^ -Error in "Xtestfile" at line 20: -x should be a dot - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20 - ^ - -Does anyone know what is the problem and how to correction it? -"Xtestfile", line 21 col 9: What is the title of the quickfix window? -"Xtestfile", line 22 col 9: What is the title of the quickfix window? -end of errorfile - -start of testfile - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 2 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 3 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 4 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 5 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 6 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 7 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 8 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 9 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 10 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 11 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 12 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 13 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 14 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 15 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 16 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 21 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 22 -end of testfile diff --git a/src/nvim/testdir/test10.ok b/src/nvim/testdir/test10.ok deleted file mode 100644 index 76a02f40b4..0000000000 --- a/src/nvim/testdir/test10.ok +++ /dev/null @@ -1,23 +0,0 @@ -start of testfile - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 2 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 3 - xxxxxxxxxxAxxxxxxxxxxxxxxxxxxx line 4 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 5 - xxxxxxxxxxxxxxxxxLINE 6, COL 19 line 6 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 7 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 8 - NO COLUMN SPECIFIEDxxxxxxxxxxx line 9 - AGAIN NO COLUMNxxxxxxxxxxxxxxx line 10 -COL 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 11 - COL 2xxxxxxxxxxxxxxxxxxxxxxxxx line 12 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 13 - xxxxxxxxCOL 10xxxxxxxxxxxxxxxx line 14 - xVCOL 10xxxxxxxxxxxxxxxxxxxxxx line 15 - Ixxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 16 - xxxx. SPACE POINTERxxxxxxxxxxx line 17 - xxxxx. DOT POINTERxxxxxxxxxxxx line 18 - xxxxxx. DASH POINTERxxxxxxxxxx line 19 - xxxxxxx. TAB-SPACE POINTERxxxx line 20 - xxxxxxxx:cf Xerrorfile1xxxxxxx line 21 - xxxxxxxx:cf Xerrorfile2xxxxxxx line 22 -end of testfile diff --git a/src/nvim/testdir/test10a.in b/src/nvim/testdir/test10a.in deleted file mode 100644 index 19e8652fe5..0000000000 --- a/src/nvim/testdir/test10a.in +++ /dev/null @@ -1,73 +0,0 @@ -Test for 'errorformat'. - -STARTTEST -:so small.vim -:/start of errorfile/,/end of errorfile/w! Xerrorfile -:/start of testfile/,/end of testfile/w! Xtestfile -:cf Xerrorfile -rA -:cn -rB -:cn -rC -:cn -rD -:cn -rE -:w! test.out " Write contents of this file -:qa! -ENDTEST - -start of errorfile - - printf(" %d \n", (number/other)%10 ); -..................^ -%CC-E-NOSEMI, Missing ";". -at line number 4 in file SYS$DISK:XTESTFILE - - other=10000000; -.............^ -%CC-E-UNDECLARED, In this statement, "oszt" is not declared. -at line number 7 in file SYS$DISK:XTESTFILE - - for (i = 0; i<7 ; i++ ){ -..................^ -%CC-E-UNDECLARED, In this statement, "i" is not declared. -at line number 16 in file SYS$DISK:XTESTFILE - -some other error somewhere here. -...........................^ -%CC-W-WARRING, Sorry, but no expalnation for such an warring. -at line number 19 in file SYS$DISK:XTESTFILE - -and finally some other error exactly here. -.....................................^ -%CC-I-INFORMATIONAL, It should be some informational message. -at line number 20 in file SYS$DISK:XTESTFILE - -Does anyone know what is the problem and how to correct ?? :) -end of errorfile - -start of testfile -01234567890123456789012345678901234567 -line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 4 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 8 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 12 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 13 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 14 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 15 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 16 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 17 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 18 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 19 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 20 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 22 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -end of testfile diff --git a/src/nvim/testdir/test10a.ok b/src/nvim/testdir/test10a.ok deleted file mode 100644 index 10e78c9239..0000000000 --- a/src/nvim/testdir/test10a.ok +++ /dev/null @@ -1,23 +0,0 @@ -start of testfile -01234567890123456789012345678901234567 -line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 4 xxxxxxxxxxAxxxxxxxxxxxxxxxxxxx -line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 7 xxxxxBxxxxxxxxxxxxxxxxxxxxxxxx -line 8 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 12 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 13 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 14 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 15 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 16 xxxxxxxxxxCxxxxxxxxxxxxxxxxxxx -line 17 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 18 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 19 xxxxxxxxxxxxxxxxxxxDxxxxxxxxxx -line 20 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxE -line 21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 22 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -end of testfile diff --git a/src/nvim/testdir/test12.in b/src/nvim/testdir/test12.in index be3169a625..0c0623e5d4 100644 --- a/src/nvim/testdir/test12.in +++ b/src/nvim/testdir/test12.in @@ -4,7 +4,6 @@ Tests for 'directory' option. - "dir", in directory relative to current dir STARTTEST -:so small.vim :set dir=.,~ :/start of testfile/,/end of testfile/w! Xtest1 :" do an ls of the current dir to find the swap file (should not be there) diff --git a/src/nvim/testdir/test13.in b/src/nvim/testdir/test13.in index 6713f80e88..fa9ba312b7 100644 --- a/src/nvim/testdir/test13.in +++ b/src/nvim/testdir/test13.in @@ -11,7 +11,6 @@ Also test changing buffers in a BufDel autocommand. If this goes wrong there are ml_line errors and/or a Crash. STARTTEST -:so small.vim :/^start of testfile/,/^end of testfile/w! Xtestje1 :/^start of testfile/,/^end of testfile/w! Xtestje2 :/^start of testfile/,/^end of testfile/w! Xtestje3 diff --git a/src/nvim/testdir/test14.in b/src/nvim/testdir/test14.in index 6ebec99af6..bef2e45431 100644 --- a/src/nvim/testdir/test14.in +++ b/src/nvim/testdir/test14.in @@ -5,7 +5,6 @@ Also test "[m", "]m", "[M" and "]M" Also test search() STARTTEST -:so small.vim /Start cursor here vaBiBD:?Bug?,/Piece/-2w! test.out /^- Bug diff --git a/src/nvim/testdir/test17.in b/src/nvim/testdir/test17.in index a8c81b832d..83abe17770 100644 --- a/src/nvim/testdir/test17.in +++ b/src/nvim/testdir/test17.in @@ -3,7 +3,6 @@ Tests for: - ":checkpath!" with various 'include' settings. STARTTEST -:so small.vim :set isfname=@,48-57,/,.,-,_,+,,,$,:,~,{,} :function! DeleteDirectory(dir) : if has("win16") || has("win32") || has("win64") || has("dos16") || has("dos32") diff --git a/src/nvim/testdir/test30.in b/src/nvim/testdir/test30.in index 2a89eac73d..56d5d5c6c2 100644 --- a/src/nvim/testdir/test30.in +++ b/src/nvim/testdir/test30.in @@ -3,7 +3,6 @@ Test for a lot of variations of the 'fileformats' option Note: This test will fail if "cat" is not available. STARTTEST -:so small.vim :" first write three test files, one in each format :set fileformat=unix :set fileformats= diff --git a/src/nvim/testdir/test32.in b/src/nvim/testdir/test32.in index 1a73c862d1..76bd9be889 100644 --- a/src/nvim/testdir/test32.in +++ b/src/nvim/testdir/test32.in @@ -21,7 +21,6 @@ Test for insert expansion * t-expansion STARTTEST -:so small.vim :se backspace="" :se cpt=.,w ff=unix | $-2,$w!Xtestfile | set ff& :se cot= diff --git a/src/nvim/testdir/test34.in b/src/nvim/testdir/test34.in deleted file mode 100644 index 71ee5f63b2..0000000000 --- a/src/nvim/testdir/test34.in +++ /dev/null @@ -1,87 +0,0 @@ -Test for user functions. -Also test an <expr> mapping calling a function. -Also test that a builtin function cannot be replaced. -Also test for regression when calling arbitrary expression. - -STARTTEST -:so small.vim -:function Table(title, ...) -: let ret = a:title -: let idx = 1 -: while idx <= a:0 -: exe "let ret = ret . a:" . idx -: let idx = idx + 1 -: endwhile -: return ret -:endfunction -:function Compute(n1, n2, divname) -: if a:n2 == 0 -: return "fail" -: endif -: exe "let g:" . a:divname . " = ". a:n1 / a:n2 -: return "ok" -:endfunction -:func Expr1() -: normal! v -: return "111" -:endfunc -:func Expr2() -: call search('XX', 'b') -: return "222" -:endfunc -:func ListItem() -: let g:counter += 1 -: return g:counter . '. ' -:endfunc -:func ListReset() -: let g:counter = 0 -: return '' -:endfunc -:func FuncWithRef(a) -: unlet g:FuncRef -: return a:a -:endfunc -:let g:FuncRef=function("FuncWithRef") -:let counter = 0 -:inoremap <expr> ( ListItem() -:inoremap <expr> [ ListReset() -:imap <expr> + Expr1() -:imap <expr> * Expr2() -:let retval = "nop" -/^here -C=Table("xxx", 4, "asdf") - =Compute(45, 0, "retval") - =retval - =Compute(45, 5, "retval") - =retval - =g:FuncRef(333) - -XX+-XX ----*--- -(one -(two -[(one again:call append(line('$'), max([1, 2, 3])) -:call extend(g:, {'max': function('min')}) -:call append(line('$'), max([1, 2, 3])) -:try -: " Regression: the first line below used to throw ?E110: Missing ')'? -: " Second is here just to prove that this line is correct when not skipping -: " rhs of &&. -: $put =(0&&(function('tr'))(1, 2, 3)) -: $put =(1&&(function('tr'))(1, 2, 3)) -:catch -: $put ='!!! Unexpected exception:' -: $put =v:exception -:endtry -:$-9,$w! test.out -:delfunc Table -:delfunc Compute -:delfunc Expr1 -:delfunc Expr2 -:delfunc ListItem -:delfunc ListReset -:unlet retval counter -:q! -ENDTEST - -here diff --git a/src/nvim/testdir/test34.ok b/src/nvim/testdir/test34.ok deleted file mode 100644 index 97995de80e..0000000000 --- a/src/nvim/testdir/test34.ok +++ /dev/null @@ -1,10 +0,0 @@ -xxx4asdf fail nop ok 9 333 -XX111-XX ----222--- -1. one -2. two -1. one again -3 -3 -0 -1 diff --git a/src/nvim/testdir/test37.in b/src/nvim/testdir/test37.in index 8ca1125793..156bf74a10 100644 --- a/src/nvim/testdir/test37.in +++ b/src/nvim/testdir/test37.in @@ -1,6 +1,6 @@ Test for 'scrollbind'. <eralston@computer.org> Do not add a line below! STARTTEST -:so small.vim +: :set noscrollbind :set scrollopt=ver,jump :set scrolloff=2 diff --git a/src/nvim/testdir/test40.in b/src/nvim/testdir/test40.in index ced4572fb8..b0285709e5 100644 --- a/src/nvim/testdir/test40.in +++ b/src/nvim/testdir/test40.in @@ -1,7 +1,6 @@ Test for "*Cmd" autocommands STARTTEST -:so small.vim :set wildchar=^E :/^start/,$w! Xxx " write lines below to Xxx :au BufReadCmd XtestA 0r Xxx|$del diff --git a/src/nvim/testdir/test42.in b/src/nvim/testdir/test42.in Binary files differindex c35569a76c..0ea0198d12 100644 --- a/src/nvim/testdir/test42.in +++ b/src/nvim/testdir/test42.in diff --git a/src/nvim/testdir/test47.in b/src/nvim/testdir/test47.in index f15eaf0f8f..c95c6a6850 100644 --- a/src/nvim/testdir/test47.in +++ b/src/nvim/testdir/test47.in @@ -3,7 +3,6 @@ Tests for vertical splits and filler lines in diff mode Also tests restoration of saved options by :diffoff. STARTTEST -:so small.vim :" Disable the title to avoid xterm keeping the wrong one. :set notitle noicon /^1 diff --git a/src/nvim/testdir/test48.in b/src/nvim/testdir/test48.in index 998e1bba00..1df5a3c46a 100644 --- a/src/nvim/testdir/test48.in +++ b/src/nvim/testdir/test48.in @@ -1,7 +1,6 @@ This is a test of 'virtualedit'. STARTTEST -:so small.vim :set noswf :set ve=all j-dgg diff --git a/src/nvim/testdir/test49.in b/src/nvim/testdir/test49.in index d95052e14c..435e62765b 100644 --- a/src/nvim/testdir/test49.in +++ b/src/nvim/testdir/test49.in @@ -4,7 +4,6 @@ If after adding a new test, the test output doesn't appear properly in test49.failed, try to add one or more "G"s at the line ending in "test.out" STARTTEST -:so small.vim :se nomore :lang mess C :so test49.vim diff --git a/src/nvim/testdir/test50.in b/src/nvim/testdir/test50.in index 0cbf4bf6d6..392177b808 100644 --- a/src/nvim/testdir/test50.in +++ b/src/nvim/testdir/test50.in @@ -2,7 +2,6 @@ Test for shortpathname ':8' extension. Only for use on Win32 systems! STARTTEST -:so small.vim :fun! TestIt(file, bits, expected) let res=fnamemodify(a:file,a:bits) if a:expected == '' diff --git a/src/nvim/testdir/test52.in b/src/nvim/testdir/test52.in index 206b65a1f9..fa75129193 100644 --- a/src/nvim/testdir/test52.in +++ b/src/nvim/testdir/test52.in @@ -1,7 +1,6 @@ Tests for reading and writing files with conversion for Win32. STARTTEST -:so mbyte.vim :" make this a dummy test for non-Win32 systems :if !has("win32") | e! test.ok | wq! test.out | endif :" diff --git a/src/nvim/testdir/test53.in b/src/nvim/testdir/test53.in index 7c35b2e853..f3778c5192 100644 --- a/src/nvim/testdir/test53.in +++ b/src/nvim/testdir/test53.in @@ -7,7 +7,6 @@ Also test match() and matchstr() Also test the gn command and repeating it. STARTTEST -:so small.vim /^start:/ da" 0va'a'rx diff --git a/src/nvim/testdir/test55.in b/src/nvim/testdir/test55.in deleted file mode 100644 index 9e3c1168cc..0000000000 --- a/src/nvim/testdir/test55.in +++ /dev/null @@ -1,601 +0,0 @@ -Tests for List and Dictionary types. vim: set ft=vim : - -STARTTEST -:so small.vim -:fun Test(...) -:lang C -:" Creating List directly with different types -:let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] -:$put =string(l) -:$put =string(l[-1]) -:$put =string(l[-4]) -:try -: $put =string(l[-5]) -:catch -: $put =v:exception[:14] -:endtry -:" List slices -:$put =string(l[:]) -:$put =string(l[1:]) -:$put =string(l[:-2]) -:$put =string(l[0:8]) -:$put =string(l[8:-1]) -:" -:" List identity -:let ll = l -:let lx = copy(l) -:try -: $put =(l == ll) . (l isnot ll) . (l is ll) . (l == lx) . (l is lx) . (l isnot lx) -:catch -: $put =v:exception -:endtry -:" -:" Creating Dictionary directly with different types -:let d = {001: 'asd', 'b': [1, 2, function('strlen')], -1: {'a': 1},} -:$put =string(d) . d.1 -:$put =string(sort(keys(d))) -:$put =string (values(d)) -:for [key, val] in items(d) -: $put =key . ':' . string(val) -: unlet key val -:endfor -:call extend (d, {3:33, 1:99}) -:call extend(d, {'b':'bbb', 'c':'ccc'}, "keep") -:try -: call extend(d, {3:333,4:444}, "error") -:catch -: $put =v:exception[:15] . v:exception[-1:-1] -:endtry -:$put =string(d) -:call filter(d, 'v:key =~ ''[ac391]''') -:$put =string(d) -:" -:" Dictionary identity -:let dd = d -:let dx = copy(d) -:try -: $put =(d == dd) . (d isnot dd) . (d is dd) . (d == dx) . (d is dx) . (d isnot dx) -:catch -: $put =v:exception -:endtry -:" -:" Changing var type should fail -:try -: let d = [] -:catch -: $put =v:exception[:14] . v:exception[-1:-1] -:endtry -:try -: let l = {} -:catch -: $put =v:exception[:14] . v:exception[-1:-1] -:endtry -:" -:" removing items with :unlet -:unlet l[2] -:$put =string(l) -:let l = range(8) -:try -:unlet l[:3] -:unlet l[1:] -:catch -:$put =v:exception -:endtry -:$put =string(l) -:" -:unlet d.c -:unlet d[-1] -:$put =string(d) -:" -:" removing items out of range: silently skip items that don't exist -let l = [0, 1, 2, 3] -:unlet l[2:1] -:$put =string(l) -let l = [0, 1, 2, 3] -:unlet l[2:2] -:$put =string(l) -let l = [0, 1, 2, 3] -:unlet l[2:3] -:$put =string(l) -let l = [0, 1, 2, 3] -:unlet l[2:4] -:$put =string(l) -let l = [0, 1, 2, 3] -:unlet l[2:5] -:$put =string(l) -let l = [0, 1, 2, 3] -:unlet l[-1:2] -:$put =string(l) -let l = [0, 1, 2, 3] -:unlet l[-2:2] -:$put =string(l) -let l = [0, 1, 2, 3] -:unlet l[-3:2] -:$put =string(l) -let l = [0, 1, 2, 3] -:unlet l[-4:2] -:$put =string(l) -let l = [0, 1, 2, 3] -:unlet l[-5:2] -:$put =string(l) -let l = [0, 1, 2, 3] -:unlet l[-6:2] -:$put =string(l) -:" -:" assignment to a list -:let l = [0, 1, 2, 3] -:let [va, vb] = l[2:3] -:$put =va -:$put =vb -:try -: let [va, vb] = l -:catch -: $put =v:exception[:14] -:endtry -:try -: let [va, vb] = l[1:1] -:catch -: $put =v:exception[:14] -:endtry -:" -:" manipulating a big Dictionary (hashtable.c has a border of 1000 entries) -:let d = {} -:for i in range(1500) -: let d[i] = 3000 - i -:endfor -:$put =d[0] . ' ' . d[100] . ' ' . d[999] . ' ' . d[1400] . ' ' . d[1499] -:try -: let n = d[1500] -:catch -: $put =substitute(v:exception, '\v(.{14}).*( \d{4}).*', '\1\2', '') -:endtry -:" lookup each items -:for i in range(1500) -: if d[i] != 3000 - i -: $put =d[i] -: endif -:endfor -: let i += 1 -:" delete even items -:while i >= 2 -: let i -= 2 -: unlet d[i] -:endwhile -:$put =get(d, 1500 - 100, 'NONE') . ' ' . d[1] -:" delete odd items, checking value, one intentionally wrong -:let d[33] = 999 -:let i = 1 -:while i < 1500 -: if d[i] != 3000 - i -: $put =i . '=' . d[i] -: else -: unlet d[i] -: endif -: let i += 2 -:endwhile -:$put =string(d) " must be almost empty now -:unlet d -:" -:" Dictionary function -:let dict = {} -:func dict.func(a) dict -: $put =a:a . len(self.data) -:endfunc -:let dict.data = [1,2,3] -:call dict.func("len: ") -:let x = dict.func("again: ") -:try -: let Fn = dict.func -: call Fn('xxx') -:catch -: $put =v:exception[:15] -:endtry -:" -:" Function in script-local List or Dict -:let g:dict = {} -:function g:dict.func() dict -: $put ='g:dict.func'.self.foo[1].self.foo[0]('asdf') -:endfunc -:let g:dict.foo = ['-', 2, 3] -:call insert(g:dict.foo, function('strlen')) -:call g:dict.func() -:" -:" Nasty: remove func from Dict that's being called (works) -:let d = {1:1} -:func d.func(a) -: return "a:". a:a -:endfunc -:$put =d.func(string(remove(d, 'func'))) -:" -:" Nasty: deepcopy() dict that refers to itself (fails when noref used) -:let d = {1:1, 2:2} -:let l = [4, d, 6] -:let d[3] = l -:let dc = deepcopy(d) -:try -: let dc = deepcopy(d, 1) -:catch -: $put =v:exception[:14] -:endtry -:let l2 = [0, l, l, 3] -:let l[1] = l2 -:let l3 = deepcopy(l2) -:$put ='same list: ' . (l3[1] is l3[2]) -:" -:" Locked variables -:for depth in range(5) -: $put ='depth is ' . depth -: for u in range(3) -: unlet l -: let l = [0, [1, [2, 3]], {4: 5, 6: {7: 8}}] -: exe "lockvar " . depth . " l" -: if u == 1 -: exe "unlockvar l" -: elseif u == 2 -: exe "unlockvar " . depth . " l" -: endif -: let ps = islocked("l").islocked("l[1]").islocked("l[1][1]").islocked("l[1][1][0]").'-'.islocked("l[2]").islocked("l[2]['6']").islocked("l[2]['6'][7]") -: $put =ps -: let ps = '' -: try -: let l[1][1][0] = 99 -: let ps .= 'p' -: catch -: let ps .= 'F' -: endtry -: try -: let l[1][1] = [99] -: let ps .= 'p' -: catch -: let ps .= 'F' -: endtry -: try -: let l[1] = [99] -: let ps .= 'p' -: catch -: let ps .= 'F' -: endtry -: try -: let l[2]['6'][7] = 99 -: let ps .= 'p' -: catch -: let ps .= 'F' -: endtry -: try -: let l[2][6] = {99: 99} -: let ps .= 'p' -: catch -: let ps .= 'F' -: endtry -: try -: let l[2] = {99: 99} -: let ps .= 'p' -: catch -: let ps .= 'F' -: endtry -: try -: let l = [99] -: let ps .= 'p' -: catch -: let ps .= 'F' -: endtry -: $put =ps -: endfor -:endfor -:" -:" Unletting locked variables -:$put ='Unletting:' -:for depth in range(5) -: $put ='depth is ' . depth -: for u in range(3) -: unlet l -: let l = [0, [1, [2, 3]], {4: 5, 6: {7: 8}}] -: exe "lockvar " . depth . " l" -: if u == 1 -: exe "unlockvar l" -: elseif u == 2 -: exe "unlockvar " . depth . " l" -: endif -: let ps = islocked("l").islocked("l[1]").islocked("l[1][1]").islocked("l[1][1][0]").'-'.islocked("l[2]").islocked("l[2]['6']").islocked("l[2]['6'][7]") -: $put =ps -: let ps = '' -: try -: unlet l[2]['6'][7] -: let ps .= 'p' -: catch -: let ps .= 'F' -: endtry -: try -: unlet l[2][6] -: let ps .= 'p' -: catch -: let ps .= 'F' -: endtry -: try -: unlet l[2] -: let ps .= 'p' -: catch -: let ps .= 'F' -: endtry -: try -: unlet l[1][1][0] -: let ps .= 'p' -: catch -: let ps .= 'F' -: endtry -: try -: unlet l[1][1] -: let ps .= 'p' -: catch -: let ps .= 'F' -: endtry -: try -: unlet l[1] -: let ps .= 'p' -: catch -: let ps .= 'F' -: endtry -: try -: unlet l -: let ps .= 'p' -: catch -: let ps .= 'F' -: endtry -: $put =ps -: endfor -:endfor -:" -:" Locked variables and :unlet or list / dict functions -:$put ='Locks and commands or functions:' -:" -:$put ='No :unlet after lock on dict:' -:unlet! d -:let d = {'a': 99, 'b': 100} -:lockvar 1 d -:try -: unlet d.a -: $put ='did :unlet' -:catch -: $put =v:exception[:16] -:endtry -:$put =string(d) -:" -:$put =':unlet after lock on dict item:' -:unlet! d -:let d = {'a': 99, 'b': 100} -:lockvar d.a -:try -: unlet d.a -: $put ='did :unlet' -:catch -: $put =v:exception[:16] -:endtry -:$put =string(d) -:" -:$put ='filter() after lock on dict item:' -:unlet! d -:let d = {'a': 99, 'b': 100} -:lockvar d.a -:try -: call filter(d, 'v:key != "a"') -: $put ='did filter()' -:catch -: $put =v:exception[:16] -:endtry -:$put =string(d) -:" -:$put ='map() after lock on dict:' -:unlet! d -:let d = {'a': 99, 'b': 100} -:lockvar 1 d -:try -: call map(d, 'v:val + 200') -: $put ='did map()' -:catch -: $put =v:exception[:16] -:endtry -:$put =string(d) -:" -:$put ='No extend() after lock on dict item:' -:unlet! d -:let d = {'a': 99, 'b': 100} -:lockvar d.a -:try -: $put =string(extend(d, {'a': 123})) -: $put ='did extend()' -:catch -: $put =v:exception[:14] -:endtry -:$put =string(d) -:" -:$put ='No remove() of write-protected scope-level variable:' -:fun! Tfunc(this_is_a_loooooooooong_parameter_name) -: try -: $put =string(remove(a:, 'this_is_a_loooooooooong_parameter_name')) -: $put ='did remove()' -: catch -: $put =v:exception[:14] -: endtry -:endfun -:call Tfunc('testval') -:" -:$put ='No extend() of write-protected scope-level variable:' -:fun! Tfunc(this_is_a_loooooooooong_parameter_name) -: try -: $put =string(extend(a:, {'this_is_a_loooooooooong_parameter_name': 1234})) -: $put ='did extend()' -: catch -: $put =v:exception[:14] -: endtry -:endfun -:call Tfunc('testval') -:" -:$put ='No :unlet of variable in locked scope:' -:let b:testvar = 123 -:lockvar 1 b: -:try -: unlet b:testvar -: $put ='b:testvar was :unlet: '. (!exists('b:testvar')) -:catch -: $put =v:exception[:16] -:endtry -:unlockvar 1 b: -:unlet! b:testvar -:" -:$put ='No :let += of locked list variable:' -:let l = ['a', 'b', 3] -:lockvar 1 l -:try -: let l += ['x'] -: $put ='did :let +=' -:catch -: $put =v:exception[:14] -:endtry -:$put =string(l) -:" -:unlet l -:let l = [1, 2, 3, 4] -:lockvar! l -:$put =string(l) -:unlockvar l[1] -:unlet l[0:1] -:$put =string(l) -:unlet l[1:2] -:$put =string(l) -:unlockvar l[1] -:let l[0:1] = [0, 1] -:$put =string(l) -:let l[1:2] = [0, 1] -:$put =string(l) -:unlet l -:" :lockvar/islocked() triggering script autoloading -:set rtp+=./sautest -:lockvar g:footest#x -:unlockvar g:footest#x -:$put ='locked g:footest#x:'.islocked('g:footest#x') -:$put ='exists g:footest#x:'.exists('g:footest#x') -:$put ='g:footest#x: '.g:footest#x -:" -:" a:000 function argument -:" first the tests that should fail -:try -: let a:000 = [1, 2] -:catch -: $put ='caught a:000' -:endtry -:try -: let a:000[0] = 9 -:catch -: $put ='caught a:000[0]' -:endtry -:try -: let a:000[2] = [9, 10] -:catch -: $put ='caught a:000[2]' -:endtry -:try -: let a:000[3] = {9: 10} -:catch -: $put ='caught a:000[3]' -:endtry -:" now the tests that should pass -:try -: let a:000[2][1] = 9 -: call extend(a:000[2], [5, 6]) -: let a:000[3][5] = 8 -: let a:000[3]['a'] = 12 -: $put =string(a:000) -:catch -: $put ='caught ' . v:exception -:endtry -:" -:" reverse(), sort(), uniq() -:let l = ['-0', 'A11', 2, 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5] -:$put =string(uniq(copy(l))) -:$put =string(reverse(l)) -:$put =string(reverse(reverse(l))) -:$put =string(sort(l)) -:$put =string(reverse(sort(l))) -:$put =string(sort(reverse(sort(l)))) -:$put =string(uniq(sort(l))) -:let l=[7, 9, 'one', 18, 12, 22, 'two', 10.0e-16, -1, 'three', 0xff, 0.22, 'four'] -:$put =string(sort(copy(l), 'n')) -:let l=[7, 9, 18, 12, 22, 10.0e-16, -1, 0xff, 0, -0, 0.22, 'bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', {}, []] -:$put =string(sort(copy(l), 1)) -:$put =string(sort(copy(l), 'i')) -:$put =string(sort(copy(l))) -:" -:" splitting a string to a List -:$put =string(split(' aa bb ')) -:$put =string(split(' aa bb ', '\W\+', 0)) -:$put =string(split(' aa bb ', '\W\+', 1)) -:$put =string(split(' aa bb ', '\W', 1)) -:$put =string(split(':aa::bb:', ':', 0)) -:$put =string(split(':aa::bb:', ':', 1)) -:$put =string(split('aa,,bb, cc,', ',\s*', 1)) -:$put =string(split('abc', '\zs')) -:$put =string(split('abc', '\zs', 1)) -:" -:" compare recursively linked list and dict -:let l = [1, 2, 3, 4] -:let d = {'1': 1, '2': l, '3': 3} -:let l[1] = d -:$put =(l == l) -:$put =(d == d) -:$put =(l != deepcopy(l)) -:$put =(d != deepcopy(d)) -:" -:" compare complex recursively linked list and dict -:let l = [] -:call add(l, l) -:let dict4 = {"l": l} -:call add(dict4.l, dict4) -:let lcopy = deepcopy(l) -:let dict4copy = deepcopy(dict4) -:$put =(l == lcopy) -:$put =(dict4 == dict4copy) -:" -:" Pass the same List to extend() -:let l = [1, 2, 3, 4, 5] -:call extend(l, l) -:$put =string(l) -:" -:" Pass the same Dict to extend() -:let d = { 'a': {'b': 'B'}} -:call extend(d, d) -:$put =string(d) -:" -:" Pass the same Dict to extend() with "error" -:try -: call extend(d, d, "error") -:catch -: $put =v:exception[:15] . v:exception[-1:-1] -:endtry -:$put =string(d) -:" -:" test for range assign -:let l = [0] -:let l[:] = [1, 2] -:$put =string(l) -:endfun -:" -:call Test(1, 2, [3, 4], {5: 6}) " This may take a while -:" -:delfunc Test -:unlet dict -:call garbagecollect(1) -:" -:" test for patch 7.3.637 -:let a = 'No error caught' -:try|foldopen|catch|let a = matchstr(v:exception,'^[^ ]*')|endtry -o=a
:" -:lang C -:redir => a -:try|foobar|catch|let a = matchstr(v:exception,'^[^ ]*')|endtry -:redir END -o=a
:" -:" -:/^start:/,$wq! test.out -ENDTEST - -start: diff --git a/src/nvim/testdir/test55.ok b/src/nvim/testdir/test55.ok deleted file mode 100644 index 607a95ead9..0000000000 --- a/src/nvim/testdir/test55.ok +++ /dev/null @@ -1,199 +0,0 @@ -start: -[1, 'as''d', [1, 2, function('strlen')], {'a': 1}] -{'a': 1} -1 -Vim(put):E684: -[1, 'as''d', [1, 2, function('strlen')], {'a': 1}] -['as''d', [1, 2, function('strlen')], {'a': 1}] -[1, 'as''d', [1, 2, function('strlen')]] -[1, 'as''d', [1, 2, function('strlen')], {'a': 1}] -[] -101101 -{'1': 'asd', 'b': [1, 2, function('strlen')], '-1': {'a': 1}}asd -['-1', '1', 'b'] -['asd', [1, 2, function('strlen')], {'a': 1}] -1:'asd' -b:[1, 2, function('strlen')] --1:{'a': 1} -Vim(call):E737: 3 -{'c': 'ccc', '1': 99, 'b': [1, 2, function('strlen')], '3': 33, '-1': {'a': 1}} -{'c': 'ccc', '1': 99, '3': 33, '-1': {'a': 1}} -101101 -Vim(let):E706: d -Vim(let):E706: l -[1, 'as''d', {'a': 1}] -[4] -{'1': 99, '3': 33} -[0, 1, 2, 3] -[0, 1, 3] -[0, 1] -[0, 1] -[0, 1] -[0, 1, 2, 3] -[0, 1, 3] -[0, 3] -[3] -[3] -[3] -2 -3 -Vim(let):E687: -Vim(let):E688: -3000 2900 2001 1600 1501 -Vim(let):E716: 1500 -NONE 2999 -33=999 -{'33': 999} -len: 3 -again: 3 -Vim(call):E725: -g:dict.func-4 -a:function('3') -Vim(let):E698: -same list: 1 -depth is 0 -0000-000 -ppppppp -0000-000 -ppppppp -0000-000 -ppppppp -depth is 1 -1000-000 -ppppppF -0000-000 -ppppppp -0000-000 -ppppppp -depth is 2 -1100-100 -ppFppFF -0000-000 -ppppppp -0000-000 -ppppppp -depth is 3 -1110-110 -pFFpFFF -0010-010 -pFppFpp -0000-000 -ppppppp -depth is 4 -1111-111 -FFFFFFF -0011-011 -FFpFFpp -0000-000 -ppppppp -Unletting: -depth is 0 -0000-000 -ppppppp -0000-000 -ppppppp -0000-000 -ppppppp -depth is 1 -1000-000 -ppFppFp -0000-000 -ppppppp -0000-000 -ppppppp -depth is 2 -1100-100 -pFFpFFp -0000-000 -ppppppp -0000-000 -ppppppp -depth is 3 -1110-110 -FFFFFFp -0010-010 -FppFppp -0000-000 -ppppppp -depth is 4 -1111-111 -FFFFFFp -0011-011 -FppFppp -0000-000 -ppppppp -Locks and commands or functions: -No :unlet after lock on dict: -Vim(unlet):E741: -{'a': 99, 'b': 100} -:unlet after lock on dict item: -did :unlet -{'b': 100} -filter() after lock on dict item: -did filter() -{'b': 100} -map() after lock on dict: -did map() -{'a': 299, 'b': 300} -No extend() after lock on dict item: -Vim(put):E741: -{'a': 99, 'b': 100} -No remove() of write-protected scope-level variable: -Vim(put):E795: -No extend() of write-protected scope-level variable: -Vim(put):E742: -No :unlet of variable in locked scope: -Vim(unlet):E741: -No :let += of locked list variable: -Vim(let):E741: -['a', 'b', 3] -[1, 2, 3, 4] -[1, 2, 3, 4] -[1, 2, 3, 4] -[1, 2, 3, 4] -[1, 2, 3, 4] -locked g:footest#x:-1 -exists g:footest#x:0 -g:footest#x: 1 -caught a:000 -caught a:000[0] -caught a:000[2] -caught a:000[3] -[1, 2, [3, 9, 5, 6], {'a': 12, '5': 8}] -['-0', 'A11', 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5] -[1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'] -[1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'] -['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]] -[[0, 1, 2], [0, 1, 2], 4, 2, 2, 1.5, 'xaaa', 'x8', 'foo6', 'foo', 'foo', 'A11', '-0'] -['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]] -['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 4, [0, 1, 2]] -[-1, 'one', 'two', 'three', 'four', 1.0e-15, 0.22, 7, 9, 12, 18, 22, 255] -['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}] -['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}] -['BAR', 'Bar', 'FOO', 'FOOBAR', 'Foo', 'bar', 'foo', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}] -['aa', 'bb'] -['aa', 'bb'] -['', 'aa', 'bb', ''] -['', '', 'aa', '', 'bb', '', ''] -['aa', '', 'bb'] -['', 'aa', '', 'bb', ''] -['aa', '', 'bb', 'cc', ''] -['a', 'b', 'c'] -['', 'a', '', 'b', '', 'c', ''] -1 -1 -0 -0 -1 -1 -[1, 2, 3, 4, 5, 1, 2, 3, 4, 5] -{'a': {'b': 'B'}} -Vim(call):E737: a -{'a': {'b': 'B'}} -[1, 2] -Vim(foldopen):E490: - - -Error detected while processing : -E492: Not an editor command: foobar|catch|let a = matchstr(v:exception,'^[^ ]*')|endtry - diff --git a/src/nvim/testdir/test64.in b/src/nvim/testdir/test64.in index fd19d3af32..c4585ecbce 100644 --- a/src/nvim/testdir/test64.in +++ b/src/nvim/testdir/test64.in @@ -5,7 +5,6 @@ A pattern that gives the expected result produces OK, so that we know it was actually tried. STARTTEST -:so small.vim :" tl is a List of Lists with: :" regexp engine :" regexp pattern diff --git a/src/nvim/testdir/test69.in b/src/nvim/testdir/test69.in index f583947dfb..39b360fc81 100644 --- a/src/nvim/testdir/test69.in +++ b/src/nvim/testdir/test69.in @@ -4,7 +4,7 @@ And test "ra" on multi-byte characters. Also test byteidx() and byteidxcomp() STARTTEST -:so mbyte.vim +: ENDTEST Results of test69: diff --git a/src/nvim/testdir/test73.in b/src/nvim/testdir/test73.in index c525e51d28..7d6c7287a5 100644 --- a/src/nvim/testdir/test73.in +++ b/src/nvim/testdir/test73.in @@ -1,7 +1,6 @@ Tests for find completion. STARTTEST -:so small.vim :set wildmode=full :" Do all test in a separate window to avoid E211 when we recursively :" delete the Xfind directory during cleanup diff --git a/src/nvim/testdir/test8.in b/src/nvim/testdir/test8.in index 41e6262e92..a5e6034782 100644 --- a/src/nvim/testdir/test8.in +++ b/src/nvim/testdir/test8.in @@ -2,7 +2,6 @@ Test for BufWritePre autocommand that deletes or unloads the buffer. Test for BufUnload autocommand that unloads all other buffers. STARTTEST -:so small.vim :au BufWritePre Xxx1 bunload :au BufWritePre Xxx2 bwipe /^start of @@ -35,8 +34,6 @@ endfunc :set shada='100 :au BufUnload * call CloseAll() :au VimLeave * call WriteToOut() -:e small.vim -:sp mbyte.vim :q :qa! ENDTEST diff --git a/src/nvim/testdir/test_close_count.in b/src/nvim/testdir/test_close_count.in deleted file mode 100644 index 58dfb425ce..0000000000 --- a/src/nvim/testdir/test_close_count.in +++ /dev/null @@ -1,156 +0,0 @@ -Tests for :[count]close! and :[count]hide vim: set ft=vim : - -STARTTEST -:let tests = [] -:so tiny.vim -:for i in range(5) -:new -:endfor -:4wincmd w -:close! -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:1close! -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:$close! -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:1wincmd w -:2close! -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:1wincmd w -:new -:new -:2wincmd w -:-1close! -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:2wincmd w -:+1close! -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:e! test.out -:call append(0, map(copy(tests), 'join(v:val, " ")')) -:w -:only! -:b1 -ENDTEST - -STARTTEST -:let tests = [] -:so tiny.vim -:for i in range(5) -:new -:endfor -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:4wincmd w -:.hide -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:1hide -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:$hide -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:1wincmd w -:2hide -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:1wincmd w -:new -:new -:3wincmd w -:-hide -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:2wincmd w -:+hide -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:e! test.out -:call append(line('$'), map(copy(tests), 'join(v:val, " ")')) -Go -:w -:only! -:b1 -ENDTEST - -STARTTEST -:let tests = [] -:so tiny.vim -:set hidden -:for i in range(5) -:new -:endfor -:1wincmd w -:$ hide -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:$-1 close! -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:1wincmd w -:.+close! -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:e! test.out -:call append(line('$'), map(copy(tests), 'join(v:val, " ")')) -Go -:w -:only! -:b1 -ENDTEST - -STARTTEST -:let tests = [] -:so tiny.vim -:set hidden -:for i in range(5) -:new -:endfor -:4wincmd w -c -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -1c -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -9c -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:1wincmd w -2c -:let buffers = [] -:windo call add(buffers, bufnr('%')) -:call add(tests, buffers) -:only! -:e! test.out -:call append(line('$'), map(copy(tests), 'join(v:val, " ")')) -:w -:qa! -ENDTEST - - diff --git a/src/nvim/testdir/test_close_count.ok b/src/nvim/testdir/test_close_count.ok deleted file mode 100644 index 1cee870487..0000000000 --- a/src/nvim/testdir/test_close_count.ok +++ /dev/null @@ -1,23 +0,0 @@ -6 5 4 2 1 -5 4 2 1 -5 4 2 -5 2 -7 5 2 -7 5 - -13 12 11 10 9 1 -13 12 11 9 1 -12 11 9 1 -12 11 9 -12 9 -15 12 9 -15 12 - -20 19 18 17 16 -20 19 18 16 -20 18 16 - -25 24 23 21 1 -24 23 21 1 -24 23 21 -24 21 diff --git a/src/nvim/testdir/test_langmap.vim b/src/nvim/testdir/test_langmap.vim new file mode 100644 index 0000000000..066c3bf2bd --- /dev/null +++ b/src/nvim/testdir/test_langmap.vim @@ -0,0 +1,24 @@ +" tests for 'langmap' + +func Test_langmap() + new + set langmap=}l,^x,%v + + call setline(1, ['abc']) + call feedkeys('gg0}^', 'tx') + call assert_equal('ac', getline(1)) + + " in Replace mode + " need silent! to avoid a delay when entering Insert mode + call setline(1, ['abcde']) + silent! call feedkeys("gg0lR%{z\<Esc>00", 'tx') + call assert_equal('a%{ze', getline(1)) + + " in Select mode + " need silent! to avoid a delay when entering Insert mode + call setline(1, ['abcde']) + silent! call feedkeys("gg0}%}\<C-G>}^\<Esc>00", 'tx') + call assert_equal('a}^de', getline(1)) + + quit! +endfunc diff --git a/src/nvim/testdir/test_listlbr.in b/src/nvim/testdir/test_listlbr.in deleted file mode 100644 index 6084711786..0000000000 --- a/src/nvim/testdir/test_listlbr.in +++ /dev/null @@ -1,120 +0,0 @@ -Test for linebreak and list option (non-utf8) - -STARTTEST -:so small.vim -:if !exists("+linebreak") | e! test.ok | w! test.out | qa! | endif -:set wildchar=^E -:10new|:vsp|:vert resize 20 -:put =\"\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP \" -:norm! zt -:set ts=4 sw=4 sts=4 linebreak sbr=+ wrap -:fu! ScreenChar(width) -: let c='' -: for j in range(1,4) -: for i in range(1,a:width) -: let c.=nr2char(screenchar(j, i)) -: endfor -: let c.="\n" -: endfor -: return c -:endfu -:fu! DoRecordScreen() -: wincmd l -: $put =printf(\"\n%s\", g:test) -: $put =g:line -: wincmd p -:endfu -:" -:let g:test="Test 1: set linebreak" -:redraw! -:let line=ScreenChar(winwidth(0)) -:call DoRecordScreen() -:" -:let g:test="Test 2: set linebreak + set list" -:set linebreak list listchars= -:redraw! -:let line=ScreenChar(winwidth(0)) -:call DoRecordScreen() -:" -:let g:test ="Test 3: set linebreak nolist" -:set nolist linebreak -:redraw! -:let line=ScreenChar(winwidth(0)) -:call DoRecordScreen() -:" -:let g:test ="Test 4: set linebreak with tab and 1 line as long as screen: should break!" -:set nolist linebreak ts=8 -:let line="1\t".repeat('a', winwidth(0)-2) -:$put =line -:$ -:norm! zt -:redraw! -:let line=ScreenChar(winwidth(0)) -:call DoRecordScreen() -:let line="_S_\t bla" -:$put =line -:$ -:norm! zt -:" -:let g:test ="Test 5: set linebreak with conceal and set list and tab displayed by different char (line may not be truncated)" -:set cpo&vim list linebreak conceallevel=2 concealcursor=nv listchars=tab:ab -:syn match ConcealVar contained /_/ conceal -:syn match All /.*/ contains=ConcealVar -:let line=ScreenChar(winwidth(0)) -:call DoRecordScreen() -:set cpo&vim linebreak -:" -:let g:test ="Test 6: set linebreak with visual block mode" -:let line="REMOVE: this not" -:$put =g:test -:$put =line -:let line="REMOVE: aaaaaaaaaaaaa" -:$put =line -:1/^REMOVE: -0jf x:$put -:set cpo&vim linebreak -:" -:let g:test ="Test 7: set linebreak with visual block mode and v_b_A" -:$put =g:test -Golong line: 40afoobar aTARGET at end -:exe "norm! $3B\<C-v>eAx\<Esc>" -:set cpo&vim linebreak sbr= -:" -:let g:test ="Test 8: set linebreak with visual char mode and changing block" -:$put =g:test -Go1111-1111-1111-11-1111-1111-11110f-lv3lc2222bgj. -:" -:let g:test ="Test 9: using redo after block visual mode" -:$put =g:test -Go -aaa -aaa -a2k2j~e. -:" -:let g:test ="Test 10: using normal commands after block-visual" -:$put =g:test -:set linebreak -Go -abcd{ef -ghijklm -no}pqrs2k0f{c% -:" -:let g:test ="Test 11: using block replace mode after wrapping" -:$put =g:test -:set linebreak wrap -Go150aayypk147|jr0 -:" -:let g:test ="Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$" -:set list listchars=space:_,trail:-,tab:>-,eol:$ -:$put =g:test -:let line="a aaaaaaaaaaaaaaaaaaaaaa\ta " -:$put =line -:$ -:norm! zt -:redraw! -:let line=ScreenChar(winwidth(0)) -:call DoRecordScreen() -:%w! test.out -:qa! -ENDTEST -dummy text diff --git a/src/nvim/testdir/test_listlbr.ok b/src/nvim/testdir/test_listlbr.ok deleted file mode 100644 index b32a54969e..0000000000 --- a/src/nvim/testdir/test_listlbr.ok +++ /dev/null @@ -1,62 +0,0 @@ - - abcdef hijklmn pqrstuvwxyz_1060ABCDEFGHIJKLMNOP - -Test 1: set linebreak - abcdef -+hijklmn -+pqrstuvwxyz_1060ABC -+DEFGHIJKLMNOP - -Test 2: set linebreak + set list -^Iabcdef hijklmn^I -+pqrstuvwxyz_1060ABC -+DEFGHIJKLMNOP - - -Test 3: set linebreak nolist - abcdef -+hijklmn -+pqrstuvwxyz_1060ABC -+DEFGHIJKLMNOP -1 aaaaaaaaaaaaaaaaaa - -Test 4: set linebreak with tab and 1 line as long as screen: should break! -1 -+aaaaaaaaaaaaaaaaaa -~ -~ -_S_ bla - -Test 5: set linebreak with conceal and set list and tab displayed by different char (line may not be truncated) -Sabbbbbb bla -~ -~ -~ -Test 6: set linebreak with visual block mode -this not -aaaaaaaaaaaaa -REMOVE: -REMOVE: -Test 7: set linebreak with visual block mode and v_b_A -long line: foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar TARGETx at end -Test 8: set linebreak with visual char mode and changing block -1111-2222-1111-11-1111-2222-1111 -Test 9: using redo after block visual mode - -AaA -AaA -A -Test 10: using normal commands after block-visual - -abcdpqrs -Test 11: using block replace mode after wrapping -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0aaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0aaa -Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$ -a aaaaaaaaaaaaaaaaaaaaaa a - -Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$ -a_ -aaaaaaaaaaaaaaaaaaaa -aa>-----a-$ -~ diff --git a/src/nvim/testdir/test_syntax.vim b/src/nvim/testdir/test_syntax.vim new file mode 100644 index 0000000000..309c0f460b --- /dev/null +++ b/src/nvim/testdir/test_syntax.vim @@ -0,0 +1,63 @@ +" Test for syntax and syntax iskeyword option + +func GetSyntaxItem(pat) + let c = '' + let a = ['a', getreg('a'), getregtype('a')] + 0 + redraw! + call search(a:pat, 'W') + let synid = synID(line('.'), col('.'), 1) + while synid == synID(line('.'), col('.'), 1) + norm! v"ay + " stop at whitespace + if @a =~# '\s' + break + endif + let c .= @a + norm! l + endw + call call('setreg', a) + 0 + return c +endfunc + +func Test_syn_iskeyword() + new + call setline(1, [ + \ 'CREATE TABLE FOOBAR(', + \ ' DLTD_BY VARCHAR2(100)', + \ ');', + \ '']) + + syntax on + set ft=sql + syn match SYN /C\k\+\>/ + hi link SYN ErrorMsg + call assert_equal('DLTD_BY', GetSyntaxItem('DLTD')) + /\<D\k\+\>/:norm! ygn + call assert_equal('DLTD_BY', @0) + redir @c + syn iskeyword + redir END + call assert_equal("\nsyntax iskeyword not set", @c) + + syn iskeyword @,48-57,_,192-255 + redir @c + syn iskeyword + redir END + call assert_equal("\nsyntax iskeyword @,48-57,_,192-255", @c) + + setlocal isk-=_ + call assert_equal('DLTD_BY', GetSyntaxItem('DLTD')) + /\<D\k\+\>/:norm! ygn + let b2=@0 + call assert_equal('DLTD', @0) + + syn iskeyword clear + redir @c + syn iskeyword + redir END + call assert_equal("\nsyntax iskeyword not set", @c) + + quit! +endfunc diff --git a/src/nvim/testdir/test_timers.vim b/src/nvim/testdir/test_timers.vim new file mode 100644 index 0000000000..9f58a35909 --- /dev/null +++ b/src/nvim/testdir/test_timers.vim @@ -0,0 +1,32 @@ +" Test for timers + +if !has('timers') + finish +endif + +func MyHandler(timer) + let s:val += 1 +endfunc + +func Test_oneshot() + let s:val = 0 + let timer = timer_start(50, 'MyHandler') + sleep 200m + call assert_equal(1, s:val) +endfunc + +func Test_repeat_three() + let s:val = 0 + let timer = timer_start(50, 'MyHandler', {'repeat': 3}) + sleep 500m + call assert_equal(3, s:val) +endfunc + +func Test_repeat_many() + let s:val = 0 + let timer = timer_start(50, 'MyHandler', {'repeat': -1}) + sleep 200m + call timer_stop(timer) + call assert_true(s:val > 1) + call assert_true(s:val < 5) +endfunc diff --git a/src/nvim/testdir/test_unlet.vim b/src/nvim/testdir/test_unlet.vim new file mode 100644 index 0000000000..f6705997a9 --- /dev/null +++ b/src/nvim/testdir/test_unlet.vim @@ -0,0 +1,26 @@ +" Tests for :unlet + +func Test_read_only() + try + " this caused a crash + unlet count + catch + call assert_true(v:exception =~ ':E795:') + endtry +endfunc + +func Test_existing() + let does_exist = 1 + call assert_true(exists('does_exist')) + unlet does_exist + call assert_false(exists('does_exist')) +endfunc + +func Test_not_existing() + unlet! does_not_exist + try + unlet does_not_exist + catch + call assert_true(v:exception =~ ':E108:') + endtry +endfunc diff --git a/src/nvim/testdir/test_viml.vim b/src/nvim/testdir/test_viml.vim index 9f0618bd45..2d989cdad9 100644 --- a/src/nvim/testdir/test_viml.vim +++ b/src/nvim/testdir/test_viml.vim @@ -922,6 +922,45 @@ func Test_curlies() call assert_equal(77, g:a['t']) endfunc +"------------------------------------------------------------------------------- +" Test 91: using type(). {{{1 +"------------------------------------------------------------------------------- + +func Test_type() + call assert_equal(0, type(0)) + call assert_equal(1, type("")) + call assert_equal(2, type(function("tr"))) + call assert_equal(3, type([])) + call assert_equal(4, type({})) + call assert_equal(5, type(0.0)) + call assert_equal(6, type(v:false)) + call assert_equal(6, type(v:true)) + call assert_equal(7, type(v:null)) +endfunc + +"------------------------------------------------------------------------------- +" Test 92: skipping code {{{1 +"------------------------------------------------------------------------------- + +func Test_skip() + let Fn = function('Test_type') + call assert_false(0 && Fn[1]) + call assert_false(0 && string(Fn)) + call assert_false(0 && len(Fn)) + let l = [] + call assert_false(0 && l[1]) + call assert_false(0 && string(l)) + call assert_false(0 && len(l)) + let f = 1.0 + call assert_false(0 && f[1]) + call assert_false(0 && string(f)) + call assert_false(0 && len(f)) + let sp = v:null + call assert_false(0 && sp[1]) + call assert_false(0 && string(sp)) + call assert_false(0 && len(sp)) + +endfunc "------------------------------------------------------------------------------- " Modelines {{{1 diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 99eb230a88..3a136a4b1d 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -4,6 +4,7 @@ #include "nvim/api/vim.h" #include "nvim/api/private/helpers.h" #include "nvim/ascii.h" +#include "nvim/main.h" #include "nvim/misc2.h" #include "nvim/os/os.h" #include "nvim/os/input.h" @@ -92,7 +93,7 @@ static void flush_input(TermInput *input, bool wait_until_empty) size_t drain_boundary = wait_until_empty ? 0 : 0xff; do { uv_mutex_lock(&input->key_buffer_mutex); - loop_schedule(&loop, event_create(1, wait_input_enqueue, 1, input)); + loop_schedule(&main_loop, event_create(1, wait_input_enqueue, 1, input)); input->waiting = true; while (input->waiting) { uv_cond_wait(&input->key_buffer_cond, &input->key_buffer_mutex); @@ -153,7 +154,8 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key) TermKeyMouseEvent ev; termkey_interpret_mouse(input->tk, key, &ev, &button, &row, &col); - if (ev != TERMKEY_MOUSE_PRESS && ev != TERMKEY_MOUSE_DRAG) { + if (ev != TERMKEY_MOUSE_PRESS && ev != TERMKEY_MOUSE_DRAG + && ev != TERMKEY_MOUSE_RELEASE) { return; } @@ -190,6 +192,8 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key) } } else if (ev == TERMKEY_MOUSE_DRAG) { len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Drag"); + } else if (ev == TERMKEY_MOUSE_RELEASE) { + len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Release"); } len += (size_t)snprintf(buf + len, sizeof(buf) - len, "><%d,%d>", col, row); @@ -336,7 +340,7 @@ static void read_cb(Stream *stream, RBuffer *buf, size_t c, void *data, stream_close(&input->read_stream, NULL); queue_put(input->loop->fast_events, restart_reading, 1, input); } else { - loop_schedule(&loop, event_create(1, input_done_event, 0)); + loop_schedule(&main_loop, event_create(1, input_done_event, 0)); } return; } diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 62bc81ba64..50558e644a 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -11,6 +11,7 @@ #include "nvim/vim.h" #include "nvim/ui.h" #include "nvim/map.h" +#include "nvim/main.h" #include "nvim/memory.h" #include "nvim/api/vim.h" #include "nvim/api/private/helpers.h" @@ -261,7 +262,7 @@ static void sigwinch_cb(SignalWatcher *watcher, int signum, void *data) UI *ui = data; update_size(ui); // run refresh_event in nvim main loop - loop_schedule(&loop, event_create(1, refresh_event, 0)); + loop_schedule(&main_loop, event_create(1, refresh_event, 0)); } static bool attrs_differ(HlAttrs a1, HlAttrs a2) @@ -681,7 +682,7 @@ static void invalidate(UI *ui, int top, int bot, int left, int right) intersects->right = MAX(right, intersects->right); } else { // Else just add a new entry; - kv_push(Rect, data->invalid_regions, ((Rect){top, bot, left, right})); + kv_push(data->invalid_regions, ((Rect) { top, bot, left, right })); } } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 05322a6f64..ae38754c1e 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -30,7 +30,11 @@ #include "nvim/screen.h" #include "nvim/syntax.h" #include "nvim/window.h" -#include "nvim/tui/tui.h" +#ifdef FEAT_TUI +# include "nvim/tui/tui.h" +#else +# include "nvim/msgpack_rpc/server.h" +#endif #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ui.c.generated.h" @@ -83,7 +87,22 @@ static int height, width; void ui_builtin_start(void) { +#ifdef FEAT_TUI tui_start(); +#else + fprintf(stderr, "Neovim was built without a Terminal UI," \ + "press Ctrl+C to exit\n"); + + size_t len; + char **addrs = server_address_list(&len); + if (addrs != NULL) { + fprintf(stderr, "currently listening on the following address(es)\n"); + for (size_t i = 0; i < len; i++) { + fprintf(stderr, "\t%s\n", addrs[i]); + } + xfree(addrs); + } +#endif } void ui_builtin_stop(void) @@ -188,7 +207,7 @@ void ui_mouse_off(void) UI_CALL(mouse_off); } -void ui_attach(UI *ui) +void ui_attach_impl(UI *ui) { if (ui_count == MAX_UI_COUNT) { abort(); @@ -198,7 +217,7 @@ void ui_attach(UI *ui) ui_refresh(); } -void ui_detach(UI *ui) +void ui_detach_impl(UI *ui) { size_t shift_index = MAX_UI_COUNT; diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c index fd9d4671e3..41d35684b1 100644 --- a/src/nvim/ui_bridge.c +++ b/src/nvim/ui_bridge.c @@ -5,6 +5,7 @@ #include <stdio.h> #include <limits.h> +#include "nvim/main.h" #include "nvim/vim.h" #include "nvim/ui.h" #include "nvim/memory.h" @@ -71,7 +72,7 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler) } uv_mutex_unlock(&rv->mutex); - ui_attach(&rv->bridge); + ui_attach_impl(&rv->bridge); return &rv->bridge; } @@ -100,12 +101,12 @@ static void ui_bridge_stop(UI *b) if (stopped) { break; } - loop_poll_events(&loop, 10); + loop_poll_events(&main_loop, 10); } uv_thread_join(&bridge->ui_thread); uv_mutex_destroy(&bridge->mutex); uv_cond_destroy(&bridge->cond); - ui_detach(b); + ui_detach_impl(b); xfree(b); } static void ui_bridge_stop_event(void **argv) diff --git a/src/nvim/version.c b/src/nvim/version.c index f582beef88..0ca859186c 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -64,12 +64,19 @@ static char *features[] = { #else "-jemalloc", #endif + +#ifdef FEAT_TUI + "+tui", +#else + "-tui", +#endif NULL }; // clang-format off static int included_patches[] = { 1832, + 1831, 1809, 1808, 1806, @@ -78,10 +85,12 @@ static int included_patches[] = { 1755, 1753, 1728, + 1695, 1654, 1652, 1643, 1641, + // 1624 NA // 1600 NA // 1599 NA @@ -106,7 +115,7 @@ static int included_patches[] = { // 1581, // 1580, // 1579, - // 1578, + 1578, // 1577, 1576, // 1575 NA @@ -117,7 +126,7 @@ static int included_patches[] = { 1570, 1569, 1568, - // 1567, + 1567, // 1566 NA // 1565, // 1564, @@ -163,12 +172,12 @@ static int included_patches[] = { // 1524 NA // 1523 NA // 1522 NA - // 1521, + 1521, // 1520 NA // 1519 NA // 1518 NA // 1517 NA - // 1516, + 1516, // 1515 NA // 1514 NA 1513, @@ -216,11 +225,11 @@ static int included_patches[] = { // 1471 NA // 1470 NA // 1469 NA - // 1468, + 1468, // 1467 NA // 1466 NA // 1465 NA - // 1464, + 1464, // 1463 NA // 1462 NA // 1461 NA @@ -287,10 +296,10 @@ static int included_patches[] = { // 1400 NA // 1399 NA // 1398 NA - // 1397, + 1397, // 1396, // 1395 NA - // 1394, + 1394, // 1393 NA // 1392 NA // 1391 NA @@ -403,12 +412,12 @@ static int included_patches[] = { 1284, // 1283 NA 1282, - // 1281, + 1281, // 1280 NA // 1279 NA // 1278 NA // 1277 NA - // 1276, + 1276, // 1275 NA // 1274 NA // 1273, @@ -461,7 +470,7 @@ static int included_patches[] = { // 1226 NA // 1225 NA // 1224 NA - // 1223, + 1223, // 1222 NA // 1221 NA // 1220 NA @@ -523,7 +532,7 @@ static int included_patches[] = { 1164, 1163, // 1162 NA - // 1161, + 1161, 1160, // 1159 NA // 1158 NA @@ -531,10 +540,10 @@ static int included_patches[] = { // 1156 NA // 1155 NA // 1154 NA - // 1153, + 1153, // 1152 NA - // 1151, - // 1150, + 1151, + 1150, 1149, // 1148 NA // 1147, @@ -542,7 +551,7 @@ static int included_patches[] = { // 1145 NA 1144, 1143, - // 1142, + 1142, 1141, // 1140, // 1139 NA @@ -552,7 +561,7 @@ static int included_patches[] = { // 1135 NA // 1134 NA // 1133 NA - // 1132, + 1132, // 1131 NA // 1130, // 1129 NA @@ -561,11 +570,11 @@ static int included_patches[] = { // 1126, // 1125 NA // 1124 NA - // 1123, + 1123, // 1122 NA // 1121, 1120, - // 1119, + 1119, 1118, 1117, 1116, @@ -576,7 +585,7 @@ static int included_patches[] = { // 1111, 1110, // 1109 NA - // 1108, + 1108, 1107, // 1106 NA 1105, @@ -588,7 +597,7 @@ static int included_patches[] = { // 1099 NA // 1098 NA // 1097, - // 1096, + 1096, // 1095 NA 1094, 1093, @@ -613,28 +622,28 @@ static int included_patches[] = { // 1074 NA, // 1073, 1072, - // 1071, + 1071, // 1070 NA // 1069 NA - // 1068, + 1068, // 1067 NA // 1066 NA 1065, - // 1064, + 1064, // 1063 NA // 1062 NA - // 1061, + 1061, // 1060 NA 1059, // 1058, 1057, - // 1056, + 1056, 1055, 1054, - // 1053, + 1053, 1052, - // 1051, - // 1050, + 1051, + 1050, 1049, 1048, 1047, @@ -2011,3 +2020,4 @@ void ex_intro(exarg_T *eap) intro_message(TRUE); wait_return(TRUE); } + diff --git a/test/benchmark/bench_re_freeze_spec.lua b/test/benchmark/bench_re_freeze_spec.lua index d40d9f9ece..a194b5f44c 100644 --- a/test/benchmark/bench_re_freeze_spec.lua +++ b/test/benchmark/bench_re_freeze_spec.lua @@ -25,8 +25,8 @@ local measure_script = [[ endfunc]] describe('regexp search', function() - -- The test cases rely on a small Vim script, which we source here, and also - -- on a temporary result file, which we prepare and write to disk. + -- The test cases rely on a temporary result file, which we prepare and write + -- to disk. setup(function() clear() source(measure_script) diff --git a/test/functional/eval/timer_spec.lua b/test/functional/eval/timer_spec.lua new file mode 100644 index 0000000000..611113f560 --- /dev/null +++ b/test/functional/eval/timer_spec.lua @@ -0,0 +1,129 @@ +local helpers = require('test.functional.helpers') +local Screen = require('test.functional.ui.screen') +local ok, feed, eq, eval = helpers.ok, helpers.feed, helpers.eq, helpers.eval +local source, nvim_async, run = helpers.source, helpers.nvim_async, helpers.run +local clear, execute, funcs = helpers.clear, helpers.execute, helpers.funcs + +describe('timers', function() + before_each(function() + clear() + source([[ + let g:val = 0 + func MyHandler(timer) + let g:val += 1 + endfunc + ]]) + end) + + it('works one-shot', function() + execute("call timer_start(50, 'MyHandler')") + eq(0,eval("g:val")) + run(nil, nil, nil, 200) + eq(1,eval("g:val")) + end) + + it('works with repeat two', function() + execute("call timer_start(50, 'MyHandler', {'repeat': 2})") + eq(0,eval("g:val")) + run(nil, nil, nil, 300) + eq(2,eval("g:val")) + end) + + it('are triggered during sleep', function() + execute("call timer_start(50, 'MyHandler', {'repeat': 2})") + nvim_async("command", "sleep 10") + eq(0,eval("g:val")) + run(nil, nil, nil, 300) + eq(2,eval("g:val")) + end) + + it('can be started during sleep', function() + nvim_async("command", "sleep 10") + -- this also tests that remote requests works during sleep + eval("timer_start(50, 'MyHandler', {'repeat': 2})") + eq(0,eval("g:val")) + run(nil, nil, nil, 300) + eq(2,eval("g:val")) + end) + + it('are paused when event processing is disabled', function() + -- this is not the intended behavior, but at least there will + -- not be a burst of queued up callbacks + execute("call timer_start(50, 'MyHandler', {'repeat': 2})") + run(nil, nil, nil, 100) + local count = eval("g:val") + nvim_async("command", "let g:c = getchar()") + run(nil, nil, nil, 300) + feed("c") + local diff = eval("g:val") - count + ok(0 <= diff and diff <= 2) + eq(99, eval("g:c")) + end) + + it('can be stopped', function() + local t = eval("timer_start(50, 'MyHandler', {'repeat': -1})") + eq(0,eval("g:val")) + run(nil, nil, nil, 300) + funcs.timer_stop(t) + local count = eval("g:val") + run(nil, nil, nil, 300) + local count2 = eval("g:val") + ok(4 <= count and count <= 7) + -- when count is eval:ed after timer_stop this should be non-racy + eq(count, count2) + end) + + it('can be stopped from the handler', function() + source([[ + func! MyHandler(timer) + let g:val += 1 + if g:val == 3 + call timer_stop(a:timer) + " check double stop is ignored + call timer_stop(a:timer) + endif + endfunc + ]]) + execute("call timer_start(50, 'MyHandler', {'repeat': -1})") + eq(0,eval("g:val")) + run(nil, nil, nil, 300) + eq(3,eval("g:val")) + end) + + it('can have two timers', function() + source([[ + let g:val2 = 0 + func! MyHandler2(timer) + let g:val2 += 1 + endfunc + ]]) + execute("call timer_start(50, 'MyHandler', {'repeat': 3})") + execute("call timer_start(100, 'MyHandler2', {'repeat': 2})") + run(nil, nil, nil, 300) + eq(3,eval("g:val")) + eq(2,eval("g:val2")) + end) + + it("doesn't mess up the cmdline", function() + local screen = Screen.new(40, 6) + screen:attach() + screen:set_default_attr_ignore({{bold=true, foreground=Screen.colors.Blue}}) + source([[ + func! MyHandler(timer) + echo "evil" + endfunc + ]]) + execute("call timer_start(100, 'MyHandler', {'repeat': 1})") + feed(":good") + screen:sleep(200) + screen:expect([[ + | + ~ | + ~ | + ~ | + ~ | + :good^ | + ]]) + end) + +end) diff --git a/test/functional/ex_cmds/cd_spec.lua b/test/functional/ex_cmds/cd_spec.lua index 69467632a4..00b3b083d1 100644 --- a/test/functional/ex_cmds/cd_spec.lua +++ b/test/functional/ex_cmds/cd_spec.lua @@ -1,49 +1,145 @@ -- Specs for :cd, :tcd, :lcd and getcwd() -local helpers = require('test.functional.helpers') -local execute, eq, clear, eval, exc_exec = - helpers.execute, helpers.eq, helpers.clear, helpers.eval, helpers.exc_exec local lfs = require('lfs') +local helpers = require('test.functional.helpers') + +local eq = helpers.eq +local call = helpers.call +local clear = helpers.clear +local execute = helpers.execute +local exc_exec = helpers.exc_exec -- These directories will be created for testing local directories = { - 'Xtest-functional-ex_cmds-cd_spec.1', -- Tab - 'Xtest-functional-ex_cmds-cd_spec.2', -- Window - 'Xtest-functional-ex_cmds-cd_spec.3', -- New global + tab = 'Xtest-functional-ex_cmds-cd_spec.tab', -- Tab + window = 'Xtest-functional-ex_cmds-cd_spec.window', -- Window + global = 'Xtest-functional-ex_cmds-cd_spec.global', -- New global } -- Shorthand writing to get the current working directory -local cwd = function() return eval('getcwd( )') end -- effective working dir -local wcwd = function() return eval('getcwd( 0 )') end -- window dir -local tcwd = function() return eval('getcwd(-1, 0)') end -- tab dir ---local gcwd = function() return eval('getcwd(-1, -1)') end -- global dir +local cwd = function(...) return call('getcwd', ...) end -- effective working dir +local wcwd = function() return cwd(0) end -- window dir +local tcwd = function() return cwd(-1, 0) end -- tab dir -- Same, except these tell us if there is a working directory at all ---local lwd = function() return eval('haslocaldir( )') end -- effective working dir -local wlwd = function() return eval('haslocaldir( 0 )') end -- window dir -local tlwd = function() return eval('haslocaldir(-1, 0)') end -- tab dir +local lwd = function(...) return call('haslocaldir', ...) end -- effective working dir +local wlwd = function() return lwd(0) end -- window dir +local tlwd = function() return lwd(-1, 0) end -- tab dir --local glwd = function() return eval('haslocaldir(-1, -1)') end -- global dir -- Test both the `cd` and `chdir` variants for _, cmd in ipairs {'cd', 'chdir'} do - describe(':*' .. cmd, function() + describe(':' .. cmd, function() before_each(function() clear() - for _, d in ipairs(directories) do + for _, d in pairs(directories) do lfs.mkdir(d) end + directories.start = cwd() end) after_each(function() - for _, d in ipairs(directories) do + for _, d in pairs(directories) do lfs.rmdir(d) end end) - it('works', function() - -- Store the initial working directory - local globalDir = cwd() + describe('using explicit scope', function() + it('for window', function() + local globalDir = directories.start + local globalwin = call('winnr') + local tabnr = call('tabpagenr') + + -- Everything matches globalDir to start + eq(globalDir, cwd(globalwin)) + eq(globalDir, cwd(globalwin, tabnr)) + eq(0, lwd(globalwin)) + eq(0, lwd(globalwin, tabnr)) + + execute('bot split') + local localwin = call('winnr') + -- Initial window is still using globalDir + eq(globalDir, cwd(localwin)) + eq(globalDir, cwd(localwin, tabnr)) + eq(0, lwd(globalwin)) + eq(0, lwd(globalwin, tabnr)) + + execute('silent l' .. cmd .. ' ' .. directories.window) + -- From window with local dir, the original window + -- is still reporting the global dir + eq(globalDir, cwd(globalwin)) + eq(globalDir, cwd(globalwin, tabnr)) + eq(0, lwd(globalwin)) + eq(0, lwd(globalwin, tabnr)) + + -- Window with local dir reports as such + eq(globalDir .. '/' .. directories.window, cwd(localwin)) + eq(globalDir .. '/' .. directories.window, cwd(localwin, tabnr)) + eq(1, lwd(localwin)) + eq(1, lwd(localwin, tabnr)) + + execute('tabnew') + -- From new tab page, original window reports global dir + eq(globalDir, cwd(globalwin, tabnr)) + eq(0, lwd(globalwin, tabnr)) + + -- From new tab page, local window reports as such + eq(globalDir .. '/' .. directories.window, cwd(localwin, tabnr)) + eq(1, lwd(localwin, tabnr)) + end) + + it('for tab page', function() + local globalDir = directories.start + local globaltab = call('tabpagenr') + + -- Everything matches globalDir to start + eq(globalDir, cwd(-1, 0)) + eq(globalDir, cwd(-1, globaltab)) + eq(0, lwd(-1, 0)) + eq(0, lwd(-1, globaltab)) + + execute('tabnew') + execute('silent t' .. cmd .. ' ' .. directories.tab) + local localtab = call('tabpagenr') + + -- From local tab page, original tab reports globalDir + eq(globalDir, cwd(-1, globaltab)) + eq(0, lwd(-1, globaltab)) + + -- new tab reports local + eq(globalDir .. '/' .. directories.tab, cwd(-1, 0)) + eq(globalDir .. '/' .. directories.tab, cwd(-1, localtab)) + eq(1, lwd(-1, 0)) + eq(1, lwd(-1, localtab)) + + execute('tabnext') + -- From original tab page, local reports as such + eq(globalDir .. '/' .. directories.tab, cwd(-1, localtab)) + eq(1, lwd(-1, localtab)) + end) + end) + + describe('getcwd(-1, -1)', function() + it('works', function() + eq(directories.start, cwd(-1, -1)) + eq(0, lwd(-1, -1)) + end) + + it('works with tab-local pwd', function() + execute('silent t' .. cmd .. ' ' .. directories.tab) + eq(directories.start, cwd(-1, -1)) + eq(0, lwd(-1, -1)) + end) + + it('works with window-local pwd', function() + execute('silent l' .. cmd .. ' ' .. directories.window) + eq(directories.start, cwd(-1, -1)) + eq(0, lwd(-1, -1)) + end) + end) + it('works', function() + local globalDir = directories.start -- Create a new tab first and verify that is has the same working dir execute('tabnew') eq(globalDir, cwd()) @@ -53,8 +149,8 @@ for _, cmd in ipairs {'cd', 'chdir'} do eq(0, wlwd()) -- Change tab-local working directory and verify it is different - execute('silent t' .. cmd .. ' ' .. directories[1]) - eq(globalDir .. '/' .. directories[1], cwd()) + execute('silent t' .. cmd .. ' ' .. directories.tab) + eq(globalDir .. '/' .. directories.tab, cwd()) eq(cwd(), tcwd()) -- working directory maches tab directory eq(1, tlwd()) eq(cwd(), wcwd()) -- still no window-directory @@ -64,16 +160,16 @@ for _, cmd in ipairs {'cd', 'chdir'} do execute('new') eq(1, tlwd()) -- Still tab-local working directory eq(0, wlwd()) -- Still no window-local working directory - eq(globalDir .. '/' .. directories[1], cwd()) - execute('silent l' .. cmd .. ' ../' .. directories[2]) - eq(globalDir .. '/' .. directories[2], cwd()) - eq(globalDir .. '/' .. directories[1], tcwd()) + eq(globalDir .. '/' .. directories.tab, cwd()) + execute('silent l' .. cmd .. ' ../' .. directories.window) + eq(globalDir .. '/' .. directories.window, cwd()) + eq(globalDir .. '/' .. directories.tab, tcwd()) eq(1, wlwd()) -- Verify the first window still has the tab local directory execute('wincmd w') - eq(globalDir .. '/' .. directories[1], cwd()) - eq(globalDir .. '/' .. directories[1], tcwd()) + eq(globalDir .. '/' .. directories.tab, cwd()) + eq(globalDir .. '/' .. directories.tab, tcwd()) eq(0, wlwd()) -- No window-local directory -- Change back to initial tab and verify working directory has stayed @@ -83,11 +179,11 @@ for _, cmd in ipairs {'cd', 'chdir'} do eq(0, wlwd()) -- Verify global changes don't affect local ones - execute('silent ' .. cmd .. ' ' .. directories[3]) - eq(globalDir .. '/' .. directories[3], cwd()) + execute('silent ' .. cmd .. ' ' .. directories.global) + eq(globalDir .. '/' .. directories.global, cwd()) execute('tabnext') - eq(globalDir .. '/' .. directories[1], cwd()) - eq(globalDir .. '/' .. directories[1], tcwd()) + eq(globalDir .. '/' .. directories.tab, cwd()) + eq(globalDir .. '/' .. directories.tab, tcwd()) eq(0, wlwd()) -- Still no window-local directory in this window -- Unless the global change happened in a tab with local directory @@ -101,9 +197,9 @@ for _, cmd in ipairs {'cd', 'chdir'} do -- But not in a window with its own local directory execute('tabnext | wincmd w') - eq(globalDir .. '/' .. directories[2], cwd() ) + eq(globalDir .. '/' .. directories.window, cwd() ) eq(0 , tlwd()) - eq(globalDir .. '/' .. directories[2], wcwd()) + eq(globalDir .. '/' .. directories.window, wcwd()) end) end) end diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index 37b7bf664c..ef8efc04e4 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -30,7 +30,7 @@ if os.getenv('VALGRIND') then prepend_argv = {'valgrind', '-q', '--tool=memcheck', '--leak-check=yes', '--track-origins=yes', '--show-possibly-lost=no', - '--suppressions=.valgrind.supp', + '--suppressions=src/.valgrind.supp', '--log-file='..log_file} if os.getenv('GDB') then table.insert(prepend_argv, '--vgdb=yes') @@ -345,10 +345,18 @@ local function rmdir(path) end for file in lfs.dir(path) do if file ~= '.' and file ~= '..' then - local ret, err = os.remove(path..'/'..file) - if not ret then - error('os.remove: '..err) - return nil + local abspath = path..'/'..file + if lfs.attributes(abspath, 'mode') == 'directory' then + local ret = rmdir(abspath) -- recurse + if not ret then + return nil + end + else + local ret, err = os.remove(abspath) + if not ret then + error('os.remove: '..err) + return nil + end end end end diff --git a/test/functional/legacy/010_errorformat_spec.lua b/test/functional/legacy/010_errorformat_spec.lua new file mode 100644 index 0000000000..40f177e658 --- /dev/null +++ b/test/functional/legacy/010_errorformat_spec.lua @@ -0,0 +1,156 @@ +-- Test for 'errorformat'. This will fail if the quickfix feature was +-- disabled. + +local helpers = require('test.functional.helpers') +local feed, clear, execute = helpers.feed, helpers.clear, helpers.execute +local expect, write_file = helpers.expect, helpers.write_file + +describe('errorformat', function() + setup(function() + clear() + local error_file_text = [[ + start of errorfile + "Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set. + "Xtestfile", line 6 col 19; this is an error + gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include version.c + Xtestfile:9: parse error before `asd' + make: *** [vim] Error 1 + in file "Xtestfile" linenr 10: there is an error + + 2 returned + "Xtestfile", line 11 col 1; this is an error + "Xtestfile", line 12 col 2; this is another error + "Xtestfile", line 14:10; this is an error in column 10 + =Xtestfile=, line 15:10; this is another error, but in vcol 10 this time + "Xtestfile", linenr 16: yet another problem + Error in "Xtestfile" at line 17: + x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17 + ^ + Error in "Xtestfile" at line 18: + x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18 + .............^ + Error in "Xtestfile" at line 19: + x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19 + --------------^ + Error in "Xtestfile" at line 20: + x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20 + ^ + + Does anyone know what is the problem and how to correction it? + "Xtestfile", line 21 col 9: What is the title of the quickfix window? + "Xtestfile", line 22 col 9: What is the title of the quickfix window? + ]] + write_file('Xerrorfile1', error_file_text .. 'end of errorfile\n') + write_file('Xerrorfile2', error_file_text) + write_file('Xtestfile', [[ + start of testfile + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 2 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 3 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 4 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 5 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 6 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 7 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 8 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 9 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 10 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 11 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 12 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 13 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 14 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 15 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 16 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 21 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 22 + end of testfile + ]]) + end) + teardown(function() + os.remove('Xerrorfile1') + os.remove('Xerrorfile2') + os.remove('Xtestfile') + end) + + it('is working', function() + -- Also test a BOM is ignored. + execute( + 'set encoding=utf-8', + [[set efm+==%f=\\,\ line\ %l%*\\D%v%*[^\ ]\ %m]], + [[set efm^=%AError\ in\ \"%f\"\ at\ line\ %l:,%Z%p^,%C%m]], + 'cf Xerrorfile2', + 'clast', + 'copen', + 'let a=w:quickfix_title', + 'wincmd p' + ) + feed('lgR<C-R>=a<CR><esc>') + execute('cf Xerrorfile1') + feed('grA<cr>') + execute('cn') + feed('gRLINE 6, COL 19<esc>') + execute('cn') + feed('gRNO COLUMN SPECIFIED<esc>') + execute('cn') + feed('gRAGAIN NO COLUMN<esc>') + execute('cn') + feed('gRCOL 1<esc>') + execute('cn') + feed('gRCOL 2<esc>') + execute('cn') + feed('gRCOL 10<esc>') + execute('cn') + feed('gRVCOL 10<esc>') + execute('cn') + feed('grI<cr>') + execute('cn') + feed('gR. SPACE POINTER<esc>') + execute('cn') + feed('gR. DOT POINTER<esc>') + execute('cn') + feed('gR. DASH POINTER<esc>') + execute('cn') + feed('gR. TAB-SPACE POINTER<esc>') + execute( + 'clast', + 'cprev', + 'cprev', + 'wincmd w', + 'let a=w:quickfix_title', + 'wincmd p' + ) + feed('lgR<C-R>=a<CR><esc>') + + -- Assert buffer contents. + expect([[ + start of testfile + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 2 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 3 + xxxxxxxxxxAxxxxxxxxxxxxxxxxxxx line 4 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 5 + xxxxxxxxxxxxxxxxxLINE 6, COL 19 line 6 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 7 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 8 + NO COLUMN SPECIFIEDxxxxxxxxxxx line 9 + AGAIN NO COLUMNxxxxxxxxxxxxxxx line 10 + COL 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 11 + COL 2xxxxxxxxxxxxxxxxxxxxxxxxx line 12 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 13 + xxxxxxxxCOL 10xxxxxxxxxxxxxxxx line 14 + xVCOL 10xxxxxxxxxxxxxxxxxxxxxx line 15 + Ixxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 16 + xxxx. SPACE POINTERxxxxxxxxxxx line 17 + xxxxx. DOT POINTERxxxxxxxxxxxx line 18 + xxxxxx. DASH POINTERxxxxxxxxxx line 19 + xxxxxxx. TAB-SPACE POINTERxxxx line 20 + xxxxxxxx:cf Xerrorfile1xxxxxxx line 21 + xxxxxxxx:cf Xerrorfile2xxxxxxx line 22 + end of testfile]]) + end) +end) diff --git a/test/functional/legacy/027_expand_file_names_spec.lua b/test/functional/legacy/027_expand_file_names_spec.lua deleted file mode 100644 index 4778d16d43..0000000000 --- a/test/functional/legacy/027_expand_file_names_spec.lua +++ /dev/null @@ -1,37 +0,0 @@ --- Test for expanding file names - -local helpers = require('test.functional.helpers') -local clear, feed = helpers.clear, helpers.feed -local execute = helpers.execute -local curbuf_contents = helpers.curbuf_contents -local eq = helpers.eq - -describe('expand file name', function() - setup(clear) - - it('is working', function() - execute('!mkdir Xdir1') - execute('!mkdir Xdir2') - execute('!mkdir Xdir3') - execute('cd Xdir3') - execute('!mkdir Xdir4') - execute('cd ..') - execute('w Xdir1/file') - execute('w Xdir3/Xdir4/file') - execute('n Xdir?/*/file') - - -- Yank current file path to @a register - feed('i<C-R>%<Esc>V"ad') - - -- Put @a and current file path in the current buffer - execute('n! Xdir?/*/nofile') - feed('V"ap') - feed('o<C-R>%<Esc>') - - eq("Xdir3/Xdir4/file\nXdir?/*/nofile", curbuf_contents()) - end) - - teardown(function() - os.execute('rm -rf Xdir1 Xdir2 Xdir3') - end) -end) diff --git a/test/functional/legacy/034_user_function_spec.lua b/test/functional/legacy/034_user_function_spec.lua new file mode 100644 index 0000000000..f1337584f0 --- /dev/null +++ b/test/functional/legacy/034_user_function_spec.lua @@ -0,0 +1,102 @@ +-- Test for user functions. +-- Also test an <expr> mapping calling a function. +-- Also test that a builtin function cannot be replaced. +-- Also test for regression when calling arbitrary expression. + +local helpers = require('test.functional.helpers') +local feed, insert, source = helpers.feed, helpers.insert, helpers.source +local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect + +describe('user functions, expr-mappings, overwrite protected builtin functions and regression on calling expressions', function() + setup(clear) + + it('are working', function() + insert('here') + + source([[ + function Table(title, ...) + let ret = a:title + let idx = 1 + while idx <= a:0 + exe "let ret = ret . a:" . idx + let idx = idx + 1 + endwhile + return ret + endfunction + function Compute(n1, n2, divname) + if a:n2 == 0 + return "fail" + endif + exe "let g:" . a:divname . " = ". a:n1 / a:n2 + return "ok" + endfunction + func Expr1() + normal! v + return "111" + endfunc + func Expr2() + call search('XX', 'b') + return "222" + endfunc + func ListItem() + let g:counter += 1 + return g:counter . '. ' + endfunc + func ListReset() + let g:counter = 0 + return '' + endfunc + func FuncWithRef(a) + unlet g:FuncRef + return a:a + endfunc + let g:FuncRef=function("FuncWithRef") + let counter = 0 + inoremap <expr> ( ListItem() + inoremap <expr> [ ListReset() + imap <expr> + Expr1() + imap <expr> * Expr2() + let retval = "nop" + /^here + ]]) + feed('C<C-R>=Table("xxx", 4, "asdf")<cr>') + -- Using a actual space will not work as feed() calls dedent on the input. + feed('<space><C-R>=Compute(45, 0, "retval")<cr>') + feed('<space><C-R>=retval<cr>') + feed('<space><C-R>=Compute(45, 5, "retval")<cr>') + feed('<space><C-R>=retval<cr>') + feed('<space><C-R>=g:FuncRef(333)<cr>') + feed('<cr>') + feed('XX+-XX<cr>') + feed('---*---<cr>') + feed('(one<cr>') + feed('(two<cr>') + feed('[(one again<esc>') + execute('call append(line("$"), max([1, 2, 3]))') + execute('call extend(g:, {"max": function("min")})') + execute('call append(line("$"), max([1, 2, 3]))') + execute('try') + -- Regression: the first line below used to throw "E110: Missing ')'" + -- Second is here just to prove that this line is correct when not + -- skipping rhs of &&. + execute([[ $put =(0&&(function('tr'))(1, 2, 3))]]) + execute([[ $put =(1&&(function('tr'))(1, 2, 3))]]) + execute('catch') + execute([[ $put ='!!! Unexpected exception:']]) + execute(' $put =v:exception') + execute('endtry') + + -- Assert buffer contents. + expect([[ + xxx4asdf fail nop ok 9 333 + XX111-XX + ---222--- + 1. one + 2. two + 1. one again + 3 + 3 + 0 + 1]]) + end) +end) diff --git a/test/functional/legacy/055_list_and_dict_types_spec.lua b/test/functional/legacy/055_list_and_dict_types_spec.lua new file mode 100644 index 0000000000..ed4cd3401d --- /dev/null +++ b/test/functional/legacy/055_list_and_dict_types_spec.lua @@ -0,0 +1,949 @@ +-- Tests for List and Dictionary types. + +local helpers = require('test.functional.helpers') +local feed, source = helpers.feed, helpers.source +local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect + +describe('list and dictionary types', function() + before_each(clear) + + it('creating list directly with different types', function() + source([[ + lang C + let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] + $put =string(l) + $put =string(l[-1]) + $put =string(l[-4]) + try + $put =string(l[-5]) + catch + $put =v:exception[:14] + endtry]]) + expect([[ + + [1, 'as''d', [1, 2, function('strlen')], {'a': 1}] + {'a': 1} + 1 + Vim(put):E684: ]]) + end) + + it('list slices', function() + source([[ + lang C + " The list from the first test repeated after splitting the tests. + let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] + $put =string(l[:]) + $put =string(l[1:]) + $put =string(l[:-2]) + $put =string(l[0:8]) + $put =string(l[8:-1])]]) + expect([=[ + + [1, 'as''d', [1, 2, function('strlen')], {'a': 1}] + ['as''d', [1, 2, function('strlen')], {'a': 1}] + [1, 'as''d', [1, 2, function('strlen')]] + [1, 'as''d', [1, 2, function('strlen')], {'a': 1}] + []]=]) + end) + + it('list identity', function() + source([[ + lang C + " The list from the first test repeated after splitting the tests. + let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] + let ll = l + let lx = copy(l) + try + $put =(l == ll) . (l isnot ll) . (l is ll) . (l == lx) . + \ (l is lx) . (l isnot lx) + catch + $put =v:exception + endtry]]) + expect('\n101101') + end) + + it('creating dictionary directly with different types', function() + source([[ + lang C + let d = {001: 'asd', 'b': [1, 2, function('strlen')], -1: {'a': 1},} + $put =string(d) . d.1 + $put =string(sort(keys(d))) + $put =string (values(d)) + for [key, val] in items(d) + $put =key . ':' . string(val) + unlet key val + endfor + call extend (d, {3:33, 1:99}) + call extend(d, {'b':'bbb', 'c':'ccc'}, "keep") + try + call extend(d, {3:333,4:444}, "error") + catch + $put =v:exception[:15] . v:exception[-1:-1] + endtry + $put =string(d) + call filter(d, 'v:key =~ ''[ac391]''') + $put =string(d)]]) + expect([[ + + {'1': 'asd', 'b': [1, 2, function('strlen')], '-1': {'a': 1}}asd + ['-1', '1', 'b'] + ['asd', [1, 2, function('strlen')], {'a': 1}] + 1:'asd' + b:[1, 2, function('strlen')] + -1:{'a': 1} + Vim(call):E737: 3 + {'c': 'ccc', '1': 99, 'b': [1, 2, function('strlen')], '3': 33, '-1': {'a': 1}} + {'c': 'ccc', '1': 99, '3': 33, '-1': {'a': 1}}]]) + end) + + it('dictionary identity', function() + source([[ + lang C + " The dict from the first test repeated after splitting the tests. + let d = {'c': 'ccc', '1': 99, '3': 33, '-1': {'a': 1}} + let dd = d + let dx = copy(d) + try + $put =(d == dd) . (d isnot dd) . (d is dd) . (d == dx) . (d is dx) . + \ (d isnot dx) + catch + $put =v:exception + endtry]]) + expect('\n101101') + end) + + it('changing var type should fail', function() + source([[ + lang C + " The list from the first test repeated after splitting the tests. + let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] + " The dict from the first test repeated after splitting the tests. + let d = {'c': 'ccc', '1': 99, '3': 33, '-1': {'a': 1}} + try + let d = [] + catch + $put =v:exception[:14] . v:exception[-1:-1] + endtry + try + let l = {} + catch + $put =v:exception[:14] . v:exception[-1:-1] + endtry]]) + expect([[ + + Vim(let):E706: d + Vim(let):E706: l]]) + end) + + it('removing items with :unlet', function() + source([[ + lang C + " The list from the first test repeated after splitting the tests. + let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] + " The dict from the first test repeated after splitting the tests. + let d = {'c': 'ccc', '1': 99, '3': 33, '-1': {'a': 1}} + unlet l[2] + $put =string(l) + let l = range(8) + try + unlet l[:3] + unlet l[1:] + catch + $put =v:exception + endtry + $put =string(l) + + unlet d.c + unlet d[-1] + $put =string(d)]]) + expect([[ + + [1, 'as''d', {'a': 1}] + [4] + {'1': 99, '3': 33}]]) + end) + + it("removing items out of range: silently skip items that don't exist", function() + -- We can not use source() here as we want to ignore all errors. + execute('lang C') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[2:1]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[2:2]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[2:3]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[2:4]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[2:5]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[-1:2]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[-2:2]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[-3:2]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[-4:2]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[-5:2]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[-6:2]') + execute('$put =string(l)') + expect([=[ + + [0, 1, 2, 3] + [0, 1, 3] + [0, 1] + [0, 1] + [0, 1] + [0, 1, 2, 3] + [0, 1, 3] + [0, 3] + [3] + [3] + [3]]=]) + end) + + it('assignment to a list', function() + source([[ + let l = [0, 1, 2, 3] + let [va, vb] = l[2:3] + $put =va + $put =vb + try + let [va, vb] = l + catch + $put =v:exception[:14] + endtry + try + let [va, vb] = l[1:1] + catch + $put =v:exception[:14] + endtry]]) + expect([[ + + 2 + 3 + Vim(let):E687: + Vim(let):E688: ]]) + end) + + it('manipulating a big dictionary', function() + -- Manipulating a big Dictionary (hashtable.c has a border of 1000 + -- entries). + source([[ + let d = {} + for i in range(1500) + let d[i] = 3000 - i + endfor + $put =d[0] . ' ' . d[100] . ' ' . d[999] . ' ' . d[1400] . ' ' . + \ d[1499] + try + let n = d[1500] + catch + $put =substitute(v:exception, '\v(.{14}).*( \d{4}).*', '\1\2', '') + endtry + " Lookup each items. + for i in range(1500) + if d[i] != 3000 - i + $put =d[i] + endif + endfor + let i += 1 + " Delete even items. + while i >= 2 + let i -= 2 + unlet d[i] + endwhile + $put =get(d, 1500 - 100, 'NONE') . ' ' . d[1] + " Delete odd items, checking value, one intentionally wrong. + let d[33] = 999 + let i = 1 + while i < 1500 + if d[i] != 3000 - i + $put =i . '=' . d[i] + else + unlet d[i] + endif + let i += 2 + endwhile + " Must be almost empty now. + $put =string(d)]]) + expect([[ + + 3000 2900 2001 1600 1501 + Vim(let):E716: 1500 + NONE 2999 + 33=999 + {'33': 999}]]) + end) + + it('dictionary function', function() + source([[ + let dict = {} + func dict.func(a) dict + $put =a:a . len(self.data) + endfunc + let dict.data = [1,2,3] + call dict.func("len: ") + let x = dict.func("again: ") + try + let Fn = dict.func + call Fn('xxx') + catch + $put =v:exception[:15] + endtry]]) + expect([[ + + len: 3 + again: 3 + Vim(call):E725: ]]) + end) + + it('Function in script-local List or Dict', function() + source([[ + let g:dict = {} + function g:dict.func() dict + $put ='g:dict.func'.self.foo[1].self.foo[0]('asdf') + endfunc + let g:dict.foo = ['-', 2, 3] + call insert(g:dict.foo, function('strlen')) + call g:dict.func()]]) + expect('\ng:dict.func-4') + end) + + it("remove func from dict that's being called (works)", function() + source([[ + let d = {1:1} + func d.func(a) + return "a:". a:a + endfunc + $put =d.func(string(remove(d, 'func')))]]) + -- The function number changed from 3 to 1 because we split the test. + -- There were two other functions in the old test before this. + expect("\na:function('1')") + end) + + it('deepcopy() dict that refers to itself', function() + -- Nasty: deepcopy() dict that refers to itself (fails when noref used). + source([[ + let d = {1:1, 2:2} + let l = [4, d, 6] + let d[3] = l + let dc = deepcopy(d) + try + let dc = deepcopy(d, 1) + catch + $put =v:exception[:14] + endtry + let l2 = [0, l, l, 3] + let l[1] = l2 + let l3 = deepcopy(l2) + $put ='same list: ' . (l3[1] is l3[2])]]) + expect([[ + + Vim(let):E698: + same list: 1]]) + end) + + it('locked variables (part 1)', function() + source([=[ + let l = [] + for depth in range(5) + $put ='depth is ' . depth + for u in range(3) + unlet l + let l = [0, [1, [2, 3]], {4: 5, 6: {7: 8}}] + exe "lockvar " . depth . " l" + if u == 1 + exe "unlockvar l" + elseif u == 2 + exe "unlockvar " . depth . " l" + endif + let ps = islocked("l") . islocked("l[1]") . islocked("l[1][1]") . + \ islocked("l[1][1][0]") . '-' . islocked("l[2]") . + \ islocked("l[2]['6']") . islocked("l[2]['6'][7]") + $put =ps + let ps = '' + try + let l[1][1][0] = 99 + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l[1][1] = [99] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l[1] = [99] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l[2]['6'][7] = 99 + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l[2][6] = {99: 99} + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l[2] = {99: 99} + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l = [99] + let ps .= 'p' + catch + let ps .= 'F' + endtry + $put =ps + endfor + endfor]=]) + expect([[ + + depth is 0 + 0000-000 + ppppppp + 0000-000 + ppppppp + 0000-000 + ppppppp + depth is 1 + 1000-000 + ppppppF + 0000-000 + ppppppp + 0000-000 + ppppppp + depth is 2 + 1100-100 + ppFppFF + 0000-000 + ppppppp + 0000-000 + ppppppp + depth is 3 + 1110-110 + pFFpFFF + 0010-010 + pFppFpp + 0000-000 + ppppppp + depth is 4 + 1111-111 + FFFFFFF + 0011-011 + FFpFFpp + 0000-000 + ppppppp]]) + end) + + -- TODO In the original test the 5th line of this source() call was used. + -- But now the test only passes if I comment it. + it('unletting locked variables', function() + source([=[ + let l = [] + for depth in range(5) + $put ='depth is ' . depth + for u in range(3) + "unlet l + let l = [0, [1, [2, 3]], {4: 5, 6: {7: 8}}] + exe "lockvar " . depth . " l" + if u == 1 + exe "unlockvar l" + elseif u == 2 + exe "unlockvar " . depth . " l" + endif + let ps = islocked("l") . islocked("l[1]") . islocked("l[1][1]") . + \ islocked("l[1][1][0]") . '-' . islocked("l[2]") . + \ islocked("l[2]['6']") . islocked("l[2]['6'][7]") + $put =ps + let ps = '' + try + unlet l[2]['6'][7] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l[2][6] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l[2] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l[1][1][0] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l[1][1] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l[1] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l + let ps .= 'p' + catch + let ps .= 'F' + endtry + $put =ps + endfor + endfor]=]) + expect([[ + + depth is 0 + 0000-000 + ppppppp + 0000-000 + ppppppp + 0000-000 + ppppppp + depth is 1 + 1000-000 + ppFppFp + 0000-000 + ppppppp + 0000-000 + ppppppp + depth is 2 + 1100-100 + pFFpFFp + 0000-000 + ppppppp + 0000-000 + ppppppp + depth is 3 + 1110-110 + FFFFFFp + 0010-010 + FppFppp + 0000-000 + ppppppp + depth is 4 + 1111-111 + FFFFFFp + 0011-011 + FppFppp + 0000-000 + ppppppp]]) + end) + + it('locked variables and :unlet or list / dict functions', function() + source([[ + $put ='Locks and commands or functions:' + + $put ='No :unlet after lock on dict:' + unlet! d + let d = {'a': 99, 'b': 100} + lockvar 1 d + try + unlet d.a + $put ='did :unlet' + catch + $put =v:exception[:16] + endtry + $put =string(d) + + $put =':unlet after lock on dict item:' + unlet! d + let d = {'a': 99, 'b': 100} + lockvar d.a + try + unlet d.a + $put ='did :unlet' + catch + $put =v:exception[:16] + endtry + $put =string(d) + + $put ='filter() after lock on dict item:' + unlet! d + let d = {'a': 99, 'b': 100} + lockvar d.a + try + call filter(d, 'v:key != "a"') + $put ='did filter()' + catch + $put =v:exception[:16] + endtry + $put =string(d) + + $put ='map() after lock on dict:' + unlet! d + let d = {'a': 99, 'b': 100} + lockvar 1 d + try + call map(d, 'v:val + 200') + $put ='did map()' + catch + $put =v:exception[:16] + endtry + $put =string(d) + + $put ='No extend() after lock on dict item:' + unlet! d + let d = {'a': 99, 'b': 100} + lockvar d.a + try + $put =string(extend(d, {'a': 123})) + $put ='did extend()' + catch + $put =v:exception[:14] + endtry + $put =string(d) + + $put ='No remove() of write-protected scope-level variable:' + fun! Tfunc(this_is_a_loooooooooong_parameter_name) + try + $put =string(remove(a:, 'this_is_a_loooooooooong_parameter_name')) + $put ='did remove()' + catch + $put =v:exception[:14] + endtry + endfun + call Tfunc('testval') + + $put ='No extend() of write-protected scope-level variable:' + fun! Tfunc(this_is_a_loooooooooong_parameter_name) + try + $put =string(extend(a:, {'this_is_a_loooooooooong_parameter_name': 1234})) + $put ='did extend()' + catch + $put =v:exception[:14] + endtry + endfun + call Tfunc('testval') + + $put ='No :unlet of variable in locked scope:' + let b:testvar = 123 + lockvar 1 b: + try + unlet b:testvar + $put ='b:testvar was :unlet: '. (!exists('b:testvar')) + catch + $put =v:exception[:16] + endtry + unlockvar 1 b: + unlet! b:testvar + + $put ='No :let += of locked list variable:' + let l = ['a', 'b', 3] + lockvar 1 l + try + let l += ['x'] + $put ='did :let +=' + catch + $put =v:exception[:14] + endtry + $put =string(l)]]) + + expect([=[ + + Locks and commands or functions: + No :unlet after lock on dict: + Vim(unlet):E741: + {'a': 99, 'b': 100} + :unlet after lock on dict item: + did :unlet + {'b': 100} + filter() after lock on dict item: + did filter() + {'b': 100} + map() after lock on dict: + did map() + {'a': 299, 'b': 300} + No extend() after lock on dict item: + Vim(put):E741: + {'a': 99, 'b': 100} + No remove() of write-protected scope-level variable: + Vim(put):E795: + No extend() of write-protected scope-level variable: + Vim(put):E742: + No :unlet of variable in locked scope: + Vim(unlet):E741: + No :let += of locked list variable: + Vim(let):E741: + ['a', 'b', 3]]=]) + end) + + it('locked variables (part 2)', function() + execute( + 'let l = [1, 2, 3, 4]', + 'lockvar! l', + '$put =string(l)', + 'unlockvar l[1]', + 'unlet l[0:1]', + '$put =string(l)', + 'unlet l[1:2]', + '$put =string(l)', + 'unlockvar l[1]', + 'let l[0:1] = [0, 1]', + '$put =string(l)', + 'let l[1:2] = [0, 1]', + '$put =string(l)') + expect([=[ + + [1, 2, 3, 4] + [1, 2, 3, 4] + [1, 2, 3, 4] + [1, 2, 3, 4] + [1, 2, 3, 4]]=]) + end) + + it(':lockvar/islocked() triggering script autoloading.', function() + source([[ + set rtp+=test/functional/fixtures + lockvar g:footest#x + unlockvar g:footest#x + $put ='locked g:footest#x:'.islocked('g:footest#x') + $put ='exists g:footest#x:'.exists('g:footest#x') + $put ='g:footest#x: '.g:footest#x]]) + expect([[ + + locked g:footest#x:-1 + exists g:footest#x:0 + g:footest#x: 1]]) + end) + + it('a:000 function argument', function() + source([[ + function Test(...) + " First the tests that should fail. + try + let a:000 = [1, 2] + catch + $put ='caught a:000' + endtry + try + let a:000[0] = 9 + catch + $put ='caught a:000[0]' + endtry + try + let a:000[2] = [9, 10] + catch + $put ='caught a:000[2]' + endtry + try + let a:000[3] = {9: 10} + catch + $put ='caught a:000[3]' + endtry + " Now the tests that should pass. + try + let a:000[2][1] = 9 + call extend(a:000[2], [5, 6]) + let a:000[3][5] = 8 + let a:000[3]['a'] = 12 + $put =string(a:000) + catch + $put ='caught ' . v:exception + endtry + endfunction]]) + execute('call Test(1, 2, [3, 4], {5: 6})') + expect([=[ + + caught a:000 + caught a:000[0] + caught a:000[2] + caught a:000[3] + [1, 2, [3, 9, 5, 6], {'a': 12, '5': 8}]]=]) + end) + + it('reverse(), sort(), uniq()', function() + source([=[ + let l = ['-0', 'A11', 2, 2, 'xaaa', 4, 'foo', 'foo6', 'foo', + \ [0, 1, 2], 'x8', [0, 1, 2], 1.5] + $put =string(uniq(copy(l))) + $put =string(reverse(l)) + $put =string(reverse(reverse(l))) + $put =string(sort(l)) + $put =string(reverse(sort(l))) + $put =string(sort(reverse(sort(l)))) + $put =string(uniq(sort(l))) + let l=[7, 9, 'one', 18, 12, 22, 'two', 10.0e-16, -1, 'three', 0xff, + \ 0.22, 'four'] + $put =string(sort(copy(l), 'n')) + let l=[7, 9, 18, 12, 22, 10.0e-16, -1, 0xff, 0, -0, 0.22, 'bar', + \ 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', {}, []] + $put =string(sort(copy(l), 1)) + $put =string(sort(copy(l), 'i')) + $put =string(sort(copy(l)))]=]) + expect([=[ + + ['-0', 'A11', 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5] + [1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'] + [1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'] + ['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]] + [[0, 1, 2], [0, 1, 2], 4, 2, 2, 1.5, 'xaaa', 'x8', 'foo6', 'foo', 'foo', 'A11', '-0'] + ['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]] + ['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 4, [0, 1, 2]] + [-1, 'one', 'two', 'three', 'four', 1.0e-15, 0.22, 7, 9, 12, 18, 22, 255] + ['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}] + ['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}] + ['BAR', 'Bar', 'FOO', 'FOOBAR', 'Foo', 'bar', 'foo', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}]]=]) + end) + + it('splitting a string to a list', function() + source([[ + $put =string(split(' aa bb ')) + $put =string(split(' aa bb ', '\W\+', 0)) + $put =string(split(' aa bb ', '\W\+', 1)) + $put =string(split(' aa bb ', '\W', 1)) + $put =string(split(':aa::bb:', ':', 0)) + $put =string(split(':aa::bb:', ':', 1)) + $put =string(split('aa,,bb, cc,', ',\s*', 1)) + $put =string(split('abc', '\zs')) + $put =string(split('abc', '\zs', 1))]]) + expect([=[ + + ['aa', 'bb'] + ['aa', 'bb'] + ['', 'aa', 'bb', ''] + ['', '', 'aa', '', 'bb', '', ''] + ['aa', '', 'bb'] + ['', 'aa', '', 'bb', ''] + ['aa', '', 'bb', 'cc', ''] + ['a', 'b', 'c'] + ['', 'a', '', 'b', '', 'c', '']]=]) + end) + + it('compare recursively linked list and dict', function() + source([[ + let l = [1, 2, 3, 4] + let d = {'1': 1, '2': l, '3': 3} + let l[1] = d + $put =(l == l) + $put =(d == d) + $put =(l != deepcopy(l)) + $put =(d != deepcopy(d))]]) + expect([[ + + 1 + 1 + 0 + 0]]) + end) + + it('compare complex recursively linked list and dict', function() + source([[ + let l = [] + call add(l, l) + let dict4 = {"l": l} + call add(dict4.l, dict4) + let lcopy = deepcopy(l) + let dict4copy = deepcopy(dict4) + $put =(l == lcopy) + $put =(dict4 == dict4copy)]]) + expect([[ + + 1 + 1]]) + end) + + it('pass the same list to extend()', function() + source([[ + let l = [1, 2, 3, 4, 5] + call extend(l, l) + $put =string(l)]]) + expect([=[ + + [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]]=]) + end) + + it('pass the same dict to extend()', function() + source([[ + let d = { 'a': {'b': 'B'}} + call extend(d, d) + $put =string(d)]]) + expect([[ + + {'a': {'b': 'B'}}]]) + end) + + it('pass the same dict to extend() with "error"', function() + source([[ + " Copy dict from previous test. + let d = { 'a': {'b': 'B'}} + try + call extend(d, d, "error") + catch + $put =v:exception[:15] . v:exception[-1:-1] + endtry + $put =string(d)]]) + expect([[ + + Vim(call):E737: a + {'a': {'b': 'B'}}]]) + end) + + it('test for range assign', function() + source([[ + let l = [0] + let l[:] = [1, 2] + $put =string(l)]]) + expect([=[ + + [1, 2]]=]) + end) + + it('vim patch 7.3.637', function() + execute('let a = "No error caught"') + execute('try') + execute(' foldopen') + execute('catch') + execute(" let a = matchstr(v:exception,'^[^ ]*')") + execute('endtry') + feed('o<C-R>=a<CR><esc>') + execute('lang C') + execute('redir => a') + -- The test failes if this is not in one line. + execute("try|foobar|catch|let a = matchstr(v:exception,'^[^ ]*')|endtry") + execute('redir END') + feed('o<C-R>=a<CR><esc>') + expect([[ + + Vim(foldopen):E490: + + + Error detected while processing : + E492: Not an editor command: foobar|catch|let a = matchstr(v:exception,'^[^ ]*')|endtry + ]]) + end) +end) diff --git a/test/functional/legacy/061_undo_tree_spec.lua b/test/functional/legacy/061_undo_tree_spec.lua index 6db37bf1ff..350a77b2c5 100644 --- a/test/functional/legacy/061_undo_tree_spec.lua +++ b/test/functional/legacy/061_undo_tree_spec.lua @@ -1,10 +1,9 @@ -- Tests for undo tree and :earlier and :later. local helpers = require('test.functional.helpers') -local feed, source, eq, eval, clear, execute, expect, wait, write_file = - helpers.feed, helpers.source, helpers.eq, helpers.eval, - helpers.clear, helpers.execute, helpers.expect, helpers.wait, - helpers.write_file +local expect, feed, source = helpers.expect, helpers.feed, helpers.source +local eval, clear, execute = helpers.eval, helpers.clear, helpers.execute +local write_file, command, eq = helpers.write_file, helpers.command, helpers.eq local function expect_empty_buffer() -- The space will be removed by helpers.dedent but is needed because dedent @@ -57,8 +56,7 @@ describe('undo tree:', function() -- Delete three other characters and go back in time step by step. feed('$xxx') expect_line('123456') - execute('sleep 1') - wait() + command('sleep 1') feed('g-') expect_line('1234567') feed('g-') @@ -79,8 +77,7 @@ describe('undo tree:', function() expect_line('123456') -- Delay for two seconds and go some seconds forward and backward. - execute('sleep 2') - wait() + command('sleep 2') feed('Aa<esc>') feed('Ab<esc>') feed('Ac<esc>') diff --git a/test/functional/legacy/arglist_spec.lua b/test/functional/legacy/arglist_spec.lua new file mode 100644 index 0000000000..b13b621b2c --- /dev/null +++ b/test/functional/legacy/arglist_spec.lua @@ -0,0 +1,268 @@ +-- Test argument list commands + +local helpers = require('test.functional.helpers') +local clear, execute, eq = helpers.clear, helpers.execute, helpers.eq +local eval, exc_exec, neq = helpers.eval, helpers.exc_exec, helpers.neq + +describe('argument list commands', function() + before_each(clear) + + local function init_abc() + execute('args a b c') + execute('next') + end + + local function reset_arglist() + execute('arga a | %argd') + end + + local function assert_fails(cmd, err) + neq(exc_exec(cmd):find(err), nil) + end + + it('test that argidx() works', function() + execute('args a b c') + execute('last') + eq(2, eval('argidx()')) + execute('%argdelete') + eq(0, eval('argidx()')) + + execute('args a b c') + eq(0, eval('argidx()')) + execute('next') + eq(1, eval('argidx()')) + execute('next') + eq(2, eval('argidx()')) + execute('1argdelete') + eq(1, eval('argidx()')) + execute('1argdelete') + eq(0, eval('argidx()')) + execute('1argdelete') + eq(0, eval('argidx()')) + end) + + it('test that argadd() works', function() + execute('%argdelete') + execute('argadd a b c') + eq(0, eval('argidx()')) + + execute('%argdelete') + execute('argadd a') + eq(0, eval('argidx()')) + execute('argadd b c d') + eq(0, eval('argidx()')) + + init_abc() + execute('argadd x') + eq({'a', 'b', 'x', 'c'}, eval('argv()')) + eq(1, eval('argidx()')) + + init_abc() + execute('0argadd x') + eq({'x', 'a', 'b', 'c'}, eval('argv()')) + eq(2, eval('argidx()')) + + init_abc() + execute('1argadd x') + eq({'a', 'x', 'b', 'c'}, eval('argv()')) + eq(2, eval('argidx()')) + + init_abc() + execute('$argadd x') + eq({'a', 'b', 'c', 'x'}, eval('argv()')) + eq(1, eval('argidx()')) + + init_abc() + execute('$argadd x') + execute('+2argadd y') + eq({'a', 'b', 'c', 'x', 'y'}, eval('argv()')) + eq(1, eval('argidx()')) + + execute('%argd') + execute('edit d') + execute('arga') + eq(1, eval('len(argv())')) + eq('d', eval('get(argv(), 0, "")')) + + execute('%argd') + execute('new') + execute('arga') + eq(0, eval('len(argv())')) + end) + + it('test for [count]argument and [count]argdelete commands', function() + reset_arglist() + execute('let save_hidden = &hidden') + execute('set hidden') + execute('let g:buffers = []') + execute('augroup TEST') + execute([[au BufEnter * call add(buffers, expand('%:t'))]]) + execute('augroup END') + + execute('argadd a b c d') + execute('$argu') + execute('$-argu') + execute('-argu') + execute('1argu') + execute('+2argu') + + execute('augroup TEST') + execute('au!') + execute('augroup END') + + eq({'d', 'c', 'b', 'a', 'c'}, eval('g:buffers')) + + execute('redir => result') + execute('ar') + execute('redir END') + eq(1, eval([[result =~# 'a b \[c] d']])) + + execute('.argd') + eq({'a', 'b', 'd'}, eval('argv()')) + + execute('-argd') + eq({'a', 'd'}, eval('argv()')) + + execute('$argd') + eq({'a'}, eval('argv()')) + + execute('1arga c') + execute('1arga b') + execute('$argu') + execute('$arga x') + eq({'a', 'b', 'c', 'x'}, eval('argv()')) + + execute('0arga Y') + eq({'Y', 'a', 'b', 'c', 'x'}, eval('argv()')) + + execute('%argd') + eq({}, eval('argv()')) + + execute('arga a b c d e f') + execute('2,$-argd') + eq({'a', 'f'}, eval('argv()')) + + execute('let &hidden = save_hidden') + + -- Setting the argument list should fail when the current buffer has + -- unsaved changes + execute('%argd') + execute('enew!') + execute('set modified') + assert_fails('args x y z', 'E37:') + execute('args! x y z') + eq({'x', 'y', 'z'}, eval('argv()')) + eq('x', eval('expand("%:t")')) + + execute('%argdelete') + assert_fails('argument', 'E163:') + end) + + it('test for 0argadd and 0argedit', function() + reset_arglist() + + execute('arga a b c d') + execute('2argu') + execute('0arga added') + eq({'added', 'a', 'b', 'c', 'd'}, eval('argv()')) + + execute('%argd') + execute('arga a b c d') + execute('2argu') + execute('0arge edited') + eq({'edited', 'a', 'b', 'c', 'd'}, eval('argv()')) + + execute('2argu') + execute('arga third') + eq({'edited', 'a', 'third', 'b', 'c', 'd'}, eval('argv()')) + end) + + it('test for argc()', function() + reset_arglist() + eq(0, eval('argc()')) + execute('argadd a b') + eq(2, eval('argc()')) + end) + + it('test for arglistid()', function() + reset_arglist() + execute('arga a b') + eq(0, eval('arglistid()')) + execute('split') + execute('arglocal') + eq(1, eval('arglistid()')) + execute('tabnew | tabfirst') + eq(0, eval('arglistid(2)')) + eq(1, eval('arglistid(1, 1)')) + eq(0, eval('arglistid(2, 1)')) + eq(1, eval('arglistid(1, 2)')) + execute('tabonly | only | enew!') + execute('argglobal') + eq(0, eval('arglistid()')) + end) + + it('test for argv()', function() + reset_arglist() + eq({}, eval('argv()')) + eq('', eval('argv(2)')) + execute('argadd a b c d') + eq('c', eval('argv(2)')) + end) + + it('test for :argedit command', function() + reset_arglist() + execute('argedit a') + eq({'a'}, eval('argv()')) + eq('a', eval('expand("%:t")')) + execute('argedit b') + eq({'a', 'b'}, eval('argv()')) + eq('b', eval('expand("%:t")')) + execute('argedit a') + eq({'a', 'b'}, eval('argv()')) + eq('a', eval('expand("%:t")')) + assert_fails('argedit a b', 'E172:') + execute('argedit c') + eq({'a', 'c', 'b'}, eval('argv()')) + execute('0argedit x') + eq({'x', 'a', 'c', 'b'}, eval('argv()')) + execute('enew! | set modified') + assert_fails('argedit y', 'E37:') + execute('argedit! y') + eq({'x', 'y', 'a', 'c', 'b'}, eval('argv()')) + execute('%argd') + end) + + it('test for :argdelete command', function() + reset_arglist() + execute('args aa a aaa b bb') + execute('argdelete a*') + eq({'b', 'bb'}, eval('argv()')) + eq('aa', eval('expand("%:t")')) + execute('last') + execute('argdelete %') + eq({'b'}, eval('argv()')) + assert_fails('argdelete', 'E471:') + assert_fails('1,100argdelete', 'E16:') + execute('%argd') + end) + + it('test for the :next, :prev, :first, :last, :rewind commands', function() + reset_arglist() + execute('args a b c d') + execute('last') + eq(3, eval('argidx()')) + assert_fails('next', 'E165:') + execute('prev') + eq(2, eval('argidx()')) + execute('Next') + eq(1, eval('argidx()')) + execute('first') + eq(0, eval('argidx()')) + assert_fails('prev', 'E164:') + execute('3next') + eq(3, eval('argidx()')) + execute('rewind') + eq(0, eval('argidx()')) + execute('%argd') + end) +end) diff --git a/test/functional/legacy/argument_0count_spec.lua b/test/functional/legacy/argument_0count_spec.lua deleted file mode 100644 index 6e8b60547b..0000000000 --- a/test/functional/legacy/argument_0count_spec.lua +++ /dev/null @@ -1,28 +0,0 @@ --- Tests for :0argadd and :0argedit - -local helpers = require('test.functional.helpers') -local eq, eval, clear, execute = - helpers.eq, helpers.eval, helpers.clear, helpers.execute - -describe('argument_0count', function() - setup(clear) - - it('is working', function() - execute('arga a b c d') - eq({'a', 'b', 'c', 'd'}, eval('argv()')) - execute('2argu') - execute('0arga added') - eq({'added', 'a', 'b', 'c', 'd'}, eval('argv()')) - execute('2argu') - execute('arga third') - eq({'added', 'a', 'third', 'b', 'c', 'd'}, eval('argv()')) - execute('%argd') - execute('arga a b c d') - execute('2argu') - execute('0arge edited') - eq({'edited', 'a', 'b', 'c', 'd'}, eval('argv()')) - execute('2argu') - execute('arga third') - eq({'edited', 'a', 'third', 'b', 'c', 'd'}, eval('argv()')) - end) -end) diff --git a/test/functional/legacy/argument_count_spec.lua b/test/functional/legacy/argument_count_spec.lua deleted file mode 100644 index 182cce9475..0000000000 --- a/test/functional/legacy/argument_count_spec.lua +++ /dev/null @@ -1,47 +0,0 @@ --- Tests for :[count]argument! and :[count]argdelete - -local helpers = require('test.functional.helpers') -local clear, execute, eq, eval = - helpers.clear, helpers.execute, helpers.eq, helpers.eval - -describe('argument_count', function() - setup(clear) - - it('is working', function() - execute('%argd') - execute('argadd a b c d') - eq({'a', 'b', 'c', 'd'}, eval('argv()')) - execute('set hidden') - execute('let buffers = []') - execute('augroup TEST') - execute([[au BufEnter * call add(buffers, expand('%:t'))]]) - execute('augroup END') - execute('$argu') - execute('$-argu') - execute('-argu') - execute('1argu') - execute('+2argu') - execute('augroup TEST') - execute('au!') - execute('augroup END') - eq({'d', 'c', 'b', 'a', 'c'}, eval('buffers')) - execute('.argd') - eq({'a', 'b', 'd'}, eval('argv()')) - execute('-argd') - eq({'a', 'd'}, eval('argv()')) - execute('$argd') - eq({'a'}, eval('argv()')) - execute('1arga c') - execute('1arga b') - execute('$argu') - execute('$arga x') - eq({'a', 'b', 'c', 'x'}, eval('argv()')) - execute('0arga Y') - eq({'Y', 'a', 'b', 'c', 'x'}, eval('argv()')) - execute('%argd') - eq({}, eval('argv()')) - execute('arga a b c d e f') - execute('2,$-argd') - eq({'a', 'f'}, eval('argv()')) - end) -end) diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua index 1ce665360d..ab6be0ecb7 100644 --- a/test/functional/legacy/assert_spec.lua +++ b/test/functional/legacy/assert_spec.lua @@ -141,5 +141,35 @@ describe('assert function:', function() tmpname_two .. " line 1: 'file two'", }) end) + + it('is reset to a list by assert functions', function() + source([[ + let save_verrors = v:errors + let v:['errors'] = {'foo': 3} + call assert_equal('yes', 'no') + let verrors = v:errors + let v:errors = save_verrors + call assert_equal(type([]), type(verrors)) + ]]) + expected_empty() + end) + end) + + -- assert_fails({cmd}, [, {error}]) + describe('assert_fails', function() + it('should change v:errors when error does not match v:errmsg', function() + execute([[call assert_fails('xxx', {})]]) + expected_errors({"Expected {} but got 'E731: using Dictionary as a String'"}) + end) + + it('should not change v:errors when cmd errors', function() + call('assert_fails', 'NonexistentCmd') + expected_empty() + end) + + it('should change v:errors when cmd succeeds', function() + call('assert_fails', 'call empty("")') + expected_errors({'command did not fail: call empty("")'}) + end) end) end) diff --git a/test/functional/legacy/close_count_spec.lua b/test/functional/legacy/close_count_spec.lua new file mode 100644 index 0000000000..ee6b29c618 --- /dev/null +++ b/test/functional/legacy/close_count_spec.lua @@ -0,0 +1,133 @@ +-- Tests for :[count]close! and :[count]hide + +local helpers = require('test.functional.helpers') +local feed, eval, eq, clear, execute = + helpers.feed, helpers.eval, helpers.eq, helpers.clear, helpers.execute + +describe('close_count', function() + setup(clear) + + it('is working', function() + execute('let tests = []') + execute('for i in range(5)') + execute('new') + execute('endfor') + execute('4wincmd w') + execute('close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({6, 5, 4, 2, 1}, eval('buffers')) + execute('1close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({5, 4, 2, 1}, eval('buffers')) + execute('$close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({5, 4, 2}, eval('buffers')) + execute('1wincmd w') + execute('2close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({5, 2}, eval('buffers')) + execute('1wincmd w') + execute('new') + execute('new') + execute('2wincmd w') + execute('-1close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({7, 5, 2}, eval('buffers')) + execute('2wincmd w') + execute('+1close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({7, 5}, eval('buffers')) + execute('only!') + execute('b1') + execute('let tests = []') + execute('for i in range(5)') + execute('new') + execute('endfor') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({13, 12, 11, 10, 9, 1}, eval('buffers')) + execute('4wincmd w') + execute('.hide') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({13, 12, 11, 9, 1}, eval('buffers')) + execute('1hide') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({12, 11, 9, 1}, eval('buffers')) + execute('$hide') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({12, 11, 9}, eval('buffers')) + execute('1wincmd w') + execute('2hide') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({12, 9}, eval('buffers')) + execute('1wincmd w') + execute('new') + execute('new') + execute('3wincmd w') + execute('-hide') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({15, 12, 9}, eval('buffers')) + execute('2wincmd w') + execute('+hide') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({15, 12}, eval('buffers')) + execute('only!') + execute('b1') + execute('let tests = []') + execute('set hidden') + execute('for i in range(5)') + execute('new') + execute('endfor') + execute('1wincmd w') + execute('$ hide') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({20, 19, 18, 17, 16}, eval('buffers')) + execute('$-1 close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({20, 19, 18, 16}, eval('buffers')) + execute('1wincmd w') + execute('.+close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({20, 18, 16}, eval('buffers')) + execute('only!') + execute('b1') + execute('let tests = []') + execute('set hidden') + execute('for i in range(5)') + execute('new') + execute('endfor') + execute('4wincmd w') + feed('<C-W>c<cr>') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({25, 24, 23, 21, 1}, eval('buffers')) + feed('1<C-W>c<cr>') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({24, 23, 21, 1}, eval('buffers')) + feed('9<C-W>c<cr>') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({24, 23, 21}, eval('buffers')) + execute('1wincmd w') + feed('2<C-W>c<cr>') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({24, 21}, eval('buffers')) + end) +end) diff --git a/test/functional/legacy/expand_spec.lua b/test/functional/legacy/expand_spec.lua new file mode 100644 index 0000000000..3da1416885 --- /dev/null +++ b/test/functional/legacy/expand_spec.lua @@ -0,0 +1,72 @@ +-- Test for expanding file names + +local helpers = require('test.functional.helpers') +local eq = helpers.eq +local call = helpers.call +local nvim = helpers.meths +local clear = helpers.clear +local source = helpers.source + +local function expected_empty() + eq({}, nvim.get_vvar('errors')) +end + +describe('expand file name', function() + after_each(function() + helpers.rmdir('Xdir1') + helpers.rmdir('Xdir2') + helpers.rmdir('Xdir3') + helpers.rmdir('Xdir4') + end) + + before_each(function() + clear() + + source([[ + func Test_with_directories() + call mkdir('Xdir1') + call mkdir('Xdir2') + call mkdir('Xdir3') + cd Xdir3 + call mkdir('Xdir4') + cd .. + + split Xdir1/file + call setline(1, ['a', 'b']) + w + w Xdir3/Xdir4/file + close + + next Xdir?/*/file + call assert_equal('Xdir3/Xdir4/file', expand('%')) + next! Xdir?/*/nofile + call assert_equal('Xdir?/*/nofile', expand('%')) + + call delete('Xdir1', 'rf') + call delete('Xdir2', 'rf') + call delete('Xdir3', 'rf') + endfunc + + func Test_with_tilde() + let dir = getcwd() + call mkdir('Xdir ~ dir') + call assert_true(isdirectory('Xdir ~ dir')) + cd Xdir\ ~\ dir + call assert_true(getcwd() =~ 'Xdir \~ dir') + exe 'cd ' . fnameescape(dir) + call delete('Xdir ~ dir', 'd') + call assert_false(isdirectory('Xdir ~ dir')) + endfunc + ]]) + end) + + it('works with directories', function() + call('Test_with_directories') + expected_empty() + end) + + it('works with tilde', function() + call('Test_with_tilde') + expected_empty() + end) +end) diff --git a/test/functional/legacy/file_perm_spec.lua b/test/functional/legacy/file_perm_spec.lua new file mode 100644 index 0000000000..cabeecdc9c --- /dev/null +++ b/test/functional/legacy/file_perm_spec.lua @@ -0,0 +1,42 @@ +-- Test getting and setting file permissions. +require('os') + +local helpers = require('test.functional.helpers') +local clear, call, eq = helpers.clear, helpers.call, helpers.eq +local neq, exc_exec = helpers.neq, helpers.exc_exec + +describe('Test getting and setting file permissions', function() + local tempfile = os.tmpname() + + before_each(function() + os.remove(tempfile) + clear() + end) + + it('file permissions', function() + eq('', call('getfperm', tempfile)) + eq(0, call('setfperm', tempfile, 'r------')) + + call('writefile', {'one'}, tempfile) + eq(9, call('len', call('getfperm', tempfile))) + + eq(1, call('setfperm', tempfile, 'rwx------')) + if helpers.os_name == 'windows' then + eq('rw-rw-rw-', call('getfperm', tempfile)) + else + eq('rwx------', call('getfperm', tempfile)) + end + + eq(1, call('setfperm', tempfile, 'r--r--r--')) + eq('r--r--r--', call('getfperm', tempfile)) + + local err = exc_exec(('call setfperm("%s", "---")'):format(tempfile)) + neq(err:find('E475:'), nil) + + eq(1, call('setfperm', tempfile, 'rwx------')) + end) + + after_each(function() + os.remove(tempfile) + end) +end) diff --git a/test/functional/legacy/function_sort_spec.lua b/test/functional/legacy/function_sort_spec.lua index 9083911021..b274aee94b 100644 --- a/test/functional/legacy/function_sort_spec.lua +++ b/test/functional/legacy/function_sort_spec.lua @@ -2,6 +2,9 @@ local helpers = require('test.functional.helpers') local clear = helpers.clear local eq = helpers.eq local eval = helpers.eval +local execute = helpers.execute +local exc_exec = helpers.exc_exec +local neq = helpers.neq describe('sort', function() before_each(clear) @@ -26,4 +29,25 @@ describe('sort', function() it('numbers compared as float', function() eq({0.28, 3, 13.5}, eval("sort([13.5, 0.28, 3], 'f')")) end) + + it('ability to call sort() from a compare function', function() + execute('func Compare1(a, b) abort') + execute([[call sort(range(3), 'Compare2')]]) + execute('return a:a - a:b') + execute('endfunc') + + execute('func Compare2(a, b) abort') + execute('return a:a - a:b') + execute('endfunc') + eq({1, 3, 5}, eval("sort([3, 1, 5], 'Compare1')")) + end) + + it('default sort', function() + -- docs say omitted, empty or zero argument sorts on string representation + eq({'2', 'A', 'AA', 'a', 1, 3.3}, eval('sort([3.3, 1, "2", "A", "a", "AA"])')) + eq({'2', 'A', 'AA', 'a', 1, 3.3}, eval([[sort([3.3, 1, "2", "A", "a", "AA"], '')]])) + eq({'2', 'A', 'AA', 'a', 1, 3.3}, eval('sort([3.3, 1, "2", "A", "a", "AA"], 0)')) + eq({'2', 'A', 'a', 'AA', 1, 3.3}, eval('sort([3.3, 1, "2", "A", "a", "AA"], 1)')) + neq(exc_exec('call sort([3.3, 1, "2"], 3)'):find('E474:'), nil) + end) end) diff --git a/test/functional/legacy/listlbr_spec.lua b/test/functional/legacy/listlbr_spec.lua new file mode 100644 index 0000000000..6601a922ef --- /dev/null +++ b/test/functional/legacy/listlbr_spec.lua @@ -0,0 +1,195 @@ +-- Test for linebreak and list option (non-utf8) + +local helpers = require('test.functional.helpers') +local feed, insert, source = helpers.feed, helpers.insert, helpers.source +local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect + +describe('listlbr', function() + setup(clear) + + it('is working', function() + insert([[ + dummy text]]) + + execute('set wildchar=^E') + execute('10new') + execute('vsp') + execute('vert resize 20') + execute([[put =\"\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP \"]]) + execute('norm! zt') + execute('set ts=4 sw=4 sts=4 linebreak sbr=+ wrap') + source([[ + fu! ScreenChar(width) + let c='' + for j in range(1,4) + for i in range(1,a:width) + let c.=nr2char(screenchar(j, i)) + endfor + let c.="\n" + endfor + return c + endfu + fu! DoRecordScreen() + wincmd l + $put =printf(\"\n%s\", g:test) + $put =g:line + wincmd p + endfu + ]]) + execute('let g:test="Test 1: set linebreak"') + execute('redraw!') + execute('let line=ScreenChar(winwidth(0))') + execute('call DoRecordScreen()') + + execute('let g:test="Test 2: set linebreak + set list"') + execute('set linebreak list listchars=') + execute('redraw!') + execute('let line=ScreenChar(winwidth(0))') + execute('call DoRecordScreen()') + + execute('let g:test ="Test 3: set linebreak nolist"') + execute('set nolist linebreak') + execute('redraw!') + execute('let line=ScreenChar(winwidth(0))') + execute('call DoRecordScreen()') + + execute('let g:test ="Test 4: set linebreak with tab and 1 line as long as screen: should break!"') + execute('set nolist linebreak ts=8') + execute([[let line="1\t".repeat('a', winwidth(0)-2)]]) + execute('$put =line') + execute('$') + execute('norm! zt') + execute('redraw!') + execute('let line=ScreenChar(winwidth(0))') + execute('call DoRecordScreen()') + execute([[let line="_S_\t bla"]]) + execute('$put =line') + execute('$') + execute('norm! zt') + + execute('let g:test ="Test 5: set linebreak with conceal and set list and tab displayed by different char (line may not be truncated)"') + execute('set cpo&vim list linebreak conceallevel=2 concealcursor=nv listchars=tab:ab') + execute('syn match ConcealVar contained /_/ conceal') + execute('syn match All /.*/ contains=ConcealVar') + execute('let line=ScreenChar(winwidth(0))') + execute('call DoRecordScreen()') + execute('set cpo&vim linebreak') + + execute('let g:test ="Test 6: set linebreak with visual block mode"') + execute('let line="REMOVE: this not"') + execute('$put =g:test') + execute('$put =line') + execute('let line="REMOVE: aaaaaaaaaaaaa"') + execute('$put =line') + execute('1/^REMOVE:') + feed('0<C-V>jf x') + execute('$put') + execute('set cpo&vim linebreak') + + execute('let g:test ="Test 7: set linebreak with visual block mode and v_b_A"') + execute('$put =g:test') + feed('Golong line: <esc>40afoobar <esc>aTARGET at end<esc>') + execute([[exe "norm! $3B\<C-v>eAx\<Esc>"]]) + execute('set cpo&vim linebreak sbr=') + + execute('let g:test ="Test 8: set linebreak with visual char mode and changing block"') + execute('$put =g:test') + feed('Go1111-1111-1111-11-1111-1111-1111<esc>0f-lv3lc2222<esc>bgj.') + + execute('let g:test ="Test 9: using redo after block visual mode"') + execute('$put =g:test') + feed('Go<CR>') + feed('aaa<CR>') + feed('aaa<CR>') + feed('a<ESC>2k<C-V>2j~e.<CR>') + + execute('let g:test ="Test 10: using normal commands after block-visual"') + execute('$put =g:test') + execute('set linebreak') + feed('Go<cr>') + feed('abcd{ef<cr>') + feed('ghijklm<cr>') + feed('no}pqrs<esc>2k0f{<C-V><C-V>c%<esc>') + + execute('let g:test ="Test 11: using block replace mode after wrapping"') + execute('$put =g:test') + execute('set linebreak wrap') + feed('Go<esc>150aa<esc>yypk147|<C-V>jr0<cr>') + + execute('let g:test ="Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$"') + execute('set list listchars=space:_,trail:-,tab:>-,eol:$') + execute('$put =g:test') + execute([[let line="a aaaaaaaaaaaaaaaaaaaaaa\ta "]]) + execute('$put =line') + execute('$') + execute('norm! zt') + execute('redraw!') + execute('let line=ScreenChar(winwidth(0))') + execute('call DoRecordScreen()') + + -- Assert buffer contents. + expect([[ + + abcdef hijklmn pqrstuvwxyz_1060ABCDEFGHIJKLMNOP + + Test 1: set linebreak + abcdef + +hijklmn + +pqrstuvwxyz_1060ABC + +DEFGHIJKLMNOP + + Test 2: set linebreak + set list + ^Iabcdef hijklmn^I + +pqrstuvwxyz_1060ABC + +DEFGHIJKLMNOP + + + Test 3: set linebreak nolist + abcdef + +hijklmn + +pqrstuvwxyz_1060ABC + +DEFGHIJKLMNOP + 1 aaaaaaaaaaaaaaaaaa + + Test 4: set linebreak with tab and 1 line as long as screen: should break! + 1 + +aaaaaaaaaaaaaaaaaa + ~ + ~ + _S_ bla + + Test 5: set linebreak with conceal and set list and tab displayed by different char (line may not be truncated) + Sabbbbbb bla + ~ + ~ + ~ + Test 6: set linebreak with visual block mode + this not + aaaaaaaaaaaaa + REMOVE: + REMOVE: + Test 7: set linebreak with visual block mode and v_b_A + long line: foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar TARGETx at end + Test 8: set linebreak with visual char mode and changing block + 1111-2222-1111-11-1111-2222-1111 + Test 9: using redo after block visual mode + + AaA + AaA + A + Test 10: using normal commands after block-visual + + abcdpqrs + Test 11: using block replace mode after wrapping + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0aaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0aaa + Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$ + a aaaaaaaaaaaaaaaaaaaaaa a + + Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$ + a_ + aaaaaaaaaaaaaaaaaaaa + aa>-----a-$ + ~ ]]) + end) +end) diff --git a/test/functional/legacy/quickfix_spec.lua b/test/functional/legacy/quickfix_spec.lua index 88f86815b3..9c378aef60 100644 --- a/test/functional/legacy/quickfix_spec.lua +++ b/test/functional/legacy/quickfix_spec.lua @@ -2,11 +2,266 @@ local helpers = require('test.functional.helpers') local source, clear = helpers.source, helpers.clear +local eq, nvim, call = helpers.eq, helpers.meths, helpers.call +local eval = helpers.eval +local execute = helpers.execute + +local function expected_empty() + eq({}, nvim.get_vvar('errors')) +end describe('helpgrep', function() - before_each(clear) + before_each(function() + clear() - it('works', function() + source([[ + " Tests for the :clist and :llist commands + function XlistTests(cchar) + let Xlist = a:cchar . 'list' + let Xgetexpr = a:cchar . 'getexpr' + + " With an empty list, command should return error + exe Xgetexpr . ' []' + exe 'silent! ' . Xlist + call assert_true(v:errmsg ==# 'E42: No Errors') + + " Populate the list and then try + exe Xgetexpr . " ['non-error 1', 'Xtestfile1:1:3:Line1', + \ 'non-error 2', 'Xtestfile2:2:2:Line2', + \ 'non-error 3', 'Xtestfile3:3:1:Line3']" + + " List only valid entries + redir => result + exe 'silent ' . Xlist + redir END + let l = split(result, "\n") + call assert_equal([' 2 Xtestfile1:1 col 3: Line1', + \ ' 4 Xtestfile2:2 col 2: Line2', + \ ' 6 Xtestfile3:3 col 1: Line3'], l) + + " List all the entries + redir => result + exe 'silent ' . Xlist . "!" + redir END + let l = split(result, "\n") + call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1', + \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2', + \ ' 5: non-error 3', ' 6 Xtestfile3:3 col 1: Line3'], l) + + " List a range of errors + redir => result + exe 'silent '. Xlist . " 3,6" + redir END + let l = split(result, "\n") + call assert_equal([' 4 Xtestfile2:2 col 2: Line2', + \ ' 6 Xtestfile3:3 col 1: Line3'], l) + + redir => result + exe 'silent ' . Xlist . "! 3,4" + redir END + let l = split(result, "\n") + call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l) + + redir => result + exe 'silent ' . Xlist . " -6,-4" + redir END + let l = split(result, "\n") + call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l) + + redir => result + exe 'silent ' . Xlist . "! -5,-3" + redir END + let l = split(result, "\n") + call assert_equal([' 2 Xtestfile1:1 col 3: Line1', + \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l) + endfunction + + " Tests for the :colder, :cnewer, :lolder and :lnewer commands + " Note that this test assumes that a quickfix/location list is + " already set by the caller + function XageTests(cchar) + let Xolder = a:cchar . 'older' + let Xnewer = a:cchar . 'newer' + let Xgetexpr = a:cchar . 'getexpr' + if a:cchar == 'c' + let Xgetlist = 'getqflist()' + else + let Xgetlist = 'getloclist(0)' + endif + + " Jumping to a non existent list should return error + exe 'silent! ' . Xolder . ' 99' + call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack') + + exe 'silent! ' . Xnewer . ' 99' + call assert_true(v:errmsg ==# 'E381: At top of quickfix stack') + + " Add three quickfix/location lists + exe Xgetexpr . " ['Xtestfile1:1:3:Line1']" + exe Xgetexpr . " ['Xtestfile2:2:2:Line2']" + exe Xgetexpr . " ['Xtestfile3:3:1:Line3']" + + " Go back two lists + exe Xolder + exe 'let l = ' . Xgetlist + call assert_equal('Line2', l[0].text) + + " Go forward two lists + exe Xnewer + exe 'let l = ' . Xgetlist + call assert_equal('Line3', l[0].text) + + " Test for the optional count argument + exe Xolder . ' 2' + exe 'let l = ' . Xgetlist + call assert_equal('Line1', l[0].text) + + exe Xnewer . ' 2' + exe 'let l = ' . Xgetlist + call assert_equal('Line3', l[0].text) + endfunction + + " Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen + " commands + function XwindowTests(cchar) + let Xwindow = a:cchar . 'window' + let Xclose = a:cchar . 'close' + let Xopen = a:cchar . 'open' + let Xgetexpr = a:cchar . 'getexpr' + + " Create a list with no valid entries + exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']" + + " Quickfix/Location window should not open with no valid errors + exe Xwindow + call assert_true(winnr('$') == 1) + + " Create a list with valid entries + exe Xgetexpr . " ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2', + \ 'Xtestfile3:3:1:Line3']" + + " Open the window + exe Xwindow + call assert_true(winnr('$') == 2 && winnr() == 2 && + \ getline('.') ==# 'Xtestfile1|1 col 3| Line1') + + " Close the window + exe Xclose + call assert_true(winnr('$') == 1) + + " Create a list with no valid entries + exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']" + + " Open the window + exe Xopen . ' 5' + call assert_true(winnr('$') == 2 && getline('.') ==# '|| non-error 1' + \ && winheight('.') == 5) + + " Opening the window again, should move the cursor to that window + wincmd t + exe Xopen . ' 7' + call assert_true(winnr('$') == 2 && winnr() == 2 && + \ winheight('.') == 7 && + \ getline('.') ==# '|| non-error 1') + + + " Calling cwindow should close the quickfix window with no valid errors + exe Xwindow + call assert_true(winnr('$') == 1) + endfunction + + " Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile + " commands. + function XfileTests(cchar) + let Xfile = a:cchar . 'file' + let Xgetfile = a:cchar . 'getfile' + let Xaddfile = a:cchar . 'addfile' + if a:cchar == 'c' + let Xgetlist = 'getqflist()' + else + let Xgetlist = 'getloclist(0)' + endif + + call writefile(['Xtestfile1:700:10:Line 700', + \ 'Xtestfile2:800:15:Line 800'], 'Xqftestfile1') + + enew! + exe Xfile . ' Xqftestfile1' + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 2 && + \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' && + \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800') + + " Run cfile/lfile from a modified buffer + enew! + silent! put ='Quickfix' + exe 'silent! ' . Xfile . ' Xqftestfile1' + call assert_true(v:errmsg ==# 'E37: No write since last change (add ! to override)') + + call writefile(['Xtestfile3:900:30:Line 900'], 'Xqftestfile1') + exe Xaddfile . ' Xqftestfile1' + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 3 && + \ l[2].lnum == 900 && l[2].col == 30 && l[2].text ==# 'Line 900') + + call writefile(['Xtestfile1:222:77:Line 222', + \ 'Xtestfile2:333:88:Line 333'], 'Xqftestfile1') + + enew! + exe Xgetfile . ' Xqftestfile1' + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 2 && + \ l[0].lnum == 222 && l[0].col == 77 && l[0].text ==# 'Line 222' && + \ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333') + + call delete('Xqftestfile1') + endfunction + + " Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and + " :lgetbuffer commands. + function XbufferTests(cchar) + let Xbuffer = a:cchar . 'buffer' + let Xgetbuffer = a:cchar . 'getbuffer' + let Xaddbuffer = a:cchar . 'addbuffer' + if a:cchar == 'c' + let Xgetlist = 'getqflist()' + else + let Xgetlist = 'getloclist(0)' + endif + + enew! + silent! call setline(1, ['Xtestfile7:700:10:Line 700', + \ 'Xtestfile8:800:15:Line 800']) + exe Xbuffer . "!" + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 2 && + \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' && + \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800') + + enew! + silent! call setline(1, ['Xtestfile9:900:55:Line 900', + \ 'Xtestfile10:950:66:Line 950']) + exe Xgetbuffer + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 2 && + \ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' && + \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950') + + enew! + silent! call setline(1, ['Xtestfile11:700:20:Line 700', + \ 'Xtestfile12:750:25:Line 750']) + exe Xaddbuffer + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 4 && + \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950' && + \ l[2].lnum == 700 && l[2].col == 20 && l[2].text ==# 'Line 700' && + \ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750') + + endfunction + ]]) + end) + + it('copen/cclose work', function() source([[ helpgrep quickfix copen @@ -14,4 +269,50 @@ describe('helpgrep', function() cclose ]]) end) + + it('clist/llist work', function() + call('XlistTests', 'c') + expected_empty() + call('XlistTests', 'l') + expected_empty() + end) + + it('colder/cnewer and lolder/lnewer work', function() + local list = {{bufnr = 1, lnum = 1}} + call('setqflist', list) + call('XageTests', 'c') + expected_empty() + + call('setloclist', 0, list) + call('XageTests', 'l') + expected_empty() + end) + + it('quickfix/location list window commands work', function() + call('XwindowTests', 'c') + expected_empty() + call('XwindowTests', 'l') + expected_empty() + end) + + it('quickfix/location list file commands work', function() + call('XfileTests', 'c') + expected_empty() + call('XfileTests', 'l') + expected_empty() + end) + + it('quickfix/location list buffer commands work', function() + call('XbufferTests', 'c') + expected_empty() + call('XbufferTests', 'l') + expected_empty() + end) + + it('autocommands triggered by quickfix can get title', function() + execute('au FileType qf let g:foo = get(w:, "quickfix_title", "NONE")') + execute('call setqflist([])') + execute('copen') + eq(':setqflist()', eval('g:foo')) + end) end) diff --git a/test/functional/provider/python_spec.lua b/test/functional/provider/python_spec.lua index da45d6aa00..06fdbef669 100644 --- a/test/functional/provider/python_spec.lua +++ b/test/functional/provider/python_spec.lua @@ -1,12 +1,22 @@ local helpers = require('test.functional.helpers') -local eval, command, feed = helpers.eval, helpers.command, helpers.feed -local eq, clear, insert = helpers.eq, helpers.clear, helpers.insert -local expect, write_file = helpers.expect, helpers.write_file + +local eq = helpers.eq +local neq = helpers.neq +local feed = helpers.feed +local clear = helpers.clear +local funcs = helpers.funcs +local meths = helpers.meths +local insert = helpers.insert +local expect = helpers.expect +local command = helpers.command +local exc_exec = helpers.exc_exec +local write_file = helpers.write_file +local curbufmeths = helpers.curbufmeths do clear() command('let [g:interp, g:errors] = provider#pythonx#Detect(2)') - local errors = eval('g:errors') + local errors = meths.get_var('errors') if errors ~= '' then pending( 'Python 2 (or the Python 2 neovim module) is broken or missing:\n' .. errors, @@ -15,49 +25,58 @@ do end end -describe('python commands and functions', function() - before_each(function() - clear() - command('python import vim') - end) +before_each(function() + clear() + command('python import vim') +end) - it('feature test', function() - eq(1, eval('has("python")')) +describe('python feature test', function() + it('works', function() + eq(1, funcs.has('python')) end) +end) - it('python_execute', function() +describe(':python command', function() + it('works with a line', function() command('python vim.vars["set_by_python"] = [100, 0]') - eq({100, 0}, eval('g:set_by_python')) + eq({100, 0}, meths.get_var('set_by_python')) end) - it('python_execute with nested commands', function() + -- TODO(ZyX-I): works with << EOF + -- TODO(ZyX-I): works with execute 'python' line1."\n".line2."\n"… + + it('supports nesting', function() command([[python vim.command('python vim.command("python vim.command(\'let set_by_nested_python = 555\')")')]]) - eq(555, eval('g:set_by_nested_python')) + eq(555, meths.get_var('set_by_nested_python')) end) - it('python_execute with range', function() + it('supports range', function() insert([[ line1 line2 line3 line4]]) feed('ggjvj:python vim.vars["range"] = vim.current.range[:]<CR>') - eq({'line2', 'line3'}, eval('g:range')) + eq({'line2', 'line3'}, meths.get_var('range')) end) +end) - it('pyfile', function() +describe(':pyfile command', function() + it('works', function() local fname = 'pyfile.py' write_file(fname, 'vim.command("let set_by_pyfile = 123")') command('pyfile pyfile.py') - eq(123, eval('g:set_by_pyfile')) + eq(123, meths.get_var('set_by_pyfile')) os.remove(fname) end) +end) - it('pydo', function() +describe(':pydo command', function() + it('works', function() -- :pydo 42 returns None for all lines, -- the buffer should not be changed command('normal :pydo 42') - eq(0, eval('&mod')) + eq(false, curbufmeths.get_option('modified')) -- insert some text insert('abc\ndef\nghi') expect([[ @@ -71,8 +90,25 @@ describe('python commands and functions', function() 2 ghi]]) end) +end) + +describe('pyeval()', function() + it('works', function() + eq({1, 2, {['key'] = 'val'}}, funcs.pyeval('[1, 2, {"key": "val"}]')) + end) + + it('errors out when given non-string', function() + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(10)')) + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:_null_dict)')) + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:_null_list)')) + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(0.0)')) + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(function("tr"))')) + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:true)')) + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:false)')) + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:null)')) + end) - it('pyeval', function() - eq({1, 2, {['key'] = 'val'}}, eval([[pyeval('[1, 2, {"key": "val"}]')]])) + it('accepts NULL string', function() + neq(0, exc_exec('call pyeval($XXX_NONEXISTENT_VAR_XXX)')) end) end) diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index 0229b8bbf7..85fca4d7ca 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -302,6 +302,47 @@ describe('Default highlight groups', function() {1:-- INSERT --} | ]], {[1] = {foreground = Screen.colors.Red, background = Screen.colors.Green}}) end) + it('can be cleared by assigning NONE', function() + execute('syn keyword TmpKeyword neovim') + execute('hi link TmpKeyword ErrorMsg') + insert('neovim') + screen:expect([[ + {1:neovi^m} | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + | + ]], { + [1] = {foreground = Screen.colors.White, background = Screen.colors.Red} + }) + execute("hi ErrorMsg term=NONE cterm=NONE ctermfg=NONE ctermbg=NONE" + .. " gui=NONE guifg=NONE guibg=NONE guisp=NONE") + screen:expect([[ + neovi^m | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + | + ]], {}) + end) end) describe('guisp (special/undercurl)', function() diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 6372cbe081..99b85caf10 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -290,6 +290,10 @@ If everything else fails, use Screen:redraw_debug to help investigate what is end end +function Screen:sleep(ms) + pcall(function() self:wait(function() return "error" end, ms) end) +end + function Screen:_redraw(updates) for _, update in ipairs(updates) do -- print('--') @@ -501,7 +505,7 @@ end function Screen:snapshot_util(attrs, ignore) -- util to generate screen test - pcall(function() self:wait(function() return "error" end, 250) end) + self:sleep(250) self:print_snapshot(attrs, ignore) end diff --git a/test/unit/os/fs_spec.lua b/test/unit/os/fs_spec.lua index 71b5e7f576..857a5001f1 100644 --- a/test/unit/os/fs_spec.lua +++ b/test/unit/os/fs_spec.lua @@ -14,6 +14,8 @@ local to_cstr = helpers.to_cstr local OK = helpers.OK local FAIL = helpers.FAIL local NULL = helpers.NULL +local NODE_NORMAL = 0 +local NODE_WRITABLE = 1 cimport('unistd.h') cimport('./src/nvim/os/shell.h') @@ -357,15 +359,12 @@ describe('fs function', function() local function os_file_exists(filename) return fs.os_file_exists((to_cstr(filename))) end - local function os_rename(path, new_path) return fs.os_rename((to_cstr(path)), (to_cstr(new_path))) end - local function os_remove(path) return fs.os_remove((to_cstr(path))) end - local function os_open(path, flags, mode) return fs.os_open((to_cstr(path)), flags, mode) end @@ -484,6 +483,20 @@ describe('fs function', function() assert.is_true(0 <= (os_open(existing_file, ffi.C.kO_RDWR, 0))) end) end) + + describe('os_nodetype', function() + before_each(function() + os.remove('non-existing-file') + end) + + it('returns NODE_NORMAL for non-existing file', function() + eq(NODE_NORMAL, fs.os_nodetype(to_cstr('non-existing-file'))) + end) + + it('returns NODE_WRITABLE for /dev/stderr', function() + eq(NODE_WRITABLE, fs.os_nodetype(to_cstr('/dev/stderr'))) + end) + end) end) describe('folder operations', function() diff --git a/test/unit/os/shell_spec.lua b/test/unit/os/shell_spec.lua index 93103e4e8c..906f950308 100644 --- a/test/unit/os/shell_spec.lua +++ b/test/unit/os/shell_spec.lua @@ -30,10 +30,6 @@ describe('shell functions', function() cimported.p_shcf = to_cstr('-c') end) - teardown(function() - cimported.event_teardown() - end) - local function shell_build_argv(cmd, extra_args) local res = cimported.shell_build_argv( cmd and to_cstr(cmd), diff --git a/test/unit/strings_spec.lua b/test/unit/strings_spec.lua index e935d2af6a..0034670ee8 100644 --- a/test/unit/strings_spec.lua +++ b/test/unit/strings_spec.lua @@ -8,6 +8,38 @@ local to_cstr = helpers.to_cstr local strings = cimport('stdlib.h', './src/nvim/strings.h', './src/nvim/memory.h') +describe('vim_strsave_escaped()', function() + local vim_strsave_escaped = function(s, chars) + local res = strings.vim_strsave_escaped(to_cstr(s), to_cstr(chars)) + local ret = ffi.string(res) + + -- Explicitly free memory so we are sure it is allocated: if it was not it + -- will crash. + strings.xfree(res) + return ret + end + + it('precedes by a backslash all chars from second argument', function() + eq([[\a\b\c\d]], vim_strsave_escaped('abcd','abcd')) + end) + + it('precedes by a backslash chars only from second argument', function() + eq([[\a\bcd]], vim_strsave_escaped('abcd','ab')) + end) + + it('returns a copy of passed string if second argument is empty', function() + eq('text \n text', vim_strsave_escaped('text \n text','')) + end) + + it('returns an empty string if first argument is empty string', function() + eq('', vim_strsave_escaped('','\r')) + end) + + it('returns a copy of passed string if it does not contain chars from 2nd argument', function() + eq('some text', vim_strsave_escaped('some text', 'a')) + end) +end) + describe('vim_strnsave_unquoted()', function() local vim_strnsave_unquoted = function(s, len) local res = strings.vim_strnsave_unquoted(to_cstr(s), len or #s) diff --git a/third-party/cmake/BuildLuarocks.cmake b/third-party/cmake/BuildLuarocks.cmake index 1662f89b24..069c94ea2e 100644 --- a/third-party/cmake/BuildLuarocks.cmake +++ b/third-party/cmake/BuildLuarocks.cmake @@ -114,6 +114,15 @@ add_custom_target(lpeg list(APPEND THIRD_PARTY_DEPS lpeg) +add_custom_command(OUTPUT ${HOSTDEPS_LIB_DIR}/luarocks/rocks/inspect + COMMAND ${LUAROCKS_BINARY} + ARGS build inspect ${LUAROCKS_BUILDARGS} + DEPENDS mpack) +add_custom_target(inspect + DEPENDS ${HOSTDEPS_LIB_DIR}/luarocks/rocks/inspect) + +list(APPEND THIRD_PARTY_DEPS inspect) + if(USE_BUNDLED_BUSTED) add_custom_command(OUTPUT ${HOSTDEPS_BIN_DIR}/busted COMMAND ${LUAROCKS_BINARY} |