Add editorconfig-vim

This commit is contained in:
Anthony Rose 2021-04-07 20:25:35 +01:00
parent 6dcddbb0dc
commit df64adb290
36 changed files with 3545 additions and 0 deletions

View file

@ -0,0 +1,107 @@
# 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 UTF-8 tests on Windows.
- cmd: echo "Reminder - did not try UTF-8"
- sh: echo "Reminder - tried UTF-8"
on_failure:
- echo "failed"
- cmd: type tests\core\build\Testing\Temporary\LastTest.log
- sh: cat tests/core/build/Testing/Temporary/LastTest.log

View file

@ -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

View file

@ -0,0 +1,8 @@
tags
tests/**/build
tests/**/.bundle
# Editor backup files
*.swp
*~
~*

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,6 @@
Contributors to the EditorConfig Vim Plugin:
Hong Xu
Trey Hunner
Kent Frazier
Chris White

View file

@ -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.

View file

@ -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=:

View file

@ -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 3 sub-directories in this runtime directory now: "autoload",
"doc" 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

View file

@ -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

View file

@ -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:

View file

@ -0,0 +1,465 @@
" 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%(^|[^\\])\{'
"LEFT_BRACE = re.compile(
" r"""
"
" (?: ^ | [^\\] ) # Beginning of string or a character besides "\"
"
" \{ # "{"
"
" """, re.VERBOSE
")
let s:RIGHT_BRACE = '\v%(^|[^\\])\}'
"RIGHT_BRACE = re.compile(
" r"""
"
" (?: ^ | [^\\] ) # Beginning of string or a character besides "\"
"
" \} # "}"
"
" """, 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:

View file

@ -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:

View file

@ -0,0 +1,273 @@
" 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 = 50
let s:MAX_PROPERTY_VALUE = 255
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)
let l:oldenc = &encoding
if !filereadable(a:config_filename)
return {}
endif
try " so &encoding will always be reset
let &encoding = 'utf-8' " so readfile() will strip BOM
let l:lines = readfile(a:config_filename)
let result = s:parse(a:config_filename, a:target_filename, l:lines)
catch
let &encoding = l:oldenc
" rethrow, but with a prefix since throw 'Vim...' fails.
throw 'Could not read editorconfig file at ' . v:throwpoint . ': ' . string(v:exception)
endtry
let &encoding = l:oldenc
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
if l:optval =~# '\v[;#]'
" ';' and '#' are comment delimiters only if
" preceded by a spacing character
let l:m = matchlist(l:optval, '\v(.{-})\s[;#]')
if len(l:m)
let l:optval = l:m[1]
endif
" ; and # can be escaped with backslash.
let l:optval = substitute(l:optval, '\v\\([;#])', '\1', 'g')
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:

View file

@ -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:

View file

@ -0,0 +1,203 @@
*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", otherwise there will be no max line indicator.
"line": the right column of the max line length column will be
highlighted, made possible by setting 'colorcolumn' to
"max_line_length + 1".
"fill": all the columns to the right of the max line length column
will be highlighted, made possible by setting 'colorcolumn'
to a list of numbers 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, made
possible by adding a match for the ColorColumn group.
"none": no max line length indicator will be shown. This is the
recommended value when you do not want any indicator to be
shown, but values other than "line" or "fill" would 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 = "none"
<
The default value is "line".
*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_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

View file

@ -0,0 +1,3 @@
#!/bin/sh
zip -r editorconfig-vim-$*.zip plugin/* autoload/* doc/*

View file

@ -0,0 +1,525 @@
" 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.
"
if v:version < 700
finish
endif
" check whether this script is already loaded
if 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
" 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() " {{{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.
if has('win32') && empty(matchstr(&shell, 'sh'))
let s:old_shellslash = &l:shellslash
setlocal noshellslash
endif
endfunction " }}}2
function! s:ResetShellSlash() " {{{2
" reset shellslash to the user-set value, if any
if exists('s:old_shellslash')
let &l: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() abort " Apply config to the current buffer {{{1
let b:editorconfig_tried = 1
let l:buffer_name = expand('%:p')
" ignore buffers without a name
if empty(l:buffer_name)
return
endif
if exists("b:EditorConfig_disable") && b:EditorConfig_disable
if g:EditorConfig_verbose
echo 'Skipping EditorConfig for buffer "' . l:buffer_name . '"'
endif
return
endif
" Check if any .editorconfig does exist
let l:conf_files = s:GetFilenames(expand('%:p:h'), '.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
" Ignore specific patterns
for pattern in g:EditorConfig_exclude_patterns
if l:buffer_name =~ pattern
return
endif
endfor
if s:editorconfig_core_mode ==? 'vim_core'
if s:UseConfigFiles_VimCore() == 0
let b:editorconfig_applied = 1
endif
elseif s:editorconfig_core_mode ==? 'external_command'
call s:UseConfigFiles_ExternalCommand()
let b: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()
endif
augroup END
endfunction
" }}}2
" Commands {{{2
command! EditorConfigEnable call s:EditorConfigEnable(1)
command! EditorConfigDisable call s:EditorConfigEnable(0)
command! EditorConfigReload call s:UseConfigFiles() " Reload EditorConfig files
" }}}2
" On startup, enable the autocommands
call s:EditorConfigEnable(1)
" Always set the filetype for .editorconfig files
augroup editorconfig_dosini
autocmd!
autocmd BufNewFile,BufRead .editorconfig set filetype=dosini
augroup END
" }}}1
" UseConfigFiles function for different modes {{{1
function! s:UseConfigFiles_VimCore()
" Use the vimscript EditorConfig core
try
let l:config = editorconfig_core#handler#get_configurations(
\ { 'target': expand('%:p') } )
call s:ApplyConfig(l:config)
return 0 " success
catch
return 1 " failure
endtry
endfunction
function! s:UseConfigFiles_ExternalCommand()
" Use external EditorConfig core (e.g., the C core)
call s:DisableShellSlash()
let l:exec_path = shellescape(s:editorconfig_exec_path)
call s:ResetShellSlash()
call s:SpawnExternalParser(l:exec_path)
endfunction
function! s:SpawnExternalParser(cmd) " {{{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()
let l:cmd = l:cmd . ' ' . shellescape(expand('%:p'))
call s:ResetShellSlash()
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(l:config)
endfunction " }}}2
" }}}1
function! s:ApplyConfig(config) abort " Set the buffer options {{{1
" Only process normal buffers (do not treat help files as '.txt' files)
if !empty(&buftype)
return
endif
if g:EditorConfig_verbose
echo 'Options: ' . string(a:config)
endif
if s:IsRuleActive('indent_style', a:config)
if a:config["indent_style"] == "tab"
setl noexpandtab
elseif a:config["indent_style"] == "space"
setl expandtab
endif
endif
if s:IsRuleActive('tab_width', a:config)
let &l:tabstop = str2nr(a:config["tab_width"])
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"
let &l:shiftwidth = &l:tabstop
let &l:softtabstop = &l:shiftwidth
else
let l:indent_size = str2nr(a:config["indent_size"])
if l:indent_size > 0
let &l:shiftwidth = l:indent_size
let &l:softtabstop = &l:shiftwidth
endif
endif
endif
if s:IsRuleActive('end_of_line', a:config) &&
\ &l:modifiable
if a:config["end_of_line"] == "lf"
setl fileformat=unix
elseif a:config["end_of_line"] == "crlf"
setl fileformat=dos
elseif a:config["end_of_line"] == "cr"
setl fileformat=mac
endif
endif
if s:IsRuleActive('charset', a:config) &&
\ &l:modifiable
if a:config["charset"] == "utf-8"
setl fileencoding=utf-8
setl nobomb
elseif a:config["charset"] == "utf-8-bom"
setl fileencoding=utf-8
setl bomb
elseif a:config["charset"] == "latin1"
setl fileencoding=latin1
setl nobomb
elseif a:config["charset"] == "utf-16be"
setl fileencoding=utf-16be
setl bomb
elseif a:config["charset"] == "utf-16le"
setl fileencoding=utf-16le
setl bomb
endif
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'
autocmd BufWritePre <buffer> call s:TrimTrailingWhitespace()
endif
augroup END
if s:IsRuleActive('insert_final_newline', a:config)
if exists('+fixendofline')
if a:config["insert_final_newline"] == "false"
setl nofixendofline
else
setl fixendofline
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
let &l:textwidth = l:max_line_length
if g:EditorConfig_preserve_formatoptions == 0
setlocal formatoptions+=tc
endif
endif
if exists('+colorcolumn')
if l:max_line_length > 0
if g:EditorConfig_max_line_indicator == 'line'
let &l:colorcolumn = l:max_line_length + 1
elseif g:EditorConfig_max_line_indicator == 'fill' &&
\ l:max_line_length < &l:columns
" Fill only if the columns of screen is large enough
let &l:colorcolumn = join(
\ range(l:max_line_length+1,&l:columns),',')
elseif g:EditorConfig_max_line_indicator == 'exceeding'
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.', 100)
endif
endif
endif
endif
call editorconfig#ApplyHooks(a:config)
endfunction
" }}}1
function! s:TrimTrailingWhitespace() " {{{1
if &l:modifiable
" don't lose user position when trimming trailing whitespace
let s:view = winsaveview()
try
silent! keeppatterns %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

View file

@ -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)

View file

@ -0,0 +1,34 @@
# 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()

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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:

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
# Where bundler installs local Gemfile dependencies
/vendor/

View file

@ -0,0 +1,5 @@
source 'https://rubygems.org'
gem 'rake', '~> 12.3.3'
gem 'rspec', '~> 3.4.0'
gem 'vimrunner', '~> 0.3.1'

View file

@ -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)

View file

@ -0,0 +1,8 @@
#
# run `rake` to run tests
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
task :default => :spec

View file

@ -0,0 +1,4 @@
[*.rb]
indent_style = space
indent_size = 2
end_of_line = lf

View file

@ -0,0 +1,161 @@
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|
expect(vim.echo("&l:#{key}")).to eq(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

View file

@ -0,0 +1,45 @@
#!/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" = '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

View file

@ -9,6 +9,7 @@ Git submodules are slow, so handle this manually.
## pack/acp/start/
* [editorconfig-vim](https://github.com/editorconfig/editorconfig-vim)
* [goyo.vim](https://github.com/junegunn/goyo.vim)
* [gruvbox](https://github.com/morhetz/gruvbox)
* [limelight.vim](https://github.com/junegunn/limelight.vim)