changeset 33014:5c8ed31be901

runtime: Distribute the editorconfig with vim (#12902) Commit: https://github.com/vim/vim/commit/e5e04306bf02aa4ad488558dd593cf5c3b72f9b7 Author: Christian Brabandt <cb@256bit.org> Date: Sun Aug 27 17:52:18 2023 +0100 runtime: Distribute the editorconfig with vim (https://github.com/vim/vim/issues/12902) This is the editorconfig-vim plugin Commit e014708e917b457e8f6c57f357d55dd3826880d4 from https://github.com/editorconfig/editorconfig-vim closes: #2286 related: https://github.com/editorconfig/editorconfig-vim/issues/223 Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Sun, 27 Aug 2023 19:00:09 +0200
parents 9cfd5f9fed6d
children 172f80704b05
files runtime/pack/dist/opt/editorconfig/.appveyor.yml runtime/pack/dist/opt/editorconfig/.editorconfig runtime/pack/dist/opt/editorconfig/.gitignore runtime/pack/dist/opt/editorconfig/.gitmodules runtime/pack/dist/opt/editorconfig/.travis.yml runtime/pack/dist/opt/editorconfig/CONTRIBUTORS runtime/pack/dist/opt/editorconfig/LICENSE runtime/pack/dist/opt/editorconfig/LICENSE.PSF runtime/pack/dist/opt/editorconfig/README.md runtime/pack/dist/opt/editorconfig/autoload/editorconfig.vim runtime/pack/dist/opt/editorconfig/autoload/editorconfig_core.vim runtime/pack/dist/opt/editorconfig/autoload/editorconfig_core/fnmatch.vim runtime/pack/dist/opt/editorconfig/autoload/editorconfig_core/handler.vim runtime/pack/dist/opt/editorconfig/autoload/editorconfig_core/ini.vim runtime/pack/dist/opt/editorconfig/autoload/editorconfig_core/util.vim runtime/pack/dist/opt/editorconfig/doc/editorconfig.txt runtime/pack/dist/opt/editorconfig/ftdetect/editorconfig.vim runtime/pack/dist/opt/editorconfig/mkzip.sh runtime/pack/dist/opt/editorconfig/plugin/editorconfig.vim runtime/pack/dist/opt/editorconfig/tests/core/CMakeLists.txt runtime/pack/dist/opt/editorconfig/tests/core/CTestCustom.cmake runtime/pack/dist/opt/editorconfig/tests/core/ecvbslib.vbs runtime/pack/dist/opt/editorconfig/tests/core/ecvimlib.ps1 runtime/pack/dist/opt/editorconfig/tests/core/editorconfig runtime/pack/dist/opt/editorconfig/tests/core/editorconfig.bat runtime/pack/dist/opt/editorconfig/tests/core/editorconfig1.vbs runtime/pack/dist/opt/editorconfig/tests/core/editorconfig2.ps1 runtime/pack/dist/opt/editorconfig/tests/fetch-vim.bat runtime/pack/dist/opt/editorconfig/tests/fetch-vim.sh runtime/pack/dist/opt/editorconfig/tests/plugin/.gitignore runtime/pack/dist/opt/editorconfig/tests/plugin/Gemfile runtime/pack/dist/opt/editorconfig/tests/plugin/Gemfile.lock runtime/pack/dist/opt/editorconfig/tests/plugin/Rakefile runtime/pack/dist/opt/editorconfig/tests/plugin/spec/.editorconfig runtime/pack/dist/opt/editorconfig/tests/plugin/spec/editorconfig_spec.rb runtime/pack/dist/opt/editorconfig/tests/travis-test.sh
diffstat 36 files changed, 3681 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/.appveyor.yml
@@ -0,0 +1,105 @@
+# appveyor.yml for editorconfig-vim.  Currently only tests the core.
+# Modified from https://github.com/ppalaga/ec4j/commit/1c849658fb189cd95bc41af95acd43b4f0d75a48
+#
+# Copyright (c) 2017--2019 Angelo Zerr and other contributors as
+# indicated by the @author tags.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# @author Chris White (cxw42) - Adapted to editorconfig-vim
+
+# === When to build ===
+# See https://www.appveyor.com/docs/how-to/filtering-commits/
+
+skip_commits:
+  message: /\[minor\]/
+  files:
+    - '**/*.md'
+
+# === Build matrix ===
+
+# Win is default; Ubuntu is override.  See
+# https://www.appveyor.com/blog/2018/04/25/specialized-build-matrix-configuration-in-appveyor/
+image:
+  - Visual Studio 2013
+  - Ubuntu1604
+
+# === How to build ===
+
+cache:
+    - C:\vim -> .appveyor.yml, tests\fetch-vim.bat
+
+environment:
+  VIM_EXE: C:\vim\vim\vim80\vim.exe
+
+for:
+  # Don't run the Windows build if the commit message includes "[ci-linux]"
+  -
+    matrix:
+      only:
+        - image: Visual Studio 2013
+    skip_commits:
+      message: /\[ci-linux\]/
+
+  # Platform-specific configuration for Ubuntu
+  -
+    matrix:
+      only:
+        - image: Ubuntu1604
+    # $APPVEYOR_BUILD_FOLDER isn't expanded in the environment section
+    # here, so I can't set $VIM_EXE the way I want to.  Instead,
+    # I set $VIM_EXE in the sh-specific install steps below.
+    environment:
+      VIM_EXE: UNDEFINED
+    cache:
+      - $APPVEYOR_BUILD_FOLDER/vim -> .appveyor.yml, tests/fetch-vim.sh
+
+    # Plus, don't run Ubuntu if the commit message includes [ci-win]
+    skip_commits:
+      message: /\[ci-win\]/
+
+install:
+  # Ubuntu-specific setup.  These carry forward to the build_script.
+  - sh: export VIM_EXE="$APPVEYOR_BUILD_FOLDER/vim/bin/vim"
+  - sh: export PATH="$PATH":$APPVEYOR_BUILD_FOLDER/vim/bin
+  - sh: echo "$VIM_EXE , $PATH"
+
+  # Cross-platform - test the core
+  - cmake --version
+  - git submodule update --init --recursive
+  - cmd: tests\fetch-vim
+  - sh: tests/fetch-vim.sh
+
+build_script:
+  # Build the core tests
+  - cd tests
+  - cd core
+  - mkdir build
+  - cd build
+  - cmake ..
+
+# Note on multicore testing:
+# Two cores are available per https://help.appveyor.com/discussions/questions/11179-how-many-cores-and-threads-can-be-used-in-free-appveyor-build .
+# However, using -j2 seems to make each job take much longer.
+
+test_script:
+  # Run the core tests
+  - ctest . --output-on-failure -C Debug
+
+  # CTestCustom specifies skipping some tests on Windows.
+  - cmd: echo "Reminder - skipped some tests"
+
+on_failure:
+  - echo "failed"
+  - cmd: type tests\core\build\Testing\Temporary\LastTest.log
+  - sh: cat tests/core/build/Testing/Temporary/LastTest.log
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/.editorconfig
@@ -0,0 +1,27 @@
+root = true
+
+[*]
+end_of_line = lf
+charset = utf-8
+max_line_length = 80
+
+[*.{vim,sh}]
+indent_style = space
+indent_size = 4
+insert_final_newline = true
+trim_trailing_whitespace = true
+max_line_length = 80
+
+[*.rb]
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+max_line_length = 120
+
+[*.yml]
+indent_style = space
+indent_size = 2
+
+[*.{bat,vbs,ps1}]
+end_of_line = CRLF
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/.gitignore
@@ -0,0 +1,8 @@
+tags
+tests/**/build
+tests/**/.bundle
+
+# Editor backup files
+*.swp
+*~
+~*
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "plugin_tests"]
+	path = tests/plugin/spec/plugin_tests
+	url = https://github.com/editorconfig/editorconfig-plugin-tests.git
+[submodule "core_tests"]
+	path = tests/core/tests
+	url = https://github.com/editorconfig/editorconfig-core-test.git
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/.travis.yml
@@ -0,0 +1,30 @@
+# Make sure xvfb works - https://docs.travis-ci.com/user/gui-and-headless-browsers/#using-xvfb-directly
+dist: trusty
+
+matrix:
+  include:
+    - name: "plugin"
+      env: TEST_WHICH=plugin
+      language: ruby
+      rvm:
+        - 2.2.4
+      gemfile: tests/plugin/Gemfile
+    - name: "core"
+      env: TEST_WHICH=core
+
+addons:
+  apt:
+    packages:
+      - vim-gtk
+
+before_script:
+  - "export DISPLAY=:99.0"
+  - "sh -e /etc/init.d/xvfb start"
+
+script:
+  ./tests/travis-test.sh
+
+notifications:
+  email:
+    on_success: change
+    on_failure: always
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/CONTRIBUTORS
@@ -0,0 +1,6 @@
+Contributors to the EditorConfig Vim Plugin:
+
+Hong Xu
+Trey Hunner
+Kent Frazier
+Chris White
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/LICENSE
@@ -0,0 +1,26 @@
+Unless otherwise stated, all files are distributed under the Simplified BSD
+license included below.
+
+Copyright (c) 2011-2019 EditorConfig Team
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
new file mode 100755
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/LICENSE.PSF
@@ -0,0 +1,53 @@
+Some code in editorconfig-vim is derived from code licensed under the
+PSF license.  The following is the text of that license, retrieved 2019-05-05
+from https://docs.python.org/2.6/license.html#terms-and-conditions-for-accessing-or-otherwise-using-python
+
+PSF LICENSE AGREEMENT FOR PYTHON 2.6.9
+
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+(``PSF''), and the Individual or Organization (``Licensee'') accessing and
+otherwise using Python 2.6.9 software in source or binary form and its
+associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python 2.6.9
+alone or in any derivative version, provided, however, that PSF's
+License Agreement and PSF's notice of copyright, i.e., ``Copyright (c)
+2001-2010 Python Software Foundation; All Rights Reserved'' are
+retained in Python 2.6.9 alone or in any derivative version prepared
+by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python 2.6.9 or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python 2.6.9.
+
+4. PSF is making Python 2.6.9 available to Licensee on an ``AS IS''
+basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
+BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY
+REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY
+PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.6.9 WILL NOT INFRINGE
+ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+2.6.9 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.6.9,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between PSF and
+Licensee. This License Agreement does not grant permission to use PSF
+trademarks or trade name in a trademark sense to endorse or promote
+products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python 2.6.9, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
+# vi: set ft=:
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/README.md
@@ -0,0 +1,148 @@
+# EditorConfig Vim Plugin
+
+[![Travis Build Status](https://img.shields.io/travis/cxw42/editorconfig-vim.svg?logo=travis)](https://travis-ci.org/editorconfig/editorconfig-vim)
+[![Appveyor Build Status](https://img.shields.io/appveyor/ci/cxw42/editorconfig-vim.svg?logo=appveyor)](https://ci.appveyor.com/project/cxw42/editorconfig-vim)
+
+This is an [EditorConfig][] plugin for Vim. This plugin can be found on both
+[GitHub][] and [Vim online][].
+
+## Installation
+
+To install this plugin, you can use one of the following ways:
+
+### Install with the archive
+
+Download the [archive][] and extract it into your Vim runtime directory
+(`~/.vim` on UNIX/Linux and `$VIM_INSTALLATION_FOLDER\vimfiles` on windows).
+You should have 4 sub-directories in this runtime directory now: "autoload",
+"doc", "ftdetect" and "plugin".
+
+### Install as Vim8 plugin
+
+Install as a Vim 8 plugin. Note `local` can be any name, but some path
+element must be present. On Windows, instead of `~/.vim` use
+`$VIM_INSTALLATION_FOLDER\vimfiles`.
+```shell
+mkdir -p ~/.vim/pack/local/start
+cd ~/.vim/pack/local/start
+git clone https://github.com/editorconfig/editorconfig-vim.git
+```
+
+### Install with [pathogen][]
+
+Use pathogen (the git repository of this plugin is
+https://github.com/editorconfig/editorconfig-vim.git)
+
+### Install with [Vundle][]
+
+Use Vundle by adding to your `.vimrc` Vundle plugins section:
+
+```viml
+Plugin 'editorconfig/editorconfig-vim'
+```
+
+Then call `:PluginInstall`.
+
+### Install with [vim-plug][]
+
+Use vim-plug by adding to your `.vimrc` in your plugin section:
+
+```viml
+Plug 'editorconfig/editorconfig-vim'
+```
+
+Source your `.vimrc` by calling `:source $MYVIMRC`.
+
+Then call `:PlugInstall`.
+
+### No external editorconfig core library is required
+
+Previous versions of this plugin also required a Python "core".
+The core included the code to parse `.editorconfig` files.
+This plugin **includes** the core, so you don't need to download the
+core separately.
+
+## Supported properties
+
+The EditorConfig Vim plugin supports the following EditorConfig [properties][]:
+
+* `indent_style`
+* `indent_size`
+* `tab_width`
+* `end_of_line`
+* `charset`
+* `insert_final_newline` (Feature `+fixendofline`, available on Vim 7.4.785+,
+  or [PreserveNoEOL][] is required for this property)
+* `trim_trailing_whitespace`
+* `max_line_length`
+* `root` (only used by EditorConfig core)
+
+## Selected Options
+
+The supported options are documented in [editorconfig.txt][]
+and can be viewed by executing the following: `:help editorconfig`. You may
+need to execute `:helptags ALL` so that Vim is aware of editorconfig.txt.
+
+### Excluded patterns
+
+To ensure that this plugin works well with [Tim Pope's fugitive][], use the
+following patterns array:
+
+```viml
+let g:EditorConfig_exclude_patterns = ['fugitive://.*']
+```
+
+If you wanted to avoid loading EditorConfig for any remote files over ssh:
+
+```viml
+let g:EditorConfig_exclude_patterns = ['scp://.*']
+```
+
+Of course these two items could be combined into the following:
+
+```viml
+let g:EditorConfig_exclude_patterns = ['fugitive://.*', 'scp://.*']
+```
+
+### Disable for a specific filetype
+
+You can disable this plugin for a specific buffer by setting
+`b:EditorConfig_disable`.  Therefore, you can disable the
+plugin for all buffers of a specific filetype. For example, to disable
+EditorConfig for all git commit messages (filetype `gitcommit`):
+
+```viml
+au FileType gitcommit let b:EditorConfig_disable = 1
+```
+
+### Disable rules
+
+In very rare cases,
+you might need to override some project-specific EditorConfig rules in global
+or local vimrc in some cases, e.g., to resolve conflicts of trailing whitespace
+trimming and buffer autosaving.  This is not recommended, but you can:
+
+```viml
+let g:EditorConfig_disable_rules = ['trim_trailing_whitespace']
+```
+
+You are able to disable any supported EditorConfig properties.
+
+## Bugs and Feature Requests
+
+Feel free to submit bugs, feature requests, and other issues to the
+[issue tracker][]. Be sure you have read the [contribution guidelines][]!
+
+[EditorConfig]: http://editorconfig.org
+[GitHub]: https://github.com/editorconfig/editorconfig-vim
+[PreserveNoEOL]: http://www.vim.org/scripts/script.php?script_id=4550
+[Tim Pope's fugitive]: https://github.com/tpope/vim-fugitive
+[Vim online]: http://www.vim.org/scripts/script.php?script_id=3934
+[Vundle]: https://github.com/gmarik/Vundle.vim
+[archive]: https://github.com/editorconfig/editorconfig-vim/archive/master.zip
+[contribution guidelines]: https://github.com/editorconfig/editorconfig/blob/master/CONTRIBUTING.md#submitting-an-issue
+[issue tracker]: https://github.com/editorconfig/editorconfig-vim/issues
+[pathogen]: https://github.com/tpope/vim-pathogen
+[properties]: http://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties
+[editorconfig.txt]: https://github.com/editorconfig/editorconfig-vim/blob/master/doc/editorconfig.txt
+[vim-plug]: https://github.com/junegunn/vim-plug
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/autoload/editorconfig.vim
@@ -0,0 +1,60 @@
+" autoload/editorconfig.vim: EditorConfig native Vimscript plugin
+" Copyright (c) 2011-2019 EditorConfig Team
+" All rights reserved.
+"
+" Redistribution and use in source and binary forms, with or without
+" modification, are permitted provided that the following conditions are met:
+"
+" 1. Redistributions of source code must retain the above copyright notice,
+"    this list of conditions and the following disclaimer.
+" 2. Redistributions in binary form must reproduce the above copyright notice,
+"    this list of conditions and the following disclaimer in the documentation
+"    and/or other materials provided with the distribution.
+"
+" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+" POSSIBILITY OF SUCH DAMAGE.
+"
+
+if v:version < 700
+    finish
+endif
+
+let s:saved_cpo = &cpo
+set cpo&vim
+
+" {{{1 variables
+let s:hook_list = []
+
+function! editorconfig#AddNewHook(func) " {{{1
+    " Add a new hook
+
+    call add(s:hook_list, a:func)
+endfunction
+
+function! editorconfig#ApplyHooks(config) abort " {{{1
+    " apply hooks
+
+    for Hook in s:hook_list
+        let l:hook_ret = Hook(a:config)
+
+        if type(l:hook_ret) != type(0) && l:hook_ret != 0
+            " TODO print some debug info here
+        endif
+    endfor
+endfunction
+
+" }}}
+
+let &cpo = s:saved_cpo
+unlet! s:saved_cpo
+
+" vim: fdm=marker fdc=3
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/autoload/editorconfig_core.vim
@@ -0,0 +1,147 @@
+" autoload/editorconfig_core.vim: top-level functions for
+" editorconfig-core-vimscript and editorconfig-vim.
+
+" Copyright (c) 2018-2020 EditorConfig Team, including Chris White {{{1
+" All rights reserved.
+"
+" Redistribution and use in source and binary forms, with or without
+" modification, are permitted provided that the following conditions are met:
+"
+" 1. Redistributions of source code must retain the above copyright notice,
+"    this list of conditions and the following disclaimer.
+" 2. Redistributions in binary form must reproduce the above copyright notice,
+"    this list of conditions and the following disclaimer in the documentation
+"    and/or other materials provided with the distribution.
+"
+" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+" POSSIBILITY OF SUCH DAMAGE. }}}1
+
+let s:saved_cpo = &cpo
+set cpo&vim
+
+" Variables {{{1
+
+" Note: we create this variable in every script that accesses it.  Normally, I
+" would put this in plugin/editorconfig.vim.  However, in some of my tests,
+" the command-line testing environment did not load plugin/* in the normal
+" way.  Therefore, I do the check everywhere so I don't have to special-case
+" the command line.
+
+if !exists('g:editorconfig_core_vimscript_debug')
+    let g:editorconfig_core_vimscript_debug = 0
+endif
+" }}}1
+
+" The latest version of the specification that we support.
+" See discussion at https://github.com/editorconfig/editorconfig/issues/395
+function! editorconfig_core#version()
+    return [0,13,0]
+endfunction
+
+" === CLI =============================================================== {{{1
+
+" For use from the command line.  Output settings for in_name to
+" the buffer named out_name.  If an optional argument is provided, it is the
+" name of the config file to use (default '.editorconfig').
+" TODO support multiple files
+"
+" filename (if any)
+" @param names  {Dictionary}    The names of the files to use for this run
+"   - output    [required]  Where the editorconfig settings should be written
+"   - target    [required]  A string or list of strings to process.  Each
+"                           must be a full path.
+"   - dump      [optional]  If present, write debug info to this file
+" @param job    {Dictionary}    What to do - same format as the input of
+"                               editorconfig_core#handler#get_configurations(),
+"                               except without the target member.
+
+function! editorconfig_core#currbuf_cli(names, job) " out_name, in_name, ...
+    let l:output = []
+
+    " Preprocess the job
+    let l:job = deepcopy(a:job)
+
+    if has_key(l:job, 'version')    " string to list
+        let l:ver = split(editorconfig_core#util#strip(l:job.version), '\v\.')
+        for l:idx in range(len(l:ver))
+            let l:ver[l:idx] = str2nr(l:ver[l:idx])
+        endfor
+
+        let l:job.version = l:ver
+    endif
+
+    " TODO provide version output from here instead of the shell script
+"    if string(a:names) ==? 'version'
+"        return
+"    endif
+"
+    if type(a:names) != type({}) || type(a:job) != type({})
+        throw 'Need two Dictionary arguments'
+    endif
+
+    if has_key(a:names, 'dump')
+        execute 'redir! > ' . fnameescape(a:names.dump)
+        echom 'Names: ' . string(a:names)
+        echom 'Job: ' . string(l:job)
+        let g:editorconfig_core_vimscript_debug = 1
+    endif
+
+    if type(a:names['target']) == type([])
+        let l:targets = a:names.target
+    else
+        let l:targets = [a:names.target]
+    endif
+
+    for l:target in l:targets
+
+        " Pre-process quoting weirdness so we are more flexible in the face
+        " of CMake+CTest+BAT+Powershell quoting.
+
+        " Permit wrapping in double-quotes
+        let l:target = substitute(l:target, '\v^"(.*)"$', '\1', '')
+
+        " Permit empty ('') entries in l:targets
+        if strlen(l:target)<1
+            continue
+        endif
+
+        if has_key(a:names, 'dump')
+            echom 'Trying: ' . string(l:target)
+        endif
+
+        let l:job.target = l:target
+        let l:options = editorconfig_core#handler#get_configurations(l:job)
+
+        if has_key(a:names, 'dump')
+            echom 'editorconfig_core#currbuf_cli result: ' . string(l:options)
+        endif
+
+        if len(l:targets) > 1
+            let l:output += [ '[' . l:target . ']' ]
+        endif
+
+        for [ l:key, l:value ] in items(l:options)
+            let l:output += [ l:key . '=' . l:value ]
+        endfor
+
+    endfor "foreach target
+
+    " Write the output file
+    call writefile(l:output, a:names.output)
+endfunction "editorconfig_core#currbuf_cli
+
+" }}}1
+
+let &cpo = s:saved_cpo
+unlet! s:saved_cpo
+
+" vi: set fdm=marker fo-=ro:
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/autoload/editorconfig_core/fnmatch.vim
@@ -0,0 +1,467 @@
+" autoload/editorconfig_core/fnmatch.vim: Globbing for
+" editorconfig-vim.  Ported from the Python core's fnmatch.py.
+
+" Copyright (c) 2012-2019 EditorConfig Team {{{1
+" All rights reserved.
+"
+" Redistribution and use in source and binary forms, with or without
+" modification, are permitted provided that the following conditions are met:
+"
+" 1. Redistributions of source code must retain the above copyright notice,
+"    this list of conditions and the following disclaimer.
+" 2. Redistributions in binary form must reproduce the above copyright notice,
+"    this list of conditions and the following disclaimer in the documentation
+"    and/or other materials provided with the distribution.
+"
+" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+" POSSIBILITY OF SUCH DAMAGE. }}}1
+
+"Filename matching with shell patterns.
+"
+"fnmatch(FILENAME, PATH, PATTERN) matches according to the local convention.
+"fnmatchcase(FILENAME, PATH, PATTERN) always takes case in account.
+"
+"The functions operate by translating the pattern into a regular
+"expression.  They cache the compiled regular expressions for speed.
+"
+"The function translate(PATTERN) returns a regular expression
+"corresponding to PATTERN.  (It does not compile it.)
+
+let s:saved_cpo = &cpo
+set cpo&vim
+
+" variables {{{1
+if !exists('g:editorconfig_core_vimscript_debug')
+    let g:editorconfig_core_vimscript_debug = 0
+endif
+" }}}1
+" === Regexes =========================================================== {{{1
+let s:LEFT_BRACE = '\v[\\]@8<!\{'
+" 8 is an arbitrary byte-count limit to the lookbehind (micro-optimization)
+"LEFT_BRACE = re.compile(
+"    r"""
+"
+"    (?<! \\ ) # Not preceded by "\"
+"
+"    \{                  # "{"
+"
+"    """, re.VERBOSE
+")
+
+let s:RIGHT_BRACE = '\v[\\]@8<!\}'
+" 8 is an arbitrary byte-count limit to the lookbehind (micro-optimization)
+"RIGHT_BRACE = re.compile(
+"    r"""
+"
+"    (?<! \\ ) # Not preceded by "\"
+"
+"    \}                  # "}"
+"
+"    """, re.VERBOSE
+")
+
+let s:NUMERIC_RANGE = '\v([+-]?\d+)' . '\.\.' . '([+-]?\d+)'
+"NUMERIC_RANGE = re.compile(
+"    r"""
+"    (               # Capture a number
+"        [+-] ?      # Zero or one "+" or "-" characters
+"        \d +        # One or more digits
+"    )
+"
+"    \.\.            # ".."
+"
+"    (               # Capture a number
+"        [+-] ?      # Zero or one "+" or "-" characters
+"        \d +        # One or more digits
+"    )
+"    """, re.VERBOSE
+")
+
+" }}}1
+" === Internal functions ================================================ {{{1
+
+" Dump the bytes of a:text.  For debugging use.
+function! s:dump_bytes(text)
+    let l:idx=0
+    while l:idx < strlen(a:text)
+        let l:byte_val = char2nr(a:text[l:idx])
+        echom printf('%10s%-5d%02x %s', '', l:idx, l:byte_val,
+            \ a:text[l:idx])
+        let l:idx+=1
+    endwhile
+endfunction "s:dump_bytes
+
+" Dump the characters of a:text and their codepoints.  For debugging use.
+function! s:dump_chars(text)
+    let l:chars = split(a:text, '\zs')
+    let l:idx = 0
+    let l:out1 = ''
+    let l:out2 = ''
+    while l:idx < len(l:chars)
+        let l:char = l:chars[l:idx]
+        let l:out1 .= printf('%5s', l:char)
+        let l:out2 .= printf('%5x', char2nr(l:char))
+        let l:idx+=1
+    endwhile
+
+    echom l:out1
+    echom l:out2
+endfunction "s:dump_chars
+
+" }}}1
+" === Translating globs to patterns ===================================== {{{1
+
+" Used by s:re_escape: backslash-escape any character below U+0080;
+" replace all others with a %U escape.
+" See https://vi.stackexchange.com/a/19617/1430 by yours truly
+" (https://vi.stackexchange.com/users/1430/cxw).
+unlockvar s:replacement_expr
+let s:replacement_expr =
+    \ '\=' .
+    \ '((char2nr(submatch(1)) >= 128) ? ' .
+    \       'printf("%%U%08x", char2nr(submatch(1))) : ' .
+    \       '("\\" . submatch(1))' .
+    \ ')'
+lockvar s:replacement_expr
+
+" Escaper for very-magic regexes
+function! s:re_escape(text)
+    return substitute(a:text, '\v([^0-9a-zA-Z_])', s:replacement_expr, 'g')
+endfunction
+
+"def translate(pat, nested=0):
+"    Translate a shell PATTERN to a regular expression.
+"    There is no way to quote meta-characters.
+function! editorconfig_core#fnmatch#translate(pat, ...)
+    let l:nested = 0
+    if a:0
+        let l:nested = a:1
+    endif
+
+    if g:editorconfig_core_vimscript_debug
+        echom '- fnmatch#translate: pattern ' . a:pat
+        echom printf(
+            \ '- %d chars', strlen(substitute(a:pat, ".", "x", "g")))
+        call s:dump_chars(a:pat)
+    endif
+
+    let l:pat = a:pat   " TODO remove if we wind up not needing this
+
+    " Note: the Python sets MULTILINE and DOTALL, but Vim has \_.
+    " instead of DOTALL, and \_^ / \_$ instead of MULTILINE.
+
+    let l:is_escaped = 0
+
+    " Find out whether the pattern has balanced braces.
+    let l:left_braces=[]
+    let l:right_braces=[]
+    call substitute(l:pat, s:LEFT_BRACE, '\=add(l:left_braces, 1)', 'g')
+    call substitute(l:pat, s:RIGHT_BRACE, '\=add(l:right_braces, 1)', 'g')
+    " Thanks to http://jeromebelleman.gitlab.io/posts/productivity/vimsub/
+    let l:matching_braces = (len(l:left_braces) == len(l:right_braces))
+
+    " Unicode support (#2).  Indexing l:pat[l:index] returns bytes, per
+    " https://github.com/neovim/neovim/issues/68#issue-28114985 .
+    " Instead, use split() per vimdoc to break the input string into an
+    " array of *characters*, and process that.
+    let l:characters = split(l:pat, '\zs')
+
+    let l:index = 0     " character index
+    let l:length = len(l:characters)
+    let l:brace_level = 0
+    let l:in_brackets = 0
+
+    let l:result = ''
+    let l:numeric_groups = []
+    while l:index < l:length
+        let l:current_char = l:characters[l:index]
+        let l:index += 1
+
+"         if g:editorconfig_core_vimscript_debug
+"             echom ' - fnmatch#translate: ' . l:current_char . '@' .
+"                 \ (l:index-1) . '; result ' . l:result
+"         endif
+
+        if l:current_char ==# '*'
+            let l:pos = l:index
+            if l:pos < l:length && l:characters[l:pos] ==# '*'
+                let l:result .= '\_.*'
+                let l:index += 1    " skip the second star
+            else
+                let l:result .= '[^/]*'
+            endif
+
+        elseif l:current_char ==# '?'
+            let l:result .= '\_[^/]'
+
+        elseif l:current_char ==# '['
+            if l:in_brackets
+                let l:result .= '\['
+            else
+                let l:pos = l:index
+                let l:has_slash = 0
+                while l:pos < l:length && l:characters[l:pos] != ']'
+                    if l:characters[l:pos] ==# '/' && l:characters[l:pos-1] !=# '\'
+                        let has_slash = 1
+                        break
+                    endif
+                    let l:pos += 1
+                endwhile
+                if l:has_slash
+                    " POSIX IEEE 1003.1-2017 sec. 2.13.3: '/' cannot occur
+                    " in a bracket expression, so [/] matches a literal
+                    " three-character string '[' . '/' . ']'.
+                    let l:result .= '\['
+                        \ . s:re_escape(join(l:characters[l:index : l:pos-1], ''))
+                        \ . '\/'
+                        " escape the slash
+                    let l:index = l:pos + 1
+                        " resume after the slash
+                else
+                    if l:index < l:length && l:characters[l:index] =~# '\v%(\^|\!)'
+                        let l:index += 1
+                        let l:result .= '[^'
+                    else
+                        let l:result .= '['
+                    endif
+                    let l:in_brackets = 1
+                endif
+            endif
+
+        elseif l:current_char ==# '-'
+            if l:in_brackets
+                let l:result .= l:current_char
+            else
+                let l:result .= '\' . l:current_char
+            endif
+
+        elseif l:current_char ==# ']'
+            if l:in_brackets && !l:is_escaped
+                let l:result .= ']'
+                let l:in_brackets = 0
+            elseif l:is_escaped
+                let l:result .= '\]'
+                let l:is_escaped = 0
+            else
+                let l:result .= '\]'
+            endif
+
+        elseif l:current_char ==# '{'
+            let l:pos = l:index
+            let l:has_comma = 0
+            while l:pos < l:length && (l:characters[l:pos] !=# '}' || l:is_escaped)
+                if l:characters[l:pos] ==# ',' && ! l:is_escaped
+                    let l:has_comma = 1
+                    break
+                endif
+                let l:is_escaped = l:characters[l:pos] ==# '\' && ! l:is_escaped
+                let l:pos += 1
+            endwhile
+            if ! l:has_comma && l:pos < l:length
+                let l:num_range =
+                    \ matchlist(join(l:characters[l:index : l:pos-1], ''),
+                    \           s:NUMERIC_RANGE)
+                if len(l:num_range) > 0     " Remember the ranges
+                    call add(l:numeric_groups, [ 0+l:num_range[1], 0+l:num_range[2] ])
+                    let l:result .= '([+-]?\d+)'
+                else
+                    let l:inner_xlat = editorconfig_core#fnmatch#translate(
+                        \ join(l:characters[l:index : l:pos-1], ''), 1)
+                    let l:inner_result = l:inner_xlat[0]
+                    let l:inner_groups = l:inner_xlat[1]
+                    let l:result .= '\{' . l:inner_result . '\}'
+                    let l:numeric_groups += l:inner_groups
+                endif
+                let l:index = l:pos + 1
+            elseif l:matching_braces
+                let l:result .= '%('
+                let l:brace_level += 1
+            else
+                let l:result .= '\{'
+            endif
+
+        elseif l:current_char ==# ','
+            if l:brace_level > 0 && ! l:is_escaped
+                let l:result .= '|'
+            else
+                let l:result .= '\,'
+            endif
+
+        elseif l:current_char ==# '}'
+            if l:brace_level > 0 && ! l:is_escaped
+                let l:result .= ')'
+                let l:brace_level -= 1
+            else
+                let l:result .= '\}'
+            endif
+
+        elseif l:current_char ==# '/'
+            if join(l:characters[l:index : (l:index + 2)], '') ==# '**/'
+                let l:result .= '%(/|/\_.*/)'
+                let l:index += 3
+            else
+                let l:result .= '\/'
+            endif
+
+        elseif l:current_char != '\'
+            let l:result .= s:re_escape(l:current_char)
+        endif
+
+        if l:current_char ==# '\'
+            if l:is_escaped
+                let l:result .= s:re_escape(l:current_char)
+            endif
+            let l:is_escaped = ! l:is_escaped
+        else
+            let l:is_escaped = 0
+        endif
+
+    endwhile
+
+    if ! l:nested
+        let l:result .= '\_$'
+    endif
+
+    return [l:result, l:numeric_groups]
+endfunction " #editorconfig_core#fnmatch#translate
+
+let s:_cache = {}
+function! s:cached_translate(pat)
+    if ! has_key(s:_cache, a:pat)
+        "regex = re.compile(res)
+        let s:_cache[a:pat] =
+            \ editorconfig_core#fnmatch#translate(a:pat)
+            " we don't compile the regex
+    endif
+    return s:_cache[a:pat]
+endfunction " cached_translate
+
+" }}}1
+" === Matching functions ================================================ {{{1
+
+function! editorconfig_core#fnmatch#fnmatch(name, path, pattern)
+"def fnmatch(name, pat):
+"    """Test whether FILENAME matches PATH/PATTERN.
+"
+"    Patterns are Unix shell style:
+"
+"    - ``*``             matches everything except path separator
+"    - ``**``            matches everything
+"    - ``?``             matches any single character
+"    - ``[seq]``         matches any character in seq
+"    - ``[!seq]``        matches any char not in seq
+"    - ``{s1,s2,s3}``    matches any of the strings given (separated by commas)
+"
+"    An initial period in FILENAME is not special.
+"    Both FILENAME and PATTERN are first case-normalized
+"    if the operating system requires it.
+"    If you don't want this, use fnmatchcase(FILENAME, PATTERN).
+"    """
+"
+    " Note: This throws away the backslash in '\.txt' on Cygwin, but that
+    " makes sense since it's Windows under the hood.
+    " We don't care about shellslash since we're going to change backslashes
+    " to slashes in just a moment anyway.
+    let l:localname = fnamemodify(a:name, ':p')
+
+    if editorconfig_core#util#is_win()      " normalize
+        let l:localname = substitute(tolower(l:localname), '\v\\', '/', 'g')
+        let l:path = substitute(tolower(a:path), '\v\\', '/', 'g')
+        let l:pattern = tolower(a:pattern)
+    else
+        let l:localname = l:localname
+        let l:path = a:path
+        let l:pattern = a:pattern
+    endif
+
+    if g:editorconfig_core_vimscript_debug
+        echom '- fnmatch#fnmatch testing <' . l:localname . '> against <' .
+            \ l:pattern . '> wrt <' . l:path . '>'
+    endif
+
+    return editorconfig_core#fnmatch#fnmatchcase(l:localname, l:path, l:pattern)
+endfunction " fnmatch
+
+function! editorconfig_core#fnmatch#fnmatchcase(name, path, pattern)
+"def fnmatchcase(name, pat):
+"    """Test whether FILENAME matches PATH/PATTERN, including case.
+"
+"    This is a version of fnmatch() which doesn't case-normalize
+"    its arguments.
+"    """
+"
+    let [regex, num_groups] = s:cached_translate(a:pattern)
+
+    let l:escaped_path = s:re_escape(a:path)
+    let l:regex = '\v' . l:escaped_path . l:regex
+
+    if g:editorconfig_core_vimscript_debug
+        echom '- fnmatch#fnmatchcase: regex    ' . l:regex
+        call s:dump_chars(l:regex)
+        echom '- fnmatch#fnmatchcase: checking ' . a:name
+        call s:dump_chars(a:name)
+    endif
+
+    let l:match_groups = matchlist(a:name, l:regex)[1:]   " [0] = full match
+
+    if g:editorconfig_core_vimscript_debug
+        echom printf('  Got %d matches', len(l:match_groups))
+    endif
+
+    if len(l:match_groups) == 0
+        return 0
+    endif
+
+    " Check numeric ranges
+    let pattern_matched = 1
+    for l:idx in range(0,len(l:match_groups))
+        let l:num = l:match_groups[l:idx]
+        if l:num ==# ''
+            break
+        endif
+
+        let [min_num, max_num] = num_groups[l:idx]
+        if (min_num > (0+l:num)) || ((0+l:num) > max_num)
+            let pattern_matched = 0
+            break
+        endif
+
+        " Reject leading zeros without sign.  This is very odd ---
+        " see editorconfig/editorconfig#371.
+        if match(l:num, '\v^0') != -1
+            let pattern_matched = 0
+            break
+        endif
+    endfor
+
+    if g:editorconfig_core_vimscript_debug
+        echom '- fnmatch#fnmatchcase: ' . (pattern_matched ? 'matched' : 'did not match')
+    endif
+
+    return pattern_matched
+endfunction " fnmatchcase
+
+" }}}1
+" === Copyright notices ================================================= {{{1
+" Based on code from fnmatch.py file distributed with Python 2.6.
+" Portions Copyright (c) 2001-2010 Python Software Foundation;
+" All Rights Reserved.  Licensed under PSF License (see LICENSE.PSF file).
+"
+" Changes to original fnmatch:
+"
+" - translate function supports ``*`` and ``**`` similarly to fnmatch C library
+" }}}1
+
+let &cpo = s:saved_cpo
+unlet! s:saved_cpo
+
+" vi: set fdm=marker:
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/autoload/editorconfig_core/handler.vim
@@ -0,0 +1,183 @@
+" autoload/editorconfig_core/handler.vim: Main worker for
+" editorconfig-core-vimscript and editorconfig-vim.
+" Modified from the Python core's handler.py.
+
+" Copyright (c) 2012-2019 EditorConfig Team {{{1
+" All rights reserved.
+"
+" Redistribution and use in source and binary forms, with or without
+" modification, are permitted provided that the following conditions are met:
+"
+" 1. Redistributions of source code must retain the above copyright notice,
+"    this list of conditions and the following disclaimer.
+" 2. Redistributions in binary form must reproduce the above copyright notice,
+"    this list of conditions and the following disclaimer in the documentation
+"    and/or other materials provided with the distribution.
+"
+" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+" POSSIBILITY OF SUCH DAMAGE. }}}1
+
+let s:saved_cpo = &cpo
+set cpo&vim
+
+" Return full filepath for filename in each directory in and above path. {{{1
+" Input path must be an absolute path.
+" TODO shellslash/shellescape?
+function! s:get_filenames(path, config_filename)
+    let l:path = a:path
+    let l:path_list = []
+    while 1
+        call add(l:path_list, editorconfig_core#util#path_join(l:path, a:config_filename))
+        let l:newpath = fnamemodify(l:path, ':h')
+        if l:path ==? l:newpath || !strlen(l:path)
+            break
+        endif
+        let l:path = l:newpath
+    endwhile
+    return l:path_list
+endfunction " get_filenames
+
+" }}}1
+" === Main ============================================================== {{{1
+
+" Find EditorConfig files and return all options matching target_filename.
+" Throws on failure.
+" @param job    {Dictionary}    required 'target'; optional 'config' and 'version'
+function! editorconfig_core#handler#get_configurations(job)
+    " TODO? support VERSION checks?
+
+"    Special exceptions that may be raised by this function include:
+"    - ``VersionError``: self.version is invalid EditorConfig version
+"    - ``PathError``: self.filepath is not a valid absolute filepath
+"    - ``ParsingError``: improperly formatted EditorConfig file found
+
+    let l:job = deepcopy(a:job)
+    if has_key(l:job, 'config')
+        let l:config_filename = l:job.config
+    else
+        let l:config_filename = '.editorconfig'
+        let l:job.config = l:config_filename
+    endif
+
+    if has_key(l:job, 'version')
+        let l:version = l:job.version
+    else
+        let l:version = editorconfig_core#version()
+        let l:job.version = l:version
+    endif
+
+    let l:target_filename = l:job.target
+
+    "echom 'Beginning job ' . string(l:job)
+    if !s:check_assertions(l:job)
+        throw "Assertions failed"
+    endif
+
+    let l:fullpath = fnamemodify(l:target_filename,':p')
+    let l:path = fnamemodify(l:fullpath, ':h')
+    let l:conf_files = s:get_filenames(l:path, l:config_filename)
+
+    " echom 'fullpath ' . l:fullpath
+    " echom 'path ' . l:path
+
+    let l:retval = {}
+
+    " Attempt to find and parse every EditorConfig file in filetree
+    for l:conf_fn in l:conf_files
+        "echom 'Trying ' . l:conf_fn
+        let l:parsed = editorconfig_core#ini#read_ini_file(l:conf_fn, l:target_filename)
+        if !has_key(l:parsed, 'options')
+            continue
+        endif
+        " echom '  Has options'
+
+        " Merge new EditorConfig file's options into current options
+        let l:old_options = l:retval
+        let l:retval = l:parsed.options
+        " echom 'Old options ' . string(l:old_options)
+        " echom 'New options ' . string(l:retval)
+        call extend(l:retval, l:old_options, 'force')
+
+        " Stop parsing if parsed file has a ``root = true`` option
+        if l:parsed.root
+            break
+        endif
+    endfor
+
+    call s:preprocess_values(l:job, l:retval)
+    return l:retval
+endfunction " get_configurations
+
+function! s:check_assertions(job)
+" TODO
+"    """Raise error if filepath or version have invalid values"""
+
+"    # Raise ``PathError`` if filepath isn't an absolute path
+"    if not os.path.isabs(self.filepath):
+"        raise PathError("Input file must be a full path name.")
+
+    " Throw if version specified is greater than current
+    let l:v = a:job.version
+    let l:us = editorconfig_core#version()
+    " echom 'Comparing requested version ' . string(l:v) .
+    "     \ ' to our version ' . string(l:us)
+    if l:v[0] > l:us[0] || l:v[1] > l:us[1] || l:v[2] > l:us[2]
+        throw 'Required version ' . string(l:v) .
+                    \ ' is greater than the current version ' . string(l:us)
+    endif
+
+    return 1    " All OK if we got here
+endfunction " check_assertions
+
+" }}}1
+
+" Preprocess option values for consumption by plugins.  {{{1
+" Modifies its argument in place.
+function! s:preprocess_values(job, opts)
+
+    " Lowercase option value for certain options
+    for l:name in ['end_of_line', 'indent_style', 'indent_size',
+                \ 'insert_final_newline', 'trim_trailing_whitespace',
+                \ 'charset']
+        if has_key(a:opts, l:name)
+            let a:opts[l:name] = tolower(a:opts[l:name])
+        endif
+    endfor
+
+    " Set indent_size to "tab" if indent_size is unspecified and
+    " indent_style is set to "tab", provided we are at least v0.10.0.
+    if get(a:opts, 'indent_style', '') ==? "tab" &&
+                \ !has_key(a:opts, 'indent_size') &&
+                \ ( a:job.version[0]>0 || a:job.version[1] >=10 )
+        let a:opts['indent_size'] = 'tab'
+    endif
+
+    " Set tab_width to indent_size if indent_size is specified and
+    " tab_width is unspecified
+    if has_key(a:opts, 'indent_size') && !has_key(a:opts, 'tab_width') &&
+                \ get(a:opts, 'indent_size', '') !=? "tab"
+        let a:opts['tab_width'] = a:opts['indent_size']
+    endif
+
+    " Set indent_size to tab_width if indent_size is "tab"
+    if has_key(a:opts, 'indent_size') && has_key(a:opts, 'tab_width') &&
+                \ get(a:opts, 'indent_size', '') ==? "tab"
+        let a:opts['indent_size'] = a:opts['tab_width']
+    endif
+endfunction " preprocess_values
+
+" }}}1
+
+let &cpo = s:saved_cpo
+unlet! s:saved_cpo
+
+" vi: set fdm=marker fdl=1:
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/autoload/editorconfig_core/ini.vim
@@ -0,0 +1,264 @@
+" autoload/editorconfig_core/ini.vim: Config-file parser for
+" editorconfig-core-vimscript and editorconfig-vim.
+" Modifed from the Python core's ini.py.
+
+" Copyright (c) 2012-2019 EditorConfig Team {{{2
+" All rights reserved.
+"
+" Redistribution and use in source and binary forms, with or without
+" modification, are permitted provided that the following conditions are met:
+"
+" 1. Redistributions of source code must retain the above copyright notice,
+"    this list of conditions and the following disclaimer.
+" 2. Redistributions in binary form must reproduce the above copyright notice,
+"    this list of conditions and the following disclaimer in the documentation
+"    and/or other materials provided with the distribution.
+"
+" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+" POSSIBILITY OF SUCH DAMAGE. }}}2
+
+let s:saved_cpo = &cpo
+set cpo&vim
+
+" variables {{{2
+if !exists('g:editorconfig_core_vimscript_debug')
+    let g:editorconfig_core_vimscript_debug = 0
+endif
+" }}}2
+" === Constants, including regexes ====================================== {{{2
+" Regular expressions for parsing section headers and options.
+" Allow ``]`` and escaped ``;`` and ``#`` characters in section headers.
+" In fact, allow \ to escape any single character - it needs to cover at
+" least \ * ? [ ! ] { }.
+unlockvar s:SECTCRE s:OPTCRE s:MAX_SECTION_NAME s:MAX_PROPERTY_NAME s:MAX_PROPERTY_VALUE
+let s:SECTCRE = '\v^\s*\[(%([^\\#;]|\\.)+)\]'
+
+" Regular expression for parsing option name/values.
+" Allow any amount of whitespaces, followed by separator
+" (either ``:`` or ``=``), followed by any amount of whitespace and then
+" any characters to eol
+let s:OPTCRE = '\v\s*([^:=[:space:]][^:=]*)\s*([:=])\s*(.*)$'
+
+let s:MAX_SECTION_NAME = 4096
+let s:MAX_PROPERTY_NAME = 1024
+let s:MAX_PROPERTY_VALUE = 4096
+
+lockvar s:SECTCRE s:OPTCRE s:MAX_SECTION_NAME s:MAX_PROPERTY_NAME s:MAX_PROPERTY_VALUE
+
+" }}}2
+" === Main ============================================================== {{{1
+
+" Read \p config_filename and return the options applicable to
+" \p target_filename.  This is the main entry point in this file.
+function! editorconfig_core#ini#read_ini_file(config_filename, target_filename)
+    if !filereadable(a:config_filename)
+        return {}
+    endif
+
+    try
+        let l:lines = readfile(a:config_filename)
+        if &encoding !=? 'utf-8'
+            " strip BOM
+            if len(l:lines) > 0 && l:lines[0][:2] ==# "\xEF\xBB\xBF"
+                let l:lines[0] = l:lines[0][3:]
+            endif
+            " convert from UTF-8 to 'encoding'
+            call map(l:lines, 'iconv(v:val, "utf-8", &encoding)')
+        endif
+        let result = s:parse(a:config_filename, a:target_filename, l:lines)
+    catch
+        " rethrow, but with a prefix since throw 'Vim...' fails.
+        throw 'Could not read editorconfig file at ' . v:throwpoint . ': ' . string(v:exception)
+    endtry
+
+    return result
+endfunction
+
+function! s:parse(config_filename, target_filename, lines)
+"    Parse a sectioned setup file.
+"    The sections in setup file contains a title line at the top,
+"    indicated by a name in square brackets (`[]'), plus key/value
+"    options lines, indicated by `name: value' format lines.
+"    Continuations are represented by an embedded newline then
+"    leading whitespace.  Blank lines, lines beginning with a '#',
+"    and just about everything else are ignored.
+
+    let l:in_section = 0
+    let l:matching_section = 0
+    let l:optname = ''
+    let l:lineno = 0
+    let l:e = []    " Errors, if any
+
+    let l:options = {}  " Options applicable to this file
+    let l:is_root = 0   " Whether a:config_filename declares root=true
+
+    while 1
+        if l:lineno == len(a:lines)
+            break
+        endif
+
+        let l:line = a:lines[l:lineno]
+        let l:lineno = l:lineno + 1
+
+        " comment or blank line?
+        if editorconfig_core#util#strip(l:line) ==# ''
+            continue
+        endif
+        if l:line =~# '\v^[#;]'
+            continue
+        endif
+
+        " is it a section header?
+        if g:editorconfig_core_vimscript_debug
+            echom "Header? <" . l:line . ">"
+        endif
+
+        let l:mo = matchlist(l:line, s:SECTCRE)
+        if len(l:mo)
+            let l:sectname = l:mo[1]
+            let l:in_section = 1
+            if strlen(l:sectname) > s:MAX_SECTION_NAME
+                " Section name too long => ignore the section
+                let l:matching_section = 0
+            else
+                let l:matching_section = s:matches_filename(
+                    \ a:config_filename, a:target_filename, l:sectname)
+            endif
+
+            if g:editorconfig_core_vimscript_debug
+                echom 'In section ' . l:sectname . ', which ' .
+                    \ (l:matching_section ? 'matches' : 'does not match')
+                    \ ' file ' . a:target_filename . ' (config ' .
+                    \ a:config_filename . ')'
+            endif
+
+            " So sections can't start with a continuation line
+            let l:optname = ''
+
+        " Is it an option line?
+        else
+            let l:mo = matchlist(l:line, s:OPTCRE)
+            if len(l:mo)
+                let l:optname = mo[1]
+                let l:optval = mo[3]
+
+                if g:editorconfig_core_vimscript_debug
+                    echom printf('Saw raw opt <%s>=<%s>', l:optname, l:optval)
+                endif
+
+                let l:optval = editorconfig_core#util#strip(l:optval)
+                " allow empty values
+                if l:optval ==? '""'
+                    let l:optval = ''
+                endif
+                let l:optname = s:optionxform(l:optname)
+                if !l:in_section && optname ==? 'root'
+                    let l:is_root = (optval ==? 'true')
+                endif
+                if g:editorconfig_core_vimscript_debug
+                    echom printf('Saw opt <%s>=<%s>', l:optname, l:optval)
+                endif
+
+                if l:matching_section &&
+                            \ strlen(l:optname) <= s:MAX_PROPERTY_NAME &&
+                            \ strlen(l:optval) <= s:MAX_PROPERTY_VALUE
+                    let l:options[l:optname] = l:optval
+                endif
+            else
+                " a non-fatal parsing error occurred.  set up the
+                " exception but keep going. the exception will be
+                " raised at the end of the file and will contain a
+                " list of all bogus lines
+                call add(e, "Parse error in '" . a:config_filename . "' at line " .
+                    \ l:lineno . ": '" . l:line . "'")
+            endif
+        endif
+    endwhile
+
+    " if any parsing errors occurred, raise an exception
+    if len(l:e)
+        throw string(l:e)
+    endif
+
+    return {'root': l:is_root, 'options': l:options}
+endfunction!
+
+" }}}1
+" === Helpers =========================================================== {{{1
+
+" Preprocess option names
+function! s:optionxform(optionstr)
+    let l:result = substitute(a:optionstr, '\v\s+$', '', 'g')   " rstrip
+    return tolower(l:result)
+endfunction
+
+" Return true if \p glob matches \p target_filename
+function! s:matches_filename(config_filename, target_filename, glob)
+"    config_dirname = normpath(dirname(config_filename)).replace(sep, '/')
+    let l:config_dirname = fnamemodify(a:config_filename, ':p:h') . '/'
+
+    if editorconfig_core#util#is_win()
+        " Regardless of whether shellslash is set, make everything slashes
+        let l:config_dirname =
+                \ tolower(substitute(l:config_dirname, '\v\\', '/', 'g'))
+    endif
+
+    let l:glob = substitute(a:glob, '\v\\([#;])', '\1', 'g')
+
+    " Take account of the path to the editorconfig file.
+    " editorconfig-core-c/src/lib/editorconfig.c says:
+    "  "Pattern would be: /dir/of/editorconfig/file[double_star]/[section] if
+    "   section does not contain '/', or /dir/of/editorconfig/file[section]
+    "   if section starts with a '/', or /dir/of/editorconfig/file/[section] if
+    "   section contains '/' but does not start with '/'."
+
+    if stridx(l:glob, '/') != -1    " contains a slash
+        if l:glob[0] ==# '/'
+            let l:glob = l:glob[1:]     " trim leading slash
+        endif
+" This will be done by fnmatch
+"        let l:glob = l:config_dirname . l:glob
+    else                            " does not contain a slash
+        let l:config_dirname = l:config_dirname[:-2]
+            " Trim trailing slash
+        let l:glob = '**/' . l:glob
+    endif
+
+    if g:editorconfig_core_vimscript_debug
+        echom '- ini#matches_filename: checking <' . a:target_filename .
+            \ '> against <' . l:glob . '> with respect to config file <' .
+            \ a:config_filename . '>'
+        echom '- ini#matches_filename: config_dirname is ' . l:config_dirname
+    endif
+
+    return editorconfig_core#fnmatch#fnmatch(a:target_filename,
+        \ l:config_dirname, l:glob)
+endfunction " matches_filename
+
+" }}}1
+" === Copyright notices ================================================= {{{2
+" Based on code from ConfigParser.py file distributed with Python 2.6.
+" Portions Copyright (c) 2001-2010 Python Software Foundation;
+" All Rights Reserved.  Licensed under PSF License (see LICENSE.PSF file).
+"
+" Changes to original ConfigParser:
+"
+" - Special characters can be used in section names
+" - Octothorpe can be used for comments (not just at beginning of line)
+" - Only track INI options in sections that match target filename
+" - Stop parsing files with when ``root = true`` is found
+" }}}2
+
+let &cpo = s:saved_cpo
+unlet! s:saved_cpo
+
+" vi: set fdm=marker fdl=1:
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/autoload/editorconfig_core/util.vim
@@ -0,0 +1,84 @@
+" util.vim: part of editorconfig-core-vimscript and editorconfig-vim.
+" Copyright (c) 2018-2019 EditorConfig Team, including Chris White {{{1
+" All rights reserved.
+"
+" Redistribution and use in source and binary forms, with or without
+" modification, are permitted provided that the following conditions are met:
+"
+" 1. Redistributions of source code must retain the above copyright notice,
+"    this list of conditions and the following disclaimer.
+" 2. Redistributions in binary form must reproduce the above copyright notice,
+"    this list of conditions and the following disclaimer in the documentation
+"    and/or other materials provided with the distribution.
+"
+" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+" POSSIBILITY OF SUCH DAMAGE. }}}1
+
+let s:saved_cpo = &cpo
+set cpo&vim
+
+" A verbatim copy of ingo#fs#path#Separator()  {{{1
+" from https://github.com/vim-scripts/ingo-library/blob/558132e2221db3af26dc2f2c6756d092d48a459f/autoload/ingo/fs/path.vim
+" distributed under the Vim license.
+function! editorconfig_core#util#Separator()
+    return (exists('+shellslash') && ! &shellslash ? '\' : '/')
+endfunction " }}}1
+
+" path_join(): ('a','b')->'a/b'; ('a/','b')->'a/b'. {{{1
+function! editorconfig_core#util#path_join(a, b)
+    " TODO shellescape/shellslash?
+    "echom 'Joining <' . a:a . '> and <' . a:b . '>'
+    "echom 'Length is ' . strlen(a:a)
+    "echom 'Last char is ' . char2nr(a:a[-1])
+    if a:a !~# '\v%(\/|\\)$'
+        return a:a . editorconfig_core#util#Separator() . a:b
+    else
+        return a:a . a:b
+    endif
+endfunction " }}}1
+
+" is_win() by xolox {{{1
+" The following function is modified from
+" https://github.com/xolox/vim-misc/blob/master/autoload/xolox/misc/os.vim
+" Copyright (c) 2015 Peter Odding <peter@peterodding.com>
+"
+" 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.
+function! editorconfig_core#util#is_win()
+    " Returns 1 (true) when on Microsoft Windows, 0 (false) otherwise.
+    return has('win16') || has('win32') || has('win64')
+endfunction " }}}1
+
+" strip() {{{1
+function! editorconfig_core#util#strip(s)
+    return substitute(a:s, '\v^\s+|\s+$','','g')
+endfunction " }}}1
+
+let &cpo = s:saved_cpo
+unlet! s:saved_cpo
+
+" vi: set fdm=marker:
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/doc/editorconfig.txt
@@ -0,0 +1,233 @@
+*editorconfig.txt*
+
+File: editorconfig.txt
+Version: 1.1.1
+Maintainer: EditorConfig Team <http://editorconfig.org>
+Description: EditorConfig vim plugin
+
+License:
+   Copyright (c) 2011-2019 EditorConfig Team
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+   2. Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+
+
+CONTENTS~
+                                            *editorconfig-contents*
+----------------------------------------------------------------------------
+1.  Overview                                 |editorconfig-overview|
+2.  Installation                             |editorconfig-installation|
+3.  Commands                                 |editorconfig-commands|
+4.  Settings                                 |editorconfig-settings|
+5.  Advanced                                 |editorconfig-advanced|
+
+
+OVERVIEW~
+                                            *editorconfig-overview*
+----------------------------------------------------------------------------
+This is the EditorConfig plugin for vim.
+
+
+INSTALLATION~
+                                            *editorconfig-installation*
+----------------------------------------------------------------------------
+Follow the instructions in the README.md file to install this plugin.
+
+COMMANDS~
+                                            *editorconfig-commands*
+----------------------------------------------------------------------------
+
+                                            *:EditorConfigReload*
+Command:
+    :EditorConfigReload
+
+Reload the EditorConfig conf files. When `.editorconfig` files are modified,
+this command could prevent you to reload the current edited file to load the
+new configuration.
+
+SETTINGS~
+                                            *editorconfig-settings*
+----------------------------------------------------------------------------
+                                            *g:EditorConfig_core_mode*
+Specify the mode of EditorConfig core. Generally it is OK to leave this option
+empty. Currently, the supported modes are "vim_core" (default) and
+"external_command".
+
+    vim_core:           Use the included VimScript EditorConfig Core.
+    external_command:   Run external EditorConfig Core.
+
+If "g:EditorConfig_core_mode" is not specified, this plugin will automatically
+choose "vim_core".
+
+If you choose "external_command" mode, you must also set
+|g:EditorConfig_exec_path|.
+
+Changes to "g:EditorConfig_core_mode" will not take effect until Vim
+is restarted.
+
+                                            *b:EditorConfig_disable*
+This is a buffer-local variable that disables the EditorConfig plugin for a
+single buffer.
+
+Example: Disable EditorConfig for the current buffer:
+>
+ let b:EditorConfig_disable = 1
+<
+Example: Disable EditorConfig for all git commit messages:
+>
+ au FileType gitcommit let b:EditorConfig_disable = 1
+<
+
+                                            *g:EditorConfig_exclude_patterns*
+This is a list contains file path patterns which will be ignored by
+EditorConfig plugin. When the path of the opened buffer (i.e.
+"expand('%:p')") matches any of the patterns in the list, EditorConfig will
+not load for this file. The default is an empty list.
+
+Example: Avoid loading EditorConfig for any remote files over ssh
+>
+ let g:EditorConfig_exclude_patterns = ['scp://.*']
+<
+
+                                            *g:EditorConfig_exec_path*
+The file path to the EditorConfig core executable. You can set this value in
+your |vimrc| like this:
+>
+ let g:EditorConfig_exec_path = 'Path to your EditorConfig Core executable'
+<
+The default value is empty.
+
+If "g:EditorConfig_exec_path" is not set, the plugin will use the "vim_core"
+mode regardless of the setting of |g:EditorConfig_core_mode|.
+
+Changes to "g:EditorConfig_exec_path" will not take effect until Vim
+is restarted.
+
+                                            *g:EditorConfig_max_line_indicator*
+The way to show the line where the maximal length is reached. Accepted values
+are "line", "fill", "exceeding" and "fillexceeding", otherwise there will be
+no max line indicator.
+
+    "line":          the right column of the max line length column will be
+                     highlighted on all lines, by adding +1 to 'colorcolumn'.
+
+    "fill":          all the columns to the right of the max line length
+                     column will be highlighted on all lines, by setting
+                     'colorcolumn' to a list starting from "max_line_length +
+                     1" to the number of columns on the screen.
+
+    "exceeding":     the right column of the max line length column will be
+                     highlighted on lines that exceed the max line length, by
+                     adding a match for the ColorColumn group.
+
+    "fillexceeding": all the columns to the right of the max line length
+                     column will be highlighted on lines that exceed the max
+                     line length, by adding a match for the ColorColumn group.
+
+    "none":          no max line length indicator will be shown. Recommended
+                     when you do not want any indicator to be shown, but any
+                     value other than those listed above also work as "none".
+
+To set this option, add any of the following lines to your |vimrc| file:
+>
+ let g:EditorConfig_max_line_indicator = "line"
+ let g:EditorConfig_max_line_indicator = "fill"
+ let g:EditorConfig_max_line_indicator = "exceeding"
+ let g:EditorConfig_max_line_indicator = "fillexceeding"
+ let g:EditorConfig_max_line_indicator = "none"
+<
+The default value is "line".
+
+                                            *g:EditorConfig_enable_for_new_buf*
+Set this to 1 if you want EditorConfig plugin to set options
+for new empty buffers too.
+Path to .editorconfig will be determined based on CWD (see |getcwd()|)
+>
+ let g:EditorConfig_enable_for_new_buf = 1
+<
+This option defaults to 0.
+
+                                            *g:EditorConfig_preserve_formatoptions*
+Set this to 1 if you don't want your formatoptions modified when
+max_line_length is set:
+>
+ let g:EditorConfig_preserve_formatoptions = 1
+<
+This option defaults to 0.
+
+                                            *g:EditorConfig_softtabstop_space*
+When spaces are used for indent, Vim's 'softtabstop' feature will make the
+backspace key delete one indent level. If you turn off that feature (by
+setting the option to 0), only a single space will be deleted.
+This option defaults to 1, which enables 'softtabstop' and uses the
+'shiftwidth' value for it. You can also set this to -1 to automatically follow
+the current 'shiftwidth' value (since Vim 7.3.693). Or set this to [] if
+EditorConfig should not touch 'softtabstop' at all.
+
+                                            *g:EditorConfig_softtabstop_tab*
+When tabs are used for indent, Vim's 'softtabstop' feature only applies to
+backspacing over existing runs of spaces.
+This option defaults to 1, so backspace will delete one indent level worth of
+spaces; -1 does the same but automatically follows the current 'shiftwidth'
+value. Set this to 0 to have backspace delete just a single space character.
+Or set this to [] if EditorConfig should not touch 'softtabstop' at all.
+
+                                            *g:EditorConfig_verbose*
+Set this to 1 if you want debug info printed:
+>
+ let g:EditorConfig_verbose = 1
+<
+
+ADVANCED~
+                                            *editorconfig-advanced*
+----------------------------------------------------------------------------
+                                            *editorconfig-hook*
+                                            *EditorConfig#AddNewHook()*
+While this plugin offers several builtin supported properties (as mentioned
+here: https://github.com/editorconfig/editorconfig-vim#supported-properties),
+we are also able to add our own hooks to support additional EditorConfig
+properties, including those not in the EditorConfig standard. For example, we
+are working on an Objective-C project, and all our "*.m" files should be
+Objective-C source files. However, vim sometimes detect "*.m" files as MATLAB
+source files, which causes incorrect syntax highlighting, code indentation,
+etc. To solve the case, we could write the following code into the |vimrc|
+file:
+>
+ function! FiletypeHook(config)
+     if has_key(a:config, 'vim_filetype')
+         let &filetype = a:config['vim_filetype']
+     endif
+
+     return 0   " Return 0 to show no error happened
+ endfunction
+
+ call editorconfig#AddNewHook(function('FiletypeHook'))
+<
+And add the following code to your .editorconfig file:
+>
+ [*.m]
+ vim_filetype = objc
+<
+Then try to open an Objective-C file, you will find the |filetype| is set to
+"objc".
+
+vim:ft=help:tw=78
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/ftdetect/editorconfig.vim
@@ -0,0 +1,1 @@
+autocmd BufNewFile,BufRead .editorconfig setfiletype dosini
new file mode 100755
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/mkzip.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+zip -r editorconfig-vim-$*.zip autoload/* doc/* ftdetect/* plugin/*
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/plugin/editorconfig.vim
@@ -0,0 +1,614 @@
+" plugin/editorconfig.vim: EditorConfig native Vimscript plugin file
+" Copyright (c) 2011-2019 EditorConfig Team
+" All rights reserved.
+"
+" Redistribution and use in source and binary forms, with or without
+" modification, are permitted provided that the following conditions are met:
+"
+" 1. Redistributions of source code must retain the above copyright notice,
+"    this list of conditions and the following disclaimer.
+" 2. Redistributions in binary form must reproduce the above copyright notice,
+"    this list of conditions and the following disclaimer in the documentation
+"    and/or other materials provided with the distribution.
+"
+" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+" POSSIBILITY OF SUCH DAMAGE.
+"
+
+" check for Vim versions and duplicate script loading.
+if v:version < 700 || exists("g:loaded_EditorConfig")
+    finish
+endif
+let g:loaded_EditorConfig = 1
+
+let s:saved_cpo = &cpo
+set cpo&vim
+
+" variables {{{1
+
+" Make sure the globals all exist
+if !exists('g:EditorConfig_exec_path')
+    let g:EditorConfig_exec_path = ''
+endif
+
+if !exists('g:EditorConfig_verbose')
+    let g:EditorConfig_verbose = 0
+endif
+
+if !exists('g:EditorConfig_preserve_formatoptions')
+    let g:EditorConfig_preserve_formatoptions = 0
+endif
+
+if !exists('g:EditorConfig_max_line_indicator')
+    let g:EditorConfig_max_line_indicator = 'line'
+endif
+
+if !exists('g:EditorConfig_exclude_patterns')
+    let g:EditorConfig_exclude_patterns = []
+endif
+
+if !exists('g:EditorConfig_disable_rules')
+    let g:EditorConfig_disable_rules = []
+endif
+
+if !exists('g:EditorConfig_enable_for_new_buf')
+    let g:EditorConfig_enable_for_new_buf = 0
+endif
+
+if !exists('g:EditorConfig_softtabstop_space')
+    let g:EditorConfig_softtabstop_space = 1
+endif
+
+if !exists('g:EditorConfig_softtabstop_tab')
+    let g:EditorConfig_softtabstop_tab = 1
+endif
+
+" Copy some of the globals into script variables --- changes to these
+" globals won't affect the plugin until the plugin is reloaded.
+if exists('g:EditorConfig_core_mode') && !empty(g:EditorConfig_core_mode)
+    let s:editorconfig_core_mode = g:EditorConfig_core_mode
+else
+    let s:editorconfig_core_mode = ''
+endif
+
+if exists('g:EditorConfig_exec_path') && !empty(g:EditorConfig_exec_path)
+    let s:editorconfig_exec_path = g:EditorConfig_exec_path
+else
+    let s:editorconfig_exec_path = ''
+endif
+
+let s:initialized = 0
+
+" }}}1
+
+" shellslash handling {{{1
+function! s:DisableShellSlash(bufnr) " {{{2
+    " disable shellslash for proper escaping of Windows paths
+
+    " In Windows, 'shellslash' also changes the behavior of 'shellescape'.
+    " It makes 'shellescape' behave like in UNIX environment. So ':setl
+    " noshellslash' before evaluating 'shellescape' and restore the
+    " settings afterwards when 'shell' does not contain 'sh' somewhere.
+    let l:shell = getbufvar(a:bufnr, '&shell')
+    if has('win32') && empty(matchstr(l:shell, 'sh'))
+        let s:old_shellslash = getbufvar(a:bufnr, '&shellslash')
+        setbufvar(a:bufnr, '&shellslash', 0)
+    endif
+endfunction " }}}2
+
+function! s:ResetShellSlash(bufnr) " {{{2
+    " reset shellslash to the user-set value, if any
+    if exists('s:old_shellslash')
+        setbufvar(a:bufnr, '&shellslash', s:old_shellslash)
+        unlet! s:old_shellslash
+    endif
+endfunction " }}}2
+" }}}1
+
+" Mode initialization functions {{{1
+
+function! s:InitializeVimCore()
+" Initialize vim core.  Returns 1 on failure; 0 on success
+" At the moment, all we need to do is to check that it is installed.
+    try
+        let l:vim_core_ver = editorconfig_core#version()
+    catch
+        return 1
+    endtry
+    return 0
+endfunction
+
+function! s:InitializeExternalCommand()
+" Initialize external_command mode
+
+    if empty(s:editorconfig_exec_path)
+        echo 'Please specify a g:EditorConfig_exec_path'
+        return 1
+    endif
+
+    if g:EditorConfig_verbose
+        echo 'Checking for external command ' . s:editorconfig_exec_path . ' ...'
+    endif
+
+    if !executable(s:editorconfig_exec_path)
+        echo 'File ' . s:editorconfig_exec_path . ' is not executable.'
+        return 1
+    endif
+
+    return 0
+endfunction
+" }}}1
+
+function! s:Initialize() " Initialize the plugin.  {{{1
+    " Returns truthy on error, falsy on success.
+
+    if empty(s:editorconfig_core_mode)
+        let s:editorconfig_core_mode = 'vim_core'   " Default core choice
+    endif
+
+    if s:editorconfig_core_mode ==? 'external_command'
+        if s:InitializeExternalCommand()
+            echohl WarningMsg
+            echo 'EditorConfig: Failed to initialize external_command mode.  ' .
+                \ 'Falling back to vim_core mode.'
+            echohl None
+            let s:editorconfig_core_mode = 'vim_core'
+        endif
+    endif
+
+    if s:editorconfig_core_mode ==? 'vim_core'
+        if s:InitializeVimCore()
+            echohl ErrorMsg
+            echo 'EditorConfig: Failed to initialize vim_core mode.  ' .
+                \ 'The plugin will not function.'
+            echohl None
+            return 1
+        endif
+
+    elseif s:editorconfig_core_mode ==? 'external_command'
+        " Nothing to do here, but this elseif is required to avoid
+        " external_command falling into the else clause.
+
+    else    " neither external_command nor vim_core
+        echohl ErrorMsg
+        echo "EditorConfig: I don't know how to use mode " . s:editorconfig_core_mode
+        echohl None
+        return 1
+    endif
+
+    let s:initialized = 1
+    return 0
+endfunction " }}}1
+
+function! s:GetFilenames(path, filename) " {{{1
+" Yield full filepath for filename in each directory in and above path
+
+    let l:path_list = []
+    let l:path = a:path
+    while 1
+        let l:path_list += [l:path . '/' . a:filename]
+        let l:newpath = fnamemodify(l:path, ':h')
+        if l:path == l:newpath
+            break
+        endif
+        let l:path = l:newpath
+    endwhile
+    return l:path_list
+endfunction " }}}1
+
+function! s:UseConfigFiles(from_autocmd) abort " Apply config to the current buffer {{{1
+    " from_autocmd is truthy if called from an autocmd, falsy otherwise.
+
+    " Get the properties of the buffer we are working on
+    if a:from_autocmd
+        let l:bufnr = str2nr(expand('<abuf>'))
+        let l:buffer_name = expand('<afile>:p')
+        let l:buffer_path = expand('<afile>:p:h')
+    else
+        let l:bufnr = bufnr('%')
+        let l:buffer_name = expand('%:p')
+        let l:buffer_path = expand('%:p:h')
+    endif
+    call setbufvar(l:bufnr, 'editorconfig_tried', 1)
+
+    " Only process normal buffers (do not treat help files as '.txt' files)
+    " When starting Vim with a directory, the buftype might not yet be set:
+    " Therefore, also check if buffer_name is a directory.
+    if index(['', 'acwrite'], &buftype) == -1 || isdirectory(l:buffer_name)
+        return
+    endif
+
+    if empty(l:buffer_name)
+        if g:EditorConfig_enable_for_new_buf
+            let l:buffer_name = getcwd() . "/."
+        else
+            if g:EditorConfig_verbose
+                echo 'Skipping EditorConfig for unnamed buffer'
+            endif
+            return
+        endif
+    endif
+
+    if getbufvar(l:bufnr, 'EditorConfig_disable', 0)
+        if g:EditorConfig_verbose
+            echo 'EditorConfig disabled --- skipping buffer "' . l:buffer_name . '"'
+        endif
+        return
+    endif
+
+    " Ignore specific patterns
+    for pattern in g:EditorConfig_exclude_patterns
+        if l:buffer_name =~ pattern
+            if g:EditorConfig_verbose
+                echo 'Skipping EditorConfig for buffer "' . l:buffer_name .
+                    \ '" based on pattern "' . pattern . '"'
+            endif
+            return
+        endif
+    endfor
+
+    " Check if any .editorconfig does exist
+    let l:conf_files = s:GetFilenames(l:buffer_path, '.editorconfig')
+    let l:conf_found = 0
+    for conf_file in conf_files
+        if filereadable(conf_file)
+            let l:conf_found = 1
+            break
+        endif
+    endfor
+    if !l:conf_found
+        return
+    endif
+
+    if !s:initialized
+        if s:Initialize()
+            return
+        endif
+    endif
+
+    if g:EditorConfig_verbose
+        echo 'Applying EditorConfig ' . s:editorconfig_core_mode .
+            \ ' on file "' . l:buffer_name . '"'
+    endif
+
+    if s:editorconfig_core_mode ==? 'vim_core'
+        if s:UseConfigFiles_VimCore(l:bufnr, l:buffer_name) == 0
+            call setbufvar(l:bufnr, 'editorconfig_applied', 1)
+        endif
+    elseif s:editorconfig_core_mode ==? 'external_command'
+        call s:UseConfigFiles_ExternalCommand(l:bufnr, l:buffer_name)
+        call setbufvar(l:bufnr, 'editorconfig_applied', 1)
+    else
+        echohl Error |
+                    \ echo "Unknown EditorConfig Core: " .
+                    \ s:editorconfig_core_mode |
+                    \ echohl None
+    endif
+endfunction " }}}1
+
+" Custom commands, and autoloading {{{1
+
+" Autocommands, and function to enable/disable the plugin {{{2
+function! s:EditorConfigEnable(should_enable)
+    augroup editorconfig
+        autocmd!
+        if a:should_enable
+            autocmd BufNewFile,BufReadPost,BufFilePost * call s:UseConfigFiles(1)
+            autocmd VimEnter,BufNew * call s:UseConfigFiles(1)
+        endif
+    augroup END
+endfunction
+
+" }}}2
+
+" Commands {{{2
+command! EditorConfigEnable call s:EditorConfigEnable(1)
+command! EditorConfigDisable call s:EditorConfigEnable(0)
+
+command! EditorConfigReload call s:UseConfigFiles(0) " Reload EditorConfig files
+" }}}2
+
+" On startup, enable the autocommands
+call s:EditorConfigEnable(1)
+
+" }}}1
+
+" UseConfigFiles function for different modes {{{1
+
+function! s:UseConfigFiles_VimCore(bufnr, target)
+" Use the vimscript EditorConfig core
+    try
+        let l:config = editorconfig_core#handler#get_configurations(
+            \ { 'target': a:target } )
+        call s:ApplyConfig(a:bufnr, l:config)
+        return 0    " success
+    catch
+        return 1    " failure
+    endtry
+endfunction
+
+function! s:UseConfigFiles_ExternalCommand(bufnr, target)
+" Use external EditorConfig core (e.g., the C core)
+
+    call s:DisableShellSlash(a:bufnr)
+    let l:exec_path = shellescape(s:editorconfig_exec_path)
+    call s:ResetShellSlash(a:bufnr)
+
+    call s:SpawnExternalParser(a:bufnr, l:exec_path, a:target)
+endfunction
+
+function! s:SpawnExternalParser(bufnr, cmd, target) " {{{2
+" Spawn external EditorConfig. Used by s:UseConfigFiles_ExternalCommand()
+
+    let l:cmd = a:cmd
+
+    if empty(l:cmd)
+        throw 'No cmd provided'
+    endif
+
+    let l:config = {}
+
+    call s:DisableShellSlash(a:bufnr)
+    let l:cmd = l:cmd . ' ' . shellescape(a:target)
+    call s:ResetShellSlash(a:bufnr)
+
+    let l:parsing_result = split(system(l:cmd), '\v[\r\n]+')
+
+    " if editorconfig core's exit code is not zero, give out an error
+    " message
+    if v:shell_error != 0
+        echohl ErrorMsg
+        echo 'Failed to execute "' . l:cmd . '". Exit code: ' .
+                    \ v:shell_error
+        echo ''
+        echo 'Message:'
+        echo l:parsing_result
+        echohl None
+        return
+    endif
+
+    if g:EditorConfig_verbose
+        echo 'Output from EditorConfig core executable:'
+        echo l:parsing_result
+    endif
+
+    for one_line in l:parsing_result
+        let l:eq_pos = stridx(one_line, '=')
+
+        if l:eq_pos == -1 " = is not found. Skip this line
+            continue
+        endif
+
+        let l:eq_left = strpart(one_line, 0, l:eq_pos)
+        if l:eq_pos + 1 < strlen(one_line)
+            let l:eq_right = strpart(one_line, l:eq_pos + 1)
+        else
+            let l:eq_right = ''
+        endif
+
+        let l:config[l:eq_left] = l:eq_right
+    endfor
+
+    call s:ApplyConfig(a:bufnr, l:config)
+endfunction " }}}2
+
+" }}}1
+
+" Set the buffer options {{{1
+function! s:SetCharset(bufnr, charset) abort " apply config['charset']
+
+    " Remember the buffer's state so we can set `nomodifed` at the end
+    " if appropriate.
+    let l:orig_fenc = getbufvar(a:bufnr, "&fileencoding")
+    let l:orig_enc = getbufvar(a:bufnr, "&encoding")
+    let l:orig_modified = getbufvar(a:bufnr, "&modified")
+
+    if a:charset == "utf-8"
+        call setbufvar(a:bufnr, '&fileencoding', 'utf-8')
+        call setbufvar(a:bufnr, '&bomb', 0)
+    elseif a:charset == "utf-8-bom"
+        call setbufvar(a:bufnr, '&fileencoding', 'utf-8')
+        call setbufvar(a:bufnr, '&bomb', 1)
+    elseif a:charset == "latin1"
+        call setbufvar(a:bufnr, '&fileencoding', 'latin1')
+        call setbufvar(a:bufnr, '&bomb', 0)
+    elseif a:charset == "utf-16be"
+        call setbufvar(a:bufnr, '&fileencoding', 'utf-16be')
+        call setbufvar(a:bufnr, '&bomb', 1)
+    elseif a:charset == "utf-16le"
+        call setbufvar(a:bufnr, '&fileencoding', 'utf-16le')
+        call setbufvar(a:bufnr, '&bomb', 1)
+    endif
+
+    let l:new_fenc = getbufvar(a:bufnr, "&fileencoding")
+
+    " If all we did was change the fileencoding from the default to a copy
+    " of the default, we didn't actually modify the file.
+    if !l:orig_modified && (l:orig_fenc ==# '') && (l:new_fenc ==# l:orig_enc)
+        if g:EditorConfig_verbose
+            echo 'Setting nomodified on buffer ' . a:bufnr
+        endif
+        call setbufvar(a:bufnr, '&modified', 0)
+    endif
+endfunction
+
+function! s:ApplyConfig(bufnr, config) abort
+    if g:EditorConfig_verbose
+        echo 'Options: ' . string(a:config)
+    endif
+
+    if s:IsRuleActive('indent_style', a:config)
+        if a:config["indent_style"] == "tab"
+            call setbufvar(a:bufnr, '&expandtab', 0)
+        elseif a:config["indent_style"] == "space"
+            call setbufvar(a:bufnr, '&expandtab', 1)
+        endif
+    endif
+
+    if s:IsRuleActive('tab_width', a:config)
+        let l:tabstop = str2nr(a:config["tab_width"])
+        call setbufvar(a:bufnr, '&tabstop', l:tabstop)
+    else
+        " Grab the current ts so we can use it below
+        let l:tabstop = getbufvar(a:bufnr, '&tabstop')
+    endif
+
+    if s:IsRuleActive('indent_size', a:config)
+        " if indent_size is 'tab', set shiftwidth to tabstop;
+        " if indent_size is a positive integer, set shiftwidth to the integer
+        " value
+        if a:config["indent_size"] == "tab"
+            call setbufvar(a:bufnr, '&shiftwidth', l:tabstop)
+            if type(g:EditorConfig_softtabstop_tab) != type([])
+                call setbufvar(a:bufnr, '&softtabstop',
+                            \ g:EditorConfig_softtabstop_tab > 0 ?
+                            \ l:tabstop : g:EditorConfig_softtabstop_tab)
+            endif
+        else
+            let l:indent_size = str2nr(a:config["indent_size"])
+            if l:indent_size > 0
+                call setbufvar(a:bufnr, '&shiftwidth', l:indent_size)
+                if type(g:EditorConfig_softtabstop_space) != type([])
+                    call setbufvar(a:bufnr, '&softtabstop',
+                            \ g:EditorConfig_softtabstop_space > 0 ?
+                            \ l:indent_size : g:EditorConfig_softtabstop_space)
+                endif
+            endif
+        endif
+
+    endif
+
+    if s:IsRuleActive('end_of_line', a:config) &&
+                \ getbufvar(a:bufnr, '&modifiable')
+        if a:config["end_of_line"] == "lf"
+            call setbufvar(a:bufnr, '&fileformat', 'unix')
+        elseif a:config["end_of_line"] == "crlf"
+            call setbufvar(a:bufnr, '&fileformat', 'dos')
+        elseif a:config["end_of_line"] == "cr"
+            call setbufvar(a:bufnr, '&fileformat', 'mac')
+        endif
+    endif
+
+    if s:IsRuleActive('charset', a:config) &&
+                \ getbufvar(a:bufnr, '&modifiable')
+        call s:SetCharset(a:bufnr, a:config["charset"])
+    endif
+
+    augroup editorconfig_trim_trailing_whitespace
+        autocmd! BufWritePre <buffer>
+        if s:IsRuleActive('trim_trailing_whitespace', a:config) &&
+                    \ get(a:config, 'trim_trailing_whitespace', 'false') ==# 'true'
+            execute 'autocmd BufWritePre <buffer=' . a:bufnr . '> call s:TrimTrailingWhitespace()'
+        endif
+    augroup END
+
+    if s:IsRuleActive('insert_final_newline', a:config)
+        if exists('+fixendofline')
+            if a:config["insert_final_newline"] == "false"
+                call setbufvar(a:bufnr, '&fixendofline', 0)
+            else
+                call setbufvar(a:bufnr, '&fixendofline', 1)
+            endif
+        elseif  exists(':SetNoEOL') == 2
+            if a:config["insert_final_newline"] == "false"
+                silent! SetNoEOL    " Use the PreserveNoEOL plugin to accomplish it
+            endif
+        endif
+    endif
+
+    " highlight the columns following max_line_length
+    if s:IsRuleActive('max_line_length', a:config) &&
+                \ a:config['max_line_length'] != 'off'
+        let l:max_line_length = str2nr(a:config['max_line_length'])
+
+        if l:max_line_length >= 0
+            call setbufvar(a:bufnr, '&textwidth', l:max_line_length)
+            if g:EditorConfig_preserve_formatoptions == 0
+                " setlocal formatoptions+=tc
+                let l:fo = getbufvar(a:bufnr, '&formatoptions')
+                if l:fo !~# 't'
+                    let l:fo .= 't'
+                endif
+                if l:fo !~# 'c'
+                    let l:fo .= 'c'
+                endif
+                call setbufvar(a:bufnr, '&formatoptions', l:fo)
+            endif
+        endif
+
+        if exists('+colorcolumn')
+            if l:max_line_length > 0
+                if g:EditorConfig_max_line_indicator == 'line'
+                    " setlocal colorcolumn+=+1
+                    let l:cocol = getbufvar(a:bufnr, '&colorcolumn')
+                    if !empty(l:cocol)
+                        let l:cocol .= ','
+                    endif
+                    let l:cocol .= '+1'
+                    call setbufvar(a:bufnr, '&colorcolumn', l:cocol)
+                elseif g:EditorConfig_max_line_indicator == 'fill' &&
+                            \ l:max_line_length < getbufvar(a:bufnr, '&columns')
+                    " Fill only if the columns of screen is large enough
+                    call setbufvar(a:bufnr, '&colorcolumn',
+                            \ join(range(l:max_line_length+1,
+                            \           getbufvar(a:bufnr, '&columns')),
+                            \       ','))
+                elseif g:EditorConfig_max_line_indicator == 'exceeding'
+                    call setbufvar(a:bufnr, '&colorcolumn', '')
+                    for l:match in getmatches()
+                        if get(l:match, 'group', '') == 'ColorColumn'
+                            call matchdelete(get(l:match, 'id'))
+                        endif
+                    endfor
+                    call matchadd('ColorColumn',
+                        \ '\%' . (l:max_line_length + 1) . 'v.', 100)
+                elseif g:EditorConfig_max_line_indicator == 'fillexceeding'
+                    let &l:colorcolumn = ''
+                    for l:match in getmatches()
+                        if get(l:match, 'group', '') == 'ColorColumn'
+                            call matchdelete(get(l:match, 'id'))
+                        endif
+                    endfor
+                    call matchadd('ColorColumn',
+                        \ '\%'. (l:max_line_length + 1) . 'v.\+', -1)
+                endif
+            endif
+        endif
+    endif
+
+    call editorconfig#ApplyHooks(a:config)
+endfunction
+
+" }}}1
+
+function! s:TrimTrailingWhitespace() " {{{1
+    " Called from within a buffer-specific autocmd, so we can use '%'
+    if getbufvar('%', '&modifiable')
+        " don't lose user position when trimming trailing whitespace
+        let s:view = winsaveview()
+        try
+            silent! keeppatterns keepjumps %s/\s\+$//e
+        finally
+            call winrestview(s:view)
+        endtry
+    endif
+endfunction " }}}1
+
+function! s:IsRuleActive(name, config) " {{{1
+    return index(g:EditorConfig_disable_rules, a:name) < 0 &&
+                 \ has_key(a:config, a:name)
+endfunction "}}}1
+
+let &cpo = s:saved_cpo
+unlet! s:saved_cpo
+
+" vim: fdm=marker fdc=3
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/core/CMakeLists.txt
@@ -0,0 +1,53 @@
+# CMakeLists.txt for core testing in
+# editorconfig-core-vimscript and editorconfig-vim.
+
+# Copyright (c) 2011-2019 EditorConfig Team
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+#    this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+#    this list of conditions and the following disclaimer in the documentation
+#    and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# To perform the test, from the root of the project tree, run
+#   mkdir build
+#   cd build
+#   cmake ..
+#   ctest .
+
+cmake_minimum_required(VERSION 3.5)
+#set(CMAKE_LEGACY_CYGWIN_WIN32 0)
+
+# Do not check any compiler
+project(editorconfig-core-vimscript NONE)
+
+enable_testing()
+
+# The test executable to use
+if(NOT WIN32)
+    set(EDITORCONFIG_CMD "${CMAKE_SOURCE_DIR}/editorconfig")
+else()
+    set(EDITORCONFIG_CMD "${CMAKE_SOURCE_DIR}/editorconfig.bat")
+endif()
+set(EDITORCONFIG_CMD_IS_TARGET FALSE)
+
+add_subdirectory(tests)
+
+# CTestCustom.cmake contains platform-specific test configuration.
+configure_file(CTestCustom.cmake ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/core/CTestCustom.cmake
@@ -0,0 +1,41 @@
+# CTestCustom.cmake: Skip UTF-8 tests
+# Part of editorconfig-vim
+
+# Copyright (c) 2011-2019 EditorConfig Team
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+#    this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+#    this list of conditions and the following disclaimer in the documentation
+#    and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# Skip UTF8 tests on Windows for now per
+# https://github.com/editorconfig/editorconfig-core-c/pull/31#issue-154810185
+if(WIN32 AND (NOT "$ENV{RUN_UTF8}"))
+    message(WARNING "Skipping UTF-8 tests on this platform")
+    set(CTEST_CUSTOM_TESTS_IGNORE ${CTEST_CUSTOM_TESTS_IGNORE} g_utf_8_char)
+    set(CTEST_CUSTOM_TESTS_IGNORE ${CTEST_CUSTOM_TESTS_IGNORE} utf_8_char)
+endif()
+
+# Skip min_supported_value_length on Windows since that test seems to
+# cause Appveyor to hang.
+if(WIN32)
+    message(WARNING "Skipping min_supported_value_length test on this platform")
+    set(CTEST_CUSTOM_TESTS_IGNORE ${CTEST_CUSTOM_TESTS_IGNORE} min_supported_value_length)
+endif()
new file mode 100755
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/core/ecvbslib.vbs
@@ -0,0 +1,171 @@
+' ecvbslib.vbs: VBScript routines for use in
+' editorconfig-core-vimscript and editorconfig-vim.
+' Copyright (c) 2018--2019 Chris White.  All rights reserved.
+' Licensed CC-BY-SA, version 3.0 or any later version, at your option.
+
+' Remove CR and LF in a string
+function nocrlf(strin)
+    nocrlf = Replace(Replace(strin, vbCr, ""), vbLf, "")
+end function
+
+' === Base64 ================================================================
+' from https://stackoverflow.com/a/40118072/2877364 by
+' https://stackoverflow.com/users/45375/mklement0
+
+' Base64-encodes the specified string.
+' Parameter fAsUtf16LE determines how the input text is encoded at the
+' byte level before Base64 encoding is applied.
+' * Pass False to use UTF-8 encoding.
+' * Pass True to use UTF-16 LE encoding.
+Function Base64Encode(ByVal sText, ByVal fAsUtf16LE)
+
+    ' Use an aux. XML document with a Base64-encoded element.
+    ' Assigning the byte stream (array) returned by StrToBytes() to .NodeTypedValue
+    ' automatically performs Base64-encoding, whose result can then be accessed
+    ' as the element's text.
+    With CreateObject("Msxml2.DOMDocument").CreateElement("aux")
+        .DataType = "bin.base64"
+        if fAsUtf16LE then
+            .NodeTypedValue = StrToBytes(sText, "utf-16le", 2)
+        else
+            .NodeTypedValue = StrToBytes(sText, "utf-8", 3)
+        end if
+        Base64Encode = nocrlf(.Text)    ' No line breaks; MSXML adds them.
+    End With
+
+End Function
+
+' Decodes the specified Base64-encoded string.
+' If the decoded string's original encoding was:
+' * UTF-8, pass False for fIsUtf16LE.
+' * UTF-16 LE, pass True for fIsUtf16LE.
+Function Base64Decode(ByVal sBase64EncodedText, ByVal fIsUtf16LE)
+
+    Dim sTextEncoding
+    if fIsUtf16LE Then sTextEncoding = "utf-16le" Else sTextEncoding = "utf-8"
+
+    ' Use an aux. XML document with a Base64-encoded element.
+    ' Assigning the encoded text to .Text makes the decoded byte array
+    ' available via .nodeTypedValue, which we can pass to BytesToStr()
+    With CreateObject("Msxml2.DOMDocument").CreateElement("aux")
+        .DataType = "bin.base64"
+        .Text = sBase64EncodedText
+        Base64Decode = BytesToStr(.NodeTypedValue, sTextEncoding)
+    End With
+
+End Function
+
+' Returns a binary representation (byte array) of the specified string in
+' the specified text encoding, such as "utf-8" or "utf-16le".
+' Pass the number of bytes that the encoding's BOM uses as iBomByteCount;
+' pass 0 to include the BOM in the output.
+function StrToBytes(ByVal sText, ByVal sTextEncoding, ByVal iBomByteCount)
+
+    ' Create a text string with the specified encoding and then
+    ' get its binary (byte array) representation.
+    With CreateObject("ADODB.Stream")
+        ' Create a stream with the specified text encoding...
+        .Type = 2  ' adTypeText
+        .Charset = sTextEncoding
+        .Open
+        .WriteText sText
+        ' ... and convert it to a binary stream to get a byte-array
+        ' representation.
+        .Position = 0
+        .Type = 1  ' adTypeBinary
+        .Position = iBomByteCount ' skip the BOM
+        StrToBytes = .Read
+        .Close
+    End With
+
+end function
+
+' Returns a string that corresponds to the specified byte array, interpreted
+' with the specified text encoding, such as "utf-8" or "utf-16le".
+function BytesToStr(ByVal byteArray, ByVal sTextEncoding)
+
+    If LCase(sTextEncoding) = "utf-16le" then
+        ' UTF-16 LE happens to be VBScript's internal encoding, so we can
+        ' take a shortcut and use CStr() to directly convert the byte array
+        ' to a string.
+        BytesToStr = CStr(byteArray)
+    Else ' Convert the specified text encoding to a VBScript string.
+        ' Create a binary stream and copy the input byte array to it.
+        With CreateObject("ADODB.Stream")
+            .Type = 1 ' adTypeBinary
+            .Open
+            .Write byteArray
+            ' Now change the type to text, set the encoding, and output the
+            ' result as text.
+            .Position = 0
+            .Type = 2 ' adTypeText
+            .CharSet = sTextEncoding
+            BytesToStr = .ReadText
+            .Close
+        End With
+    End If
+
+end function
+
+' === Runner ================================================================
+
+' Run a command, copy its stdout/stderr to ours, and return its exit
+' status.
+' Modified from https://stackoverflow.com/a/32493083/2877364 by
+' https://stackoverflow.com/users/3191599/nate-barbettini .
+' See also https://www.vbsedit.com/html/4c5b06ac-dc45-4ec2-aca1-f168bab75483.asp
+function RunCommandAndEcho(strCommand)
+    Const WshRunning = 0
+    Const WshFinished = 1
+    Const WshFailed = 2
+
+    Set WshShell = CreateObject("WScript.Shell")
+    'WScript.Echo "Running >>" & strCommand & "<<..."
+    Set WshShellExec = WshShell.Exec(strCommand)
+
+    Do While WshShellExec.Status = WshRunning
+        'WScript.Echo "Waiting..."
+        WScript.Sleep 100
+    Loop
+
+    if not WshShellExec.StdOut.AtEndOfStream then
+        WScript.StdOut.Write(WshShellExec.StdOut.ReadAll())
+    end if
+
+    if not WshShellExec.StdErr.AtEndOfStream then
+        WScript.StdErr.Write(WshShellExec.StdErr.ReadAll())
+    end if
+
+    RunCommandAndEcho = WshShellExec.ExitCode
+end function
+
+' === Argument processing ===================================================
+
+function MakeY64Args(args)
+
+    dim b64args(100)    ' 100 = arbitrary max
+
+    ' Make Y64-flavored base64 versions of each arg so we don't have to
+    ' worry about quoting issues while executing PowerShell.
+
+    idx=0
+    For Each arg In args
+        b64args(idx) = Base64Encode(nocrlf(arg), False)
+        ' Y64 flavor of Base64
+        b64args(idx) = replace( _
+        replace( _
+            replace(b64args(idx), "+", "."), _
+            "/", "_" ), _
+        "=", "-")
+        'Wscript.Echo cstr(idx) & ": >" & arg & "< = >" & b64args(idx) & "<"
+        'Wscript.Echo b64args(idx)
+        idx = idx+1
+    Next
+
+    MakeY64Args = b64args
+end function
+
+Function QuoteForShell(strIn)
+    QuoteForShell = """" & _
+        replace(strIn, """", """""") & """"
+End Function
new file mode 100755
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/core/ecvimlib.ps1
@@ -0,0 +1,140 @@
+# ecvimlib.ps1: Editorconfig Vimscript core CLI, PowerShell version,
+# library routines.
+# Copyright (c) 2018--2019 Chris White.  All rights reserved.
+# Licensed CC-BY-SA, version 3.0 or any later version, at your option.
+#
+# N.B.: debug output uses Warning only because those are displayed by default.
+
+#Requires -Version 3
+
+# Get the directory of this script.  From
+# https://stackoverflow.com/a/5466355/2877364 by
+# https://stackoverflow.com/users/23283/jaredpar
+
+$global:DIR = $PSScriptRoot
+
+### Set up debugging output ============================================
+
+$global:debug=$env:EDITORCONFIG_DEBUG  # Debug filename
+
+if($global:debug -and ($global:debug -notmatch '^/')) {
+    # Relative to this script unless it starts with a slash.  This is because
+    # cwd is usually not $DIR when testing.
+    $global:debug="${DIR}/${global:debug}"
+}
+
+### Process args =======================================================
+
+function de64_args($argv) {
+    $argv | % {
+        $b64 = $_ -replace '-','=' -replace '_','/' -replace '\.','+'
+        [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($b64))
+    }
+}
+
+### Helpers ============================================================
+
+# Append a string to $debug in UTF-8 rather than the default UTF-16
+filter global:D($file = $debug) {
+    if($debug) {
+        echo $_ | Out-File -FilePath $file -Encoding utf8 -Append
+    }
+}
+
+# Escape a string for Vim
+function global:vesc($str) {
+    return "'" + ($str -replace "'","''") + "'"
+}
+
+# Escape a string for a command-line argument.
+# See https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.arguments?view=netframework-4.7.2
+function global:argesc($arg) {
+    return '"' + ($arg -replace '"','"""') + '"'
+}
+
+### Find the Vim EXE ===================================================
+
+function global:Find-Vim
+{
+    if($env:VIM_EXE) {
+        if($debug) { echo "Using env Vim $($env:VIM_EXE)" | D }
+        return $env:VIM_EXE
+    }
+
+    $vims = @(get-childitem 'c:\program files*\vim\**\vim.exe' | `
+            sort LastWriteTime -Descending)     # @() => always array
+
+    # write-host ($vims | format-table | out-string)    # DEBUG
+    # write-host ($vims | get-member | out-string)
+    if($vims.count -gt 0) {
+        if($debug) { echo "Using found Vim $($vims[0].FullName)" | D }
+        return $vims[0].FullName
+    }
+
+    throw "Could not find vim.exe.  Please set VIM_EXE to the path to your Vim."
+} #Find-Vim
+
+### Runner =============================================================
+
+# Run a process with the given arguments.
+function global:run_process
+{
+    param(
+        [Parameter(Mandatory=$true, Position=0)][string]$run,
+        [string]$extrapath,
+        [string]$stdout,        # Redirect stdout to this file
+        [string]$stderr,        # Redirect stderr to this file
+        [string[]]$argv         # Arguments to $run
+    )
+    $si = new-object Diagnostics.ProcessStartInfo
+    if($extrapath) {
+        $si.EnvironmentVariables['path']+=";${extrapath}"
+    }
+    $si.FileName=$run
+
+    # Stringify the arguments (blech)
+    $argstr = $argv | % { (argesc $_) + ' ' }
+    $si.Arguments = $argstr;
+
+    if($debug) { echo "Running process $run with arguments >>$argstr<<" | D }
+
+    $si.UseShellExecute=$false
+    # DEBUG  $si.RedirectStandardInput=$true
+    if($stdout) {
+        if($debug) { echo "Saving stdout to ${stdout}" | D }
+        $si.RedirectStandardOutput=$true;
+    }
+    if($stderr) {
+        if($debug) { echo "Saving stderr to ${stderr}" | D }
+        $si.RedirectStandardError=$true;
+    }
+
+    $p = [Diagnostics.Process]::Start($si)
+    # DEBUG $p.StandardInput.Close()        # < /dev/null
+
+    $p.WaitForExit()
+    $retval = $p.ExitCode
+
+    if($stdout) {
+        echo "Standard output:" | D $stdout
+        $p.StandardOutput.ReadToEnd() | `
+            Out-File -FilePath $stdout -Encoding utf8 -Append
+    }
+
+    if($stderr) {
+        echo "Standard error:" | D $stderr
+        $p.StandardError.ReadToEnd() | `
+            Out-File -FilePath $stderr -Encoding utf8 -Append
+    }
+
+    $p.Close()
+
+    return $retval
+}
+
+if($debug) {
+    echo "======================================================" | D
+    Get-Date -format F | D
+}
+
+$global:VIM = Find-Vim
new file mode 100755
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/core/editorconfig
@@ -0,0 +1,219 @@
+#!/bin/bash
+# editorconfig: Editorconfig Vimscript core CLI
+# Copyright (c) 2018--2019 Chris White.  All rights reserved.
+# Licensed CC-BY-SA, version 3.0 or any later version, at your option.
+
+# Documentation {{{1
+helpstr=$(cat<<'EOF'
+editorconfig: command-line invoker for the Vimscript editorconfig core
+
+Normal usage:
+    editorconfig [-f <config-file name>] [-b <version>]
+        [-x <extra information>] <filenames...>
+
+The default <config-file name> is ".editorconfig".
+If -b is given, behave as <version>.
+If -x is given, the <extra information> is included in the debug-output file.
+
+Other options:
+    editorconfig -h, --help     Show this help
+    editorconfig -v, --version  Show version information
+
+Environment variables:
+    VIM_EXE             File/path of vim (default "vim")
+    EDITORCONFIG_DEBUG  File/path to which to append debug output
+
+EOF
+)
+
+# }}}1
+
+# Get the directory of this script into $this_script_dir. {{{1
+# From https://stackoverflow.com/a/246128/2877364 by
+# https://stackoverflow.com/users/407731 et al.
+
+this_script_dir=
+function get_dir()
+{
+    local script_source_path="${BASH_SOURCE[0]}"
+    while [ -h "$script_source_path" ]; do
+        # resolve $script_source_path until the file is no longer a symlink
+        this_script_dir="$( cd -P "$( dirname "$script_source_path" )" >/dev/null && pwd )"
+        script_source_path="$(readlink "$script_source_path")"
+        [[ $script_source_path != /* ]] && script_source_path="$this_script_dir/$script_source_path"
+            # if $script_source_path was a relative symlink, we need to resolve
+            # it relative to the path where the symlink file was located
+    done
+    this_script_dir="$( cd -P "$( dirname "$script_source_path" )" >/dev/null && pwd )"
+} #get_dir()
+
+get_dir
+
+# }}}1
+
+# Setup debug output, if $EDITORCONFIG_DEBUG is given {{{1
+debug="${EDITORCONFIG_DEBUG}"   # Debug filename
+if [[ $debug && $debug != /* ]]; then     # Relative to this script unless it
+    debug="${this_script_dir}/${debug}"     # starts with a slash.  This is because
+fi                              # cwd is usually not $this_script_dir when testing.
+if [[ $debug ]] && ! touch "$debug"; then
+    echo "Could not write file '$debug' - aborting" 1>&2
+    exit 1
+fi
+
+[[ $debug ]] && echo "$(date) ==================================" >> "$debug"
+
+# }}}1
+
+# Option processing {{{1
+
+# Use a manually-specified Vim, if any
+if [[ $VIM_EXE ]]; then
+    vim_pgm="$VIM_EXE"
+else
+    vim_pgm="vim"
+fi
+
+# Command-line options
+confname=
+ver=
+print_ver=
+extra_info=
+
+while getopts 'hvf:b:-:x:' opt ; do
+    case "$opt" in
+        (v) print_ver=1
+            ;;
+
+        (f) confname="$OPTARG"
+            ;;
+
+        (b) ver="$OPTARG"
+            ;;
+
+        (-) case "$OPTARG" in   # hacky long-option processing
+                version)    print_ver=1
+                            ;;
+                dummy)      # A dummy option so that I can test
+                            # list-valued EDITORCONFIG_CMD
+                            ;;
+                help)       echo "$helpstr"
+                            exit 0
+                            ;;
+            esac
+            ;;
+
+        (h) echo "$helpstr"
+            exit 0
+            ;;
+
+        # A way to put the test name into the log
+        (x) extra_info="$OPTARG"
+            ;;
+
+    esac
+done
+
+shift $(( $OPTIND - 1 ))
+
+if [[ $print_ver ]]; then
+    echo "EditorConfig VimScript Core Version 0.12.2"
+    exit 0
+fi
+
+if (( "$#" < 1 )); then
+    exit 1
+fi
+
+if [[ $1 = '-' ]]; then
+    echo "Reading filenames from stdin not yet supported" 1>&2  # TODO
+    exit 1
+fi
+
+# }}}1
+
+# Build the Vim command line {{{1
+
+fn="$(mktemp)"      # Vim will write the settings into here.  ~stdout.
+script_output_fn="${debug:+$(mktemp)}"  # Vim's :messages.  ~stderr.
+
+cmd="call editorconfig_core#currbuf_cli({"
+
+# Names
+cmd+="'output':'${fn//\'/\'\'}', "
+    # filename to put the settings in
+[[ $debug ]] && cmd+=" 'dump':'${script_output_fn//\'/\'\'}', "
+    # where to put debug info
+
+# Filenames to get the settings for
+cmd+="'target':["
+for f in "$@" ; do
+    cmd+="'${f//\'/\'\'}', "
+done
+cmd+="],"
+    # filename to get the settings for
+
+# Job
+cmd+="}, {"
+[[ $confname ]] && cmd+="'config':'${confname//\'/\'\'}', "
+    # config name (e.g., .editorconfig)
+[[ $ver ]] && cmd+="'version':'${ver//\'/\'\'}', "
+    # version number we should behave as
+cmd+="})"
+
+vim_args=(
+    -c "set runtimepath+=$this_script_dir/../.."
+    -c "$cmd"
+)
+
+# }}}1
+
+# Run the editorconfig core through Vim {{{1
+# Thanks for options to
+# http://vim.wikia.com/wiki/Vim_as_a_system_interpreter_for_vimscript .
+# Add -V1 to the below for debugging output.
+# Do not output anything to stdout or stderr,
+# since it messes up ctest's interpretation
+# of the results.
+
+"$vim_pgm" -nNes -i NONE -u NONE -U NONE \
+    "${vim_args[@]}" \
+    </dev/null &>> "${debug:-/dev/null}"
+vimstatus="$?"
+if [[ $vimstatus -eq 0 ]]; then
+    cat "$fn"
+fi
+
+# }}}1
+
+# Produce debug output {{{1
+# Debug output cannot be included on stdout or stderr, because
+# ctest's regex check looks both of those places.  Therefore, dump to a
+# separate debugging file.
+if [[ $debug ]]
+then
+    [[ $extra_info ]] && echo "--- $extra_info ---" >> "$debug"
+    echo "Vim in $vim_pgm" >> "$debug"
+    echo "Current directory: $(pwd)" >> "$debug"
+    echo "Script directory: $this_script_dir" >> "$debug"
+    echo Vim args: "${vim_args[@]}" >> "$debug"
+    #od -c <<<"${vim_args[@]}" >> "$debug"
+    echo "Vim returned $vimstatus" >> "$debug"
+    echo "Vim messages were: " >> "$debug"
+    cat "$script_output_fn" >> "$debug"
+    echo "Output was:" >> "$debug"
+    od -c "$fn" >> "$debug"
+
+    rm -f "$script_output_fn"
+fi
+
+# }}}1
+
+# Cleanup {{{1
+
+rm -f "$fn"
+
+# }}}1
+
+exit "$vimstatus"   # forward the Vim exit status to the caller
+# vi: set ft=sh fdm=marker:
new file mode 100755
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/core/editorconfig.bat
@@ -0,0 +1,11 @@
+@echo off
+:: editorconfig.bat: First-level invoker for editorconfig-core-vimscript
+:: and editorconfig-vim.
+:: Just passes the full command line to editorconfig1.vbs, since VBScript
+:: applies very simple quoting rules when it parses a command line.
+:: Copyright (c) 2018--2019 Chris White.  All rights reserved.
+:: Licensed CC-BY-SA, version 3.0 or any later version, at your option.
+set here=%~dp0
+
+cscript //Nologo "%here%editorconfig1.vbs" %*
+:: %* has the whole command line
new file mode 100755
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/core/editorconfig1.vbs
@@ -0,0 +1,39 @@
+' editorconfig1.vbs: run by editorconfig.bat
+' runs editorconfig2.ps1
+' Part of editorconfig-core-vimscript and editorconfig-vim.
+'
+' Copyright (c) 2018--2019 Chris White.  All rights reserved.
+' Licensed CC-BY-SA, version 3.0 or any later version, at your option.
+'
+' Modified from
+' https://stackoverflow.com/a/2470557/2877364 by
+' https://stackoverflow.com/users/2441/aphoria
+
+' Thanks to https://www.geekshangout.com/vbs-script-to-get-the-location-of-the-current-script/
+currentScriptPath = Replace(WScript.ScriptFullName, WScript.ScriptName, "")
+
+' Load our common library.  Thanks to https://stackoverflow.com/a/316169/2877364
+With CreateObject("Scripting.FileSystemObject")
+   executeGlobal .openTextFile(currentScriptPath & "ecvbslib.vbs").readAll()
+End With
+
+' === MAIN ==================================================================
+
+' Encode all the arguments as modified base64 so there will be no quoting
+' issues when we invoke powershell.
+b64args = MakeY64Args(Wscript.Arguments)
+
+' Quote script name just in case
+ps1name = QuoteForShell(currentScriptPath & "editorconfig2.ps1")
+'Wscript.Echo "Script is in " & ps1name
+
+if True then
+    retval = RunCommandAndEcho( "powershell.exe" & _
+        " -executionpolicy bypass -file " & ps1name & " " & join(b64args) _
+    )
+        ' add -noexit to leave window open so you can see error messages
+
+    WScript.Quit retval
+end if
+
+' vi: set ts=4 sts=4 sw=4 et ai:
new file mode 100755
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/core/editorconfig2.ps1
@@ -0,0 +1,218 @@
+# editorconfig2.ps1: Editorconfig Vimscript core CLI, PowerShell version
+# Copyright (c) 2018--2019 Chris White.  All rights reserved.
+# Licensed CC-BY-SA, version 3.0 or any later version, at your option.
+# Thanks to https://cecs.wright.edu/~pmateti/Courses/233/Labs/Scripting/bashVsPowerShellTable.html
+# by Gallagher and Mateti.
+
+#Requires -Version 3
+
+. "$PSScriptRoot\ecvimlib.ps1"
+
+# Argument parsing =================================================== {{{1
+
+$argv = @(de64_args($args))
+
+# Defaults
+$report_version = $false
+$set_version = ''
+$config_name = '.editorconfig'
+$extra_info = ''
+$files=@()
+
+# Hand-parse - pretend we're sort of like getopt.
+$idx = 0
+while($idx -lt $argv.count) {
+    $a = $argv[$idx]
+
+    switch -CaseSensitive -Regex ($a) {
+        '^(-v|--version)$' { $report_version = $true }
+
+        '^--dummy$' {
+            # A dummy option so that I can test list-valued EDITORCONFIG_CMD
+        }
+
+        '^-f$' {
+            if($idx -eq ($argv.count-1)) {
+                throw '-f <filename>: no filename provided'
+            } else {
+                ++$idx
+                $config_name = $argv[$idx]
+            }
+        } #-f
+
+        '^-b$' {
+            if($idx -eq ($argv.count-1)) {
+                throw '-b <version>: no version provided'
+            } else {
+                ++$idx
+                $set_version = $argv[$idx]
+            }
+        } #-b
+
+        '^-x$' {
+            if($idx -eq ($argv.count-1)) {
+                throw '-x <extra info>: no info provided'
+            } else {
+                ++$idx
+                $extra_info = $argv[$idx]
+            }
+        } #-x
+
+        '^--$' {    # End of options, so capture the rest as filenames
+            ++$idx;
+            while($idx -lt $argv.count) {
+                $files += $argv[$idx]
+            }
+        }
+
+        default { $files += $a }
+    }
+
+    ++$idx
+} # end foreach argument
+
+# }}}1
+# Argument processing ================================================ {{{1
+
+if($debug) {
+    if($extra_info -ne '') {
+        echo "--- $extra_info --- "             | D
+    }
+
+    echo "Running in       $DIR"                | D
+    echo "Vim executable:  $VIM"                | D
+    echo "report version?  $report_version"     | D
+    echo "set version to:  $set_version"        | D
+    echo "config filename: $config_name"        | D
+    echo "Filenames:       $files"              | D
+    echo "Args:            $args"               | D
+    echo "Decoded args:    $argv"               | D
+}
+
+if($report_version) {
+    echo "EditorConfig VimScript Core Version 0.12.2"
+    exit
+}
+
+if($files.count -lt 1) {
+    exit
+}
+
+if($files[0] -eq '-') {
+    echo "Reading filenames from stdin not yet supported" # TODO
+    exit 1
+}
+
+$fn=[System.IO.Path]::GetTempFileName();
+    # Vim will write the settings into here.  Sort of like stdout.
+$script_output_fn = ''
+if($debug) {
+    $script_output_fn = [System.IO.Path]::GetTempFileName()
+}
+
+# Permit throwing in setup commands
+$cmd = ''
+if($env:EDITORCONFIG_EXTRA) {
+    $cmd += $env:EDITORCONFIG_EXTRA + ' | '
+}
+
+# }}}1
+# Build Vim command line ============================================= {{{1
+$cmd += 'call editorconfig_core#currbuf_cli({'
+
+# Names
+$cmd += "'output':" + (vesc($fn)) + ", "
+    # filename to put the settings in
+if($debug) {
+    $cmd += " 'dump':" + (vesc($script_output_fn)) + ", "
+    # where to put debug info
+}
+
+# Filenames to get the settings for
+$cmd += "'target':["
+ForEach ($item in $files) {
+    $cmd += (vesc($item)) + ", "
+}
+$cmd += "],"
+
+# Job
+$cmd += "}, {"
+if($config_name) { $cmd += "'config':" + (vesc($config_name)) + ", " }
+    # config name (e.g., .editorconfig)
+if($set_version) { $cmd += "'version':" + (vesc($set_version)) + ", " }
+    # version number we should behave as
+$cmd += "})"
+
+#$cmd =':q!'  # DEBUG
+if($debug) { echo "Using Vim command ${cmd}" | D }
+$vim_args = @(
+    '-c', "set runtimepath+=${DIR}\..\..",
+    '-c', $cmd,
+    '-c', 'quit!'   # TODO write a wrapper that will cquit on exception
+)
+
+# Run editorconfig.  Thanks for options to
+# http://vim.wikia.com/wiki/Vim_as_a_system_interpreter_for_vimscript .
+# Add -V1 to the below for debugging output.
+# Do not output anything to stdout or stderr,
+# since it messes up ctest's interpretation
+# of the results.
+
+$basic_args = '-nNes','-i','NONE','-u','NONE','-U','NONE'   #, '-V1'
+
+# }}}1
+# Run Vim ============================================================ {{{1
+
+if($debug) { echo "Running vim ${VIM}" | D }
+$vimstatus = run_process $VIM -stdout $debug -stderr $debug `
+    -argv ($basic_args+$vim_args)
+if($debug) { echo "Done running vim" | D }
+
+if($vimstatus -eq 0) {
+    cat $fn
+}
+
+# }}}1
+# Produce debug output =============================================== {{{1
+
+# Debug output cannot be included on stdout or stderr, because
+# ctest's regex check looks both of those places.  Therefore, dump to a
+# separate debugging file.
+
+if($debug) {
+    echo "Current directory:" | D
+    (get-item -path '.').FullName | D
+    echo "Script directory: $DIR" | D
+###     echo Vim args: "${vim_args[@]}" >> "$debug"
+###     #od -c <<<"${vim_args[@]}" >> "$debug"
+    echo "Vim returned $vimstatus" | D
+    echo "Vim messages were: " | D
+    cat $script_output_fn | D
+    echo "Output was:" | D
+
+    # Modified from https://www.itprotoday.com/powershell/get-hex-dumps-files-powershell
+    Get-Content $script_output_fn -Encoding Byte -ReadCount 16 | `
+    ForEach-Object {
+        $output = ""
+        $chars = ''
+        foreach ( $byte in $_ ) {
+            $output += "{0:X2} " -f $byte
+            if( ($byte -ge 32) -and ($byte -le 127) ) {
+                $chars += [char]$byte
+            } else {
+                $chars += '.'
+            }
+        }
+        $output + ' ' + $chars
+    } | D
+
+    del -Force $script_output_fn
+} #endif $debug
+
+# }}}1
+
+del -Force $fn
+
+exit $vimstatus
+
+# vi: set fdm=marker:
new file mode 100755
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/fetch-vim.bat
@@ -0,0 +1,12 @@
+:: fetch-vim.bat: Fetch vim if necessary
+:: For use in the editorconfig-vim Appveyor build
+:: Copyright (c) 2018--2019 Chris White.  All rights reserved.
+:: Licensed Apache 2.0, or any later version, at your option.
+
+:: If it's already been loaded from the cache, we're done
+if exist C:\vim\vim\vim80\vim.exe exit
+
+:: Otherwise, download and unzip it.
+appveyor DownloadFile https://github.com/cxw42/editorconfig-core-vimscript/releases/download/v0.1.0/vim.7z
+
+7z x vim.7z -oC:\vim
new file mode 100755
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/fetch-vim.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# fetch-vim.bat: Fetch vim if necessary
+# For use in the editorconfig-vim Appveyor build
+# Copyright (c) 2018--2019 Chris White.  All rights reserved.
+# Licensed Apache 2.0, or any later version, at your option.
+
+# Debugging
+set -x
+set -o nounset
+#set -o errexit
+
+# Basic system info
+uname -a
+pwd
+ls -l
+
+echo "VIM_EXE: $VIM_EXE"
+set
+
+# If it's already been loaded from the cache, we're done
+if [[ -x "$VIM_EXE" ]]; then
+    echo Vim found in cache at "$VIM_EXE"
+    exit 0
+fi
+
+# Otherwise, clone and build it
+WHITHER="$APPVEYOR_BUILD_FOLDER/vim"
+
+git clone https://github.com/vim/vim-appimage.git
+cd vim-appimage
+git submodule update --init --recursive
+
+cd vim/src
+./configure --with-features=huge --prefix="$WHITHER" --enable-fail-if-missing
+make -j2    # Free tier provides two cores
+make install
+./vim --version
+cd $APPVEYOR_BUILD_FOLDER
+find . -type f -name vim -exec ls -l {} +
+
+echo Done fetching and installing vim
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/plugin/.gitignore
@@ -0,0 +1,2 @@
+# Where bundler installs local Gemfile dependencies
+/vendor/
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/plugin/Gemfile
@@ -0,0 +1,5 @@
+source 'https://rubygems.org'
+
+gem 'rake', '~> 12.3.3'
+gem 'rspec', '~> 3.4.0'
+gem 'vimrunner', '~> 0.3.1'
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/plugin/Gemfile.lock
@@ -0,0 +1,27 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    diff-lcs (1.2.5)
+    rake (12.3.3)
+    rspec (3.4.0)
+      rspec-core (~> 3.4.0)
+      rspec-expectations (~> 3.4.0)
+      rspec-mocks (~> 3.4.0)
+    rspec-core (3.4.1)
+      rspec-support (~> 3.4.0)
+    rspec-expectations (3.4.0)
+      diff-lcs (>= 1.2.0, < 2.0)
+      rspec-support (~> 3.4.0)
+    rspec-mocks (3.4.0)
+      diff-lcs (>= 1.2.0, < 2.0)
+      rspec-support (~> 3.4.0)
+    rspec-support (3.4.1)
+    vimrunner (0.3.1)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  rake (~> 12.3.3)
+  rspec (~> 3.4.0)
+  vimrunner (~> 0.3.1)
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/plugin/Rakefile
@@ -0,0 +1,8 @@
+#
+# run `rake` to run tests
+
+require 'rspec/core/rake_task'
+
+RSpec::Core::RakeTask.new(:spec)
+
+task :default => :spec
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/plugin/spec/.editorconfig
@@ -0,0 +1,4 @@
+[*.rb]
+indent_style = space
+indent_size = 2
+end_of_line = lf
new file mode 100644
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/plugin/spec/editorconfig_spec.rb
@@ -0,0 +1,169 @@
+require 'vimrunner'
+
+def create_vim(*initial_commands)
+  vim = Vimrunner.start
+  initial_commands.each do |cmd|
+    vim.command cmd
+  end
+  vim.add_plugin(File.expand_path('../../../..', __FILE__), 'plugin/editorconfig.vim')
+  return vim
+end
+
+# The base path of the testing files
+BASE_PATH = File.expand_path('../plugin_tests/test_files/', __FILE__)
+
+# file_name is the file name that should be open by Vim
+# expected_values is a Hash that contains all the Vim options we need to test
+def test_editorconfig(vim, file_name, expected_values)
+  vim.edit(File.join(BASE_PATH, file_name))
+
+  expected_values.each do |key, val|
+    vimval = vim.echo("&l:#{key}")
+    expect(vimval).to eq(val), "key #{key} had value #{vimval}, but I expected #{val}"
+  end
+
+  vim.command 'bd!'
+end
+
+def test_instance(vim)
+  describe 'plugin/editorconfig.vim' do
+    after(:all) do
+      vim.kill
+    end
+
+    describe '#all' do
+      it '3_space.py' do
+        test_editorconfig vim, '3_space.txt',
+          expandtab: '1',
+          shiftwidth: '3',
+          tabstop: '3'
+      end
+    end
+
+    it '4_space.py' do
+      test_editorconfig vim, '4_space.py',
+        expandtab: '1',
+        shiftwidth: '4',
+        tabstop: '8'
+    end
+
+    it 'space.txt' do
+      test_editorconfig vim, 'space.txt',
+        expandtab: '1',
+        shiftwidth: vim.echo('&l:tabstop')
+    end
+
+    it 'tab.txt' do
+      test_editorconfig vim, 'tab.txt',
+        expandtab: '0'
+    end
+
+    it '4_tab.txt' do
+      test_editorconfig vim, '4_tab.txt',
+        expandtab: '0',
+        shiftwidth: '4',
+        tabstop: '4'
+    end
+
+    it '4_tab_width_of_8' do
+      test_editorconfig vim, '4_tab_width_of_8.txt',
+        expandtab: '0',
+        shiftwidth: '4',
+        tabstop: '8'
+    end
+
+    it 'lf.txt' do
+      test_editorconfig vim, 'lf.txt',
+        fileformat: 'unix'
+    end
+
+    it 'crlf.txt' do
+      test_editorconfig vim, 'crlf.txt',
+        fileformat: 'dos'
+    end
+
+    it 'cr.txt' do
+      test_editorconfig vim, 'cr.txt',
+        fileformat: 'mac'
+    end
+
+    it 'utf-8.txt' do
+      test_editorconfig vim, 'utf-8.txt',
+        fileencoding: 'utf-8',
+        bomb: '0'
+    end
+
+    it 'utf-8-bom.txt' do
+      test_editorconfig vim, 'utf-8-bom.txt',
+        fileencoding: 'utf-8',
+        bomb: '1'
+    end
+
+    it 'utf-16be.txt' do
+      test_editorconfig vim, 'utf-16be.txt',
+        fileencoding: 'utf-16'
+    end
+
+    it 'utf-16le.txt' do
+      test_editorconfig vim, 'utf-16le.txt',
+        fileencoding: 'utf-16le'
+    end
+
+    it 'latin1.txt' do
+      test_editorconfig vim, 'latin1.txt',
+        fileencoding: 'latin1'
+    end
+
+    # insert_final_newline by PreserveNoEOL tests are omitted, since they are not supported
+    if vim.echo("exists('+fixendofline')") == '1'
+      it 'with_newline.txt' do
+        test_editorconfig vim, 'with_newline.txt',
+          fixendofline: '1'
+      end
+
+      it 'without_newline.txt' do
+        test_editorconfig vim, 'without_newline.txt',
+          fixendofline: '0'
+      end
+    end
+  end
+end
+
+# Test the vim core
+(lambda do
+  puts 'Testing default'
+  vim = create_vim
+  test_instance vim
+end).call
+
+# Test the vim core with an express setting
+(lambda do
+  puts 'Testing with express vim_core mode'
+  vim = create_vim("let g:EditorConfig_core_mode='vim_core'")
+  test_instance vim
+end).call
+
+# Test with external-core mode, but no external core defined
+(lambda do
+  puts 'Testing with fallback to vim_core mode'
+  vim = create_vim("let g:EditorConfig_core_mode='external_command'")
+  test_instance vim
+end).call
+
+# Test with an external core, if desired
+extcore = ENV['EDITORCONFIG_VIM_EXTERNAL_CORE']
+if extcore
+  puts "Testing with external_command #{extcore}"
+  vim = create_vim(
+    "let g:EditorConfig_core_mode='external_command'",
+    "let g:EditorConfig_exec_path='#{extcore}'",
+  )
+  test_instance vim
+end
+
+# Test the vim core with latin1 encoding
+(lambda do
+  puts 'Testing with express vim_core mode'
+  vim = create_vim("set encoding=latin1")
+  test_instance vim
+end).call
new file mode 100755
--- /dev/null
+++ b/runtime/pack/dist/opt/editorconfig/tests/travis-test.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+# travis-test.sh: Script for running editorconfig-vim tests under Travis CI.
+# Copyright (c) 2019 Chris White.  All rights reserved.
+# Licensed Apache, version 2.0 or any later version, at your option.
+
+# Error exit; debug output
+set -vxEeuo pipefail
+
+# Permit `travis-test.sh plugin` if TEST_WHICH is unset
+if [[ ( ! "${TEST_WHICH:-}" ) && "${1:-}" ]]; then
+    export TEST_WHICH="$1"
+fi
+
+if [[ ! "${TEST_WHICH:-}" ]]; then
+    cat <<EOT
+Usage: $0 \$WHICH
+  or:  TEST_WHICH=\$WHICH $0
+Run automated tests of editorconfig-vim
+
+\$WHICH can be "core" or "plugin".
+EOT
+    exit 2
+fi
+
+if [[ "$TEST_WHICH" = 'plugin' ]]; then       # test plugin
+
+    # If not running from Travis, do what Travis would have
+    # done for us.
+    if [[ ! "${BUNDLE_GEMFILE:-}" ]]; then
+        here="$(cd "$(dirname "$0")" &>/dev/null ; pwd)"
+        export BUNDLE_GEMFILE="${here}/plugin/Gemfile"
+        # Install into tests/plugin/vendor.  Don't clear it first,
+        # since you can clear it yourself if you're running from a
+        # dev environment.
+        bundle install --jobs=3 --retry=3 --deployment
+    fi
+
+    # Use the standalone Vimscript EditorConfig core to test the plugin's
+    # external_command mode
+    export EDITORCONFIG_VIM_EXTERNAL_CORE=tests/core/editorconfig
+
+    bundle exec rspec tests/plugin/spec/editorconfig_spec.rb
+
+elif [[ "$TEST_WHICH" = 'core' ]]; then     # test core
+    cd tests/core
+    mkdir -p build  # May already exist if running from a dev env
+    cd build
+    cmake ..
+    ctest . --output-on-failure -VV -C Debug
+    # -C Debug: for Visual Studio builds, you have to specify
+    # a configuration.
+
+else
+    echo 'Invalid TEST_WHICH value' 1>&2
+    exit 1
+fi