1
0
Fork 0
mirror of synced 2025-01-20 19:39:46 -05:00

feat: include editorconfig-vim plugin

Signed-off-by: luc <onion0709@gmail.com>
This commit is contained in:
luc 2021-06-06 15:51:23 +08:00
parent 8cba9bb7a8
commit da40fe1222
37 changed files with 3551 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 <&