Squashed 'vim/bundle/editorconfig/' content from commit 3bb9f129c
git-subtree-dir: vim/bundle/editorconfig git-subtree-split: 3bb9f129ca364e484654e37ecb7bdcde58100b22main
commit
50248aee06
@ -0,0 +1,23 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = LF
|
||||
charset = utf-8
|
||||
|
||||
[*.vim]
|
||||
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
|
@ -0,0 +1 @@
|
||||
tags
|
@ -0,0 +1,3 @@
|
||||
[submodule "tests/spec/plugin_tests"]
|
||||
path = tests/spec/plugin_tests
|
||||
url = git://github.com/editorconfig/editorconfig-plugin-tests.git
|
@ -0,0 +1,20 @@
|
||||
language: ruby
|
||||
|
||||
rvm:
|
||||
- 1.9.3
|
||||
|
||||
gemfile: tests/Gemfile
|
||||
|
||||
before_install: sudo apt-get install vim-gtk
|
||||
|
||||
before_script:
|
||||
- "export DISPLAY=:99.0"
|
||||
- "sh -e /etc/init.d/xvfb start"
|
||||
|
||||
script:
|
||||
bundle exec rspec tests/spec/editorconfig_spec.rb
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: change
|
||||
on_failure: always
|
@ -0,0 +1,5 @@
|
||||
Contributors to the EditorConfig Vim Plugin:
|
||||
|
||||
Hong Xu
|
||||
Trey Hunner
|
||||
Kent Frazier
|
@ -0,0 +1,26 @@
|
||||
Unless otherwise stated, all files are distributed under the Simplified BSD
|
||||
license included below.
|
||||
|
||||
Copyright (c) 2011-2012 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.
|
@ -0,0 +1,46 @@
|
||||
# EditorConfig Vim Plugin
|
||||
|
||||
[![Build Status](https://travis-ci.org/editorconfig/editorconfig-vim.png?branch=master)](https://travis-ci.org/editorconfig/editorconfig-vim)
|
||||
|
||||
This is an [EditorConfig][] plugin for Vim. This plugin could be found on both
|
||||
[GitHub][] and [Vim online][].
|
||||
|
||||
## Installation
|
||||
|
||||
There are two ways for installation:
|
||||
|
||||
- If your Vim is compiled with `+python` feature (this is usually true on most
|
||||
Linux distributions), the most simple way to install this plugin is to
|
||||
download the archive and extract it into your Vim runtime directory (`~/.vim`
|
||||
on UNIX/Linux and `$VIM_INSTALLATION_FOLDER\vimfiles` on windows).
|
||||
|
||||
- If your Vim is not compiled with `+python` feature, please first download the
|
||||
[EditorConfig core][] and follow the instructions in the README and INSTALL
|
||||
files to install it. This plugin would NOT work if neither `+python` nor
|
||||
EditorConfig core is available.
|
||||
|
||||
|
||||
## Supported properties
|
||||
|
||||
The EditorConfig Vim plugin supports the following EditorConfig [properties][]:
|
||||
|
||||
* indent_style
|
||||
* indent_size
|
||||
* tab_width
|
||||
* end_of_line
|
||||
* charset
|
||||
* trim_trailing_whitespace
|
||||
* max_line_width
|
||||
* root (only used by EditorConfig core)
|
||||
|
||||
## Bugs and Feature Requests
|
||||
|
||||
Feel free to submit bugs, feature requests, and other issues to the main
|
||||
[EditorConfig issue tracker][].
|
||||
|
||||
[EditorConfig]: http://editorconfig.org
|
||||
[EditorConfig core]: https://github.com/editorconfig/editorconfig-core
|
||||
[GitHub]: https://github.com/editorconfig/editorconfig-vim
|
||||
[properties]: http://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties
|
||||
[Vim online]: http://www.vim.org/scripts/script.php?script_id=3934
|
||||
[EditorConfig issue tracker]: https://github.com/editorconfig/editorconfig/issues
|
@ -0,0 +1,59 @@
|
||||
" Copyright (c) 2011-2012 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) " {{{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
|
@ -0,0 +1,173 @@
|
||||
*editorconfig.txt*
|
||||
|
||||
File: editorconfig.txt
|
||||
Version: 0.3.2
|
||||
Maintainer: EditorConfig Team <http://editorconfig.org>
|
||||
Description: EditorConfig vim plugin
|
||||
|
||||
License:
|
||||
Copyright (c) 2011-2013 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*
|
||||
----------------------------------------------------------------------------
|
||||
Download the [EditorConfig core][] and follow the instructions in the README
|
||||
and INSTALL files to install it.
|
||||
|
||||
Once EditorConfig core is installed, copy the `plugin/editorconfig.vim` file
|
||||
to your `~/.vim/plugin` directory and `doc/editorconfig.txt` to your
|
||||
`~/.vim/doc` directory to install the EditorConfig 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. There are 3 modes currently: "external_command", "python_builtin",
|
||||
"python_external".
|
||||
|
||||
python_builtin: Use the vim built-in python to run the python version
|
||||
EditorConfig Core.
|
||||
python_external: Use an external python interpreter to run the python
|
||||
version EditorConfig Core.
|
||||
external_command: Run external EditorConfig Core.
|
||||
|
||||
If "g:EditorConfig_core_mode" is not specified, this plugin will automatically
|
||||
choose a mode that could work for you. The checking sequence is:
|
||||
python_builtin, external_command, python_external.
|
||||
|
||||
*g:EditorConfig_exec_path*
|
||||
The file path to the EditorConfig core executable. You could set this value in
|
||||
your |vimrc| like this:
|
||||
>
|
||||
let g:EditorConfig_exec_path = 'Path to your EditorConfig Core executable'
|
||||
<
|
||||
The default value is empty.
|
||||
|
||||
This plugin will search through the following executables in order:
|
||||
|
||||
On UNIX:
|
||||
the value of g:EditorConfig_exec_path
|
||||
editorconfig
|
||||
/usr/local/bin/editorconfig
|
||||
/usr/bin/editorconfig
|
||||
/opt/bin/editorconfig
|
||||
/opt/editorconfig/bin/editorconfig
|
||||
editorconfig.py
|
||||
/usr/local/bin/editorconfig.py
|
||||
/usr/bin/editorconfig.py
|
||||
/opt/bin/editorconfig.py
|
||||
/opt/editorconfig/bin/editorconfig.py
|
||||
|
||||
On Windows:
|
||||
the value of g:EditorConfig_exec_path
|
||||
editorconfig
|
||||
C:\editorconfig\bin\editorconfig
|
||||
D:\editorconfig\bin\editorconfig
|
||||
E:\editorconfig\bin\editorconfig
|
||||
F:\editorconfig\bin\editorconfig
|
||||
C:\Program Files\editorconfig\bin\editorconfig
|
||||
D:\Program Files\editorconfig\bin\editorconfig
|
||||
E:\Program Files\editorconfig\bin\editorconfig
|
||||
F:\Program Files\editorconfig\bin\editorconfig
|
||||
editorconfig.py
|
||||
|
||||
*g:EditorConfig_python_files_dir*
|
||||
If the EditorConfig core mode is python_builtin or python_external (see
|
||||
|g:EditorConfig_core_mode|), this variable is the directory where the plugin
|
||||
looks for the python scripts. This could either be an abosolute path, or a
|
||||
path relative to any of the directories in 'runtimepath'. The default value is
|
||||
"plugin/editorconfig-core-py", which means all "plugin/editorconfig-core-py"
|
||||
directory in 'runtimepath' will be searched.
|
||||
|
||||
*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
|
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
zip -r editorconfig-vim-$*.zip plugin/editorconfig.vim plugin/editorconfig-core-py/* doc/editorconfig.txt autoload/*.vim
|
@ -0,0 +1,12 @@
|
||||
root = true
|
||||
|
||||
[*.{py,rst,txt}]
|
||||
indent_style = space
|
||||
trim_trailing_whitespace = true
|
||||
indent_size = 4
|
||||
end_of_line = LF
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = LF
|
@ -0,0 +1,11 @@
|
||||
*.py[co]
|
||||
*\$py.class
|
||||
*.egg-info
|
||||
dist
|
||||
build
|
||||
/Testing
|
||||
/Makefile
|
||||
/tests/Makefile
|
||||
*.cmake
|
||||
CMakeFiles
|
||||
CMakeCache.txt
|
@ -0,0 +1,51 @@
|
||||
language: python
|
||||
|
||||
# We support from Python 2.4 to 2.7. However, 2.4 is not supported by travis,
|
||||
# so it is not listed here
|
||||
python:
|
||||
- "2.5"
|
||||
- "2.6"
|
||||
- "2.7"
|
||||
- "3.2"
|
||||
- "3.3"
|
||||
|
||||
# For testing with JYTHON=true, we will use Jython 2.2 instead of the python
|
||||
# version provided by Travis CI
|
||||
env:
|
||||
- JYTHON=true
|
||||
- JYTHON=false
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- python: "2.5"
|
||||
env: JYTHON=true
|
||||
- python: "2.6"
|
||||
env: JYTHON=true
|
||||
- python: "3.2"
|
||||
env: JYTHON=true
|
||||
- python: "3.3"
|
||||
env: JYTHON=true
|
||||
|
||||
# we need cmake, and jython if JYTHON=true
|
||||
install:
|
||||
- sudo apt-get install cmake ant
|
||||
- export JYTHON_URL='http://downloads.sourceforge.net/project/jython/jython/2.2.1/jython_installer-2.2.1.jar?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fjython%2Ffiles%2Fjython%2F2.2.1%2F&ts=1338180153&use_mirror=iweb'
|
||||
- if [ "$JYTHON" == "true" ]; then wget $JYTHON_URL -O jython_installer.jar; java -jar jython_installer.jar -s -d $HOME/jython; export PATH=$HOME/jython:$PATH;jython --version; fi
|
||||
|
||||
# Before run the test case, we need to make jython run some code
|
||||
before_script:
|
||||
- if [ "$JYTHON" == "true" ]; then jython -c "print ''"; fi
|
||||
|
||||
# test script
|
||||
script:
|
||||
- if [ "$JYTHON" == "true" ]; then cmake -DPYTHON_EXECUTABLE="$(which jython)" . ; else cmake . ; fi
|
||||
- ctest -V --output-on-failure .
|
||||
- cd java-binding
|
||||
- ant -v
|
||||
- ant -v doc
|
||||
|
||||
# Notify the mailing list
|
||||
notifications:
|
||||
email:
|
||||
on_success: change
|
||||
on_failure: always
|
@ -0,0 +1,21 @@
|
||||
# This file is used for testing only
|
||||
|
||||
# To perform the test, run `cmake .` at the root of the project tree followed
|
||||
# by ctest .
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
# Do not check any compiler
|
||||
project(editorconfig-core-py NONE)
|
||||
|
||||
find_package(PythonInterp)
|
||||
|
||||
if(NOT PYTHONINTERP_FOUND)
|
||||
message(FETAL_ERROR
|
||||
"Python interpreter is not found. If you have python installed, please run:
|
||||
cmake -DPYTHON_EXECUTABLE=/path/to/python .")
|
||||
endif()
|
||||
|
||||
enable_testing()
|
||||
set(EDITORCONFIG_CMD ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/main.py)
|
||||
add_subdirectory(tests)
|
@ -0,0 +1,192 @@
|
||||
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
||||
--------------------------------------------
|
||||
|
||||
1. This LICENSE AGREEMENT is between the Python Software Foundation
|
||||
("PSF"), and the Individual or Organization ("Licensee") accessing and
|
||||
otherwise using this software ("Python") 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 alone or in any derivative version,
|
||||
provided, however, that PSF's License Agreement and PSF's notice of copyright,
|
||||
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
Python Software Foundation; All Rights Reserved" are retained in Python 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 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.
|
||||
|
||||
4. PSF is making Python 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 WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
|
||||
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, Licensee
|
||||
agrees to be bound by the terms and conditions of this License
|
||||
Agreement.
|
||||
|
||||
|
||||
BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
|
||||
-------------------------------------------
|
||||
|
||||
BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
|
||||
|
||||
1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
|
||||
office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
|
||||
Individual or Organization ("Licensee") accessing and otherwise using
|
||||
this software in source or binary form and its associated
|
||||
documentation ("the Software").
|
||||
|
||||
2. Subject to the terms and conditions of this BeOpen Python License
|
||||
Agreement, BeOpen hereby grants Licensee a non-exclusive,
|
||||
royalty-free, world-wide license to reproduce, analyze, test, perform
|
||||
and/or display publicly, prepare derivative works, distribute, and
|
||||
otherwise use the Software alone or in any derivative version,
|
||||
provided, however, that the BeOpen Python License is retained in the
|
||||
Software, alone or in any derivative version prepared by Licensee.
|
||||
|
||||
3. BeOpen is making the Software available to Licensee on an "AS IS"
|
||||
basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
|
||||
SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
|
||||
AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
|
||||
DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
|
||||
5. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
|
||||
6. This License Agreement shall be governed by and interpreted in all
|
||||
respects by the law of the State of California, excluding conflict of
|
||||
law provisions. Nothing in this License Agreement shall be deemed to
|
||||
create any relationship of agency, partnership, or joint venture
|
||||
between BeOpen and Licensee. This License Agreement does not grant
|
||||
permission to use BeOpen trademarks or trade names in a trademark
|
||||
sense to endorse or promote products or services of Licensee, or any
|
||||
third party. As an exception, the "BeOpen Python" logos available at
|
||||
http://www.pythonlabs.com/logos.html may be used according to the
|
||||
permissions granted on that web page.
|
||||
|
||||
7. By copying, installing or otherwise using the software, Licensee
|
||||
agrees to be bound by the terms and conditions of this License
|
||||
Agreement.
|
||||
|
||||
|
||||
CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
|
||||
---------------------------------------
|
||||
|
||||
1. This LICENSE AGREEMENT is between the Corporation for National
|
||||
Research Initiatives, having an office at 1895 Preston White Drive,
|
||||
Reston, VA 20191 ("CNRI"), and the Individual or Organization
|
||||
("Licensee") accessing and otherwise using Python 1.6.1 software in
|
||||
source or binary form and its associated documentation.
|
||||
|
||||
2. Subject to the terms and conditions of this License Agreement, CNRI
|
||||
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 1.6.1
|
||||
alone or in any derivative version, provided, however, that CNRI's
|
||||
License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
|
||||
1995-2001 Corporation for National Research Initiatives; All Rights
|
||||
Reserved" are retained in Python 1.6.1 alone or in any derivative
|
||||
version prepared by Licensee. Alternately, in lieu of CNRI's License
|
||||
Agreement, Licensee may substitute the following text (omitting the
|
||||
quotes): "Python 1.6.1 is made available subject to the terms and
|
||||
conditions in CNRI's License Agreement. This Agreement together with
|
||||
Python 1.6.1 may be located on the Internet using the following
|
||||
unique, persistent identifier (known as a handle): 1895.22/1013. This
|
||||
Agreement may also be obtained from a proxy server on the Internet
|
||||
using the following URL: http://hdl.handle.net/1895.22/1013".
|
||||
|
||||
3. In the event Licensee prepares a derivative work that is based on
|
||||
or incorporates Python 1.6.1 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 1.6.1.
|
||||
|
||||
4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
|
||||
basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||
1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
|
||||
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. This License Agreement shall be governed by the federal
|
||||
intellectual property law of the United States, including without
|
||||
limitation the federal copyright law, and, to the extent such
|
||||
U.S. federal law does not apply, by the law of the Commonwealth of
|
||||
Virginia, excluding Virginia's conflict of law provisions.
|
||||
Notwithstanding the foregoing, with regard to derivative works based
|
||||
on Python 1.6.1 that incorporate non-separable material that was
|
||||
previously distributed under the GNU General Public License (GPL), the
|
||||
law of the Commonwealth of Virginia shall govern this License
|
||||
Agreement only as to issues arising under or with respect to
|
||||
Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
|
||||
License Agreement shall be deemed to create any relationship of
|
||||
agency, partnership, or joint venture between CNRI and Licensee. This
|
||||
License Agreement does not grant permission to use CNRI trademarks or
|
||||
trade name in a trademark sense to endorse or promote products or
|
||||
services of Licensee, or any third party.
|
||||
|
||||
8. By clicking on the "ACCEPT" button where indicated, or by copying,
|
||||
installing or otherwise using Python 1.6.1, Licensee agrees to be
|
||||
bound by the terms and conditions of this License Agreement.
|
||||
|
||||
ACCEPT
|
||||
|
||||
|
||||
CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
|
||||
--------------------------------------------------
|
||||
|
||||
Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
|
||||
The Netherlands. All rights reserved.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the name of Stichting Mathematisch
|
||||
Centrum or CWI not be used in advertising or publicity pertaining to
|
||||
distribution of the software without specific, written prior
|
||||
permission.
|
||||
|
||||
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
||||
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
|
||||
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
@ -0,0 +1 @@
|
||||
include README.rst LICENSE.txt
|
@ -0,0 +1,82 @@
|
||||
========================
|
||||
EditorConfig Python Core
|
||||
========================
|
||||
|
||||
.. image:: https://secure.travis-ci.org/editorconfig/editorconfig-core-py.png?branch=master
|
||||
:target: http://travis-ci.org/editorconfig/editorconfig-core-py
|
||||
|
||||
EditorConfig Python Core provides the same functionality as the
|
||||
`EditorConfig C Core <https://github.com/editorconfig/editorconfig-core>`_.
|
||||
EditorConfig Python core can be used as a command line program or as an
|
||||
importable library.
|
||||
|
||||
EditorConfig Project
|
||||
====================
|
||||
|
||||
EditorConfig makes it easy to maintain the correct coding style when switching
|
||||
between different text editors and between different projects. The
|
||||
EditorConfig project maintains a file format and plugins for various text
|
||||
editors which allow this file format to be read and used by those editors. For
|
||||
information on the file format and supported text editors, see the
|
||||
`EditorConfig website <http://editorconfig.org>`_.
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
With setuptools::
|
||||
|
||||
sudo python setup.py install
|
||||
|
||||
Getting Help
|
||||
============
|
||||
For help with the EditorConfig core code, please write to our `mailing list
|
||||
<http://groups.google.com/group/editorconfig>`_. Bugs and feature requests
|
||||
should be submitted to our `issue tracker
|
||||
<https://github.com/editorconfig/editorconfig/issues>`_.
|
||||
|
||||
If you are writing a plugin a language that can import Python libraries, you
|
||||
may want to import and use the EditorConfig Python Core directly.
|
||||
|
||||
Using as a Library
|
||||
==================
|
||||
|
||||
Basic example use of EditorConfig Python Core as a library:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from editorconfig import get_properties, EditorConfigError
|
||||
|
||||
filename = "/home/zoidberg/humans/anatomy.md"
|
||||
|
||||
try:
|
||||
options = get_properties(filename)
|
||||
except EditorConfigError:
|
||||
print "Error occurred while getting EditorConfig properties"
|
||||
else:
|
||||
for key, value in options.items():
|
||||
print "%s=%s" % (key, value)
|
||||
|
||||
For details, please take a look at the `online documentation
|
||||
<http://pydocs.editorconfig.org>`_.
|
||||
|
||||
Running Test Cases
|
||||
==================
|
||||
|
||||
`Cmake <http://www.cmake.org>`_ has to be installed first. Run the test cases
|
||||
using the following commands::
|
||||
|
||||
cmake .
|
||||
ctest .
|
||||
|
||||
Use ``-DPYTHON_EXECUTABLE`` to run the tests using an alternative versions of
|
||||
Python (Python 3, Jython, etc.)::
|
||||
|
||||
cmake -DPYTHON_EXECUTABLE=/usr/bin/python3 .
|
||||
ctest .
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
Unless otherwise stated, all files are distributed under the PSF license. The
|
||||
odict library (editorconfig/odict.py) is distributed under the New BSD license.
|
||||
See LICENSE.txt file for details on PSF license.
|
@ -0,0 +1,130 @@
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = _build
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/EditorConfigPythonCore.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/EditorConfigPythonCore.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/EditorConfigPythonCore"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/EditorConfigPythonCore"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
@ -0,0 +1,18 @@
|
||||
==================
|
||||
Command Line Usage
|
||||
==================
|
||||
|
||||
The EditorConfig Python Core can be used from the command line in the same way
|
||||
as the EditorConfig C Core.
|
||||
|
||||
Discovering EditorConfig properties
|
||||
-----------------------------------
|
||||
|
||||
Installing EditorConfig Python Core should add an ``editorconfig.py`` command
|
||||
to your path. This command can be used to locate and parse EditorConfig files
|
||||
for a given full filepath. For example::
|
||||
|
||||
editorconfig.py /home/zoidberg/humans/anatomy.md
|
||||
|
||||
When used to retrieve EditorConfig file properties, ``editorconfig.py`` will
|
||||
return discovered properties in *key=value* pairs, one on each line.
|
@ -0,0 +1,219 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# EditorConfig Python Core documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sat May 5 09:51:42 2012.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys, os
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path.insert(0, os.path.abspath('..'))
|
||||
|
||||
import editorconfig
|
||||
from editorconfig import __version__
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'EditorConfig Python Core'
|
||||
copyright = u'2012, EditorConfig Team'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = __version__
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = __version__
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'agogo'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'EditorConfigPythonCoredoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
||||
# The paper size ('letter' or 'a4').
|
||||
#latex_paper_size = 'letter'
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#latex_font_size = '10pt'
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'EditorConfigPythonCore.tex', u'EditorConfig Python Core Documentation',
|
||||
u'EditorConfig Team', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#latex_preamble = ''
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output --------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'editorconfigpythoncore', u'EditorConfig Python Core Documentation',
|
||||
[u'EditorConfig Team'], 1)
|
||||
]
|
@ -0,0 +1,23 @@
|
||||
==================================================================
|
||||
EditorConfig Python Core -- Process EditorConfig Files With Python
|
||||
==================================================================
|
||||
|
||||
EditorConfig is a file format for defining file-specific coding styles and a
|
||||
set of plugins that allow text editors and IDEs to read this file format. For
|
||||
more information on the EditorConfig project visit the
|
||||
`EditorConfig Homepage`_.
|
||||
|
||||
The EditorConfig Python Core is a Python package for locating and parsing
|
||||
EditorConfig files. This package can be used as an import by other Python code
|
||||
or as a stand-alone command line program.
|
||||
|
||||
.. _`EditorConfig Homepage`: http://editorconfig.org
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
usage
|
||||
command_line_usage
|
||||
plugins
|
@ -0,0 +1,170 @@
|
||||
@ECHO OFF
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set BUILDDIR=_build
|
||||
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
|
||||
if NOT "%PAPER%" == "" (
|
||||
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
if "%1" == "help" (
|
||||
:help
|
||||
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||
echo. html to make standalone HTML files
|
||||
echo. dirhtml to make HTML files named index.html in directories
|
||||
echo. singlehtml to make a single large HTML file
|
||||
echo. pickle to make pickle files
|
||||
echo. json to make JSON files
|
||||
echo. htmlhelp to make HTML files and a HTML help project
|
||||
echo. qthelp to make HTML files and a qthelp project
|
||||
echo. devhelp to make HTML files and a Devhelp project
|
||||
echo. epub to make an epub
|
||||
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||
echo. text to make text files
|
||||
echo. man to make manual pages
|
||||
echo. changes to make an overview over all changed/added/deprecated items
|
||||
echo. linkcheck to check all external links for integrity
|
||||
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "clean" (
|
||||
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||
del /q /s %BUILDDIR%\*
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "html" (
|
||||
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "dirhtml" (
|
||||
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "singlehtml" (
|
||||
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pickle" (
|
||||
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the pickle files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "json" (
|
||||
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the JSON files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "htmlhelp" (
|
||||
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "qthelp" (
|
||||
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\EditorConfigPythonCore.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\EditorConfigPythonCore.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "devhelp" (
|
||||
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "epub" (
|
||||
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latex" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "text" (
|
||||
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "man" (
|
||||
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "changes" (
|
||||
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.The overview file is in %BUILDDIR%/changes.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "linkcheck" (
|
||||
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Link check complete; look for any errors in the above output ^
|
||||
or in %BUILDDIR%/linkcheck/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "doctest" (
|
||||
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of doctests in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/doctest/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
:end
|
@ -0,0 +1,72 @@
|
||||
===============
|
||||
Writing Plugins
|
||||
===============
|
||||
|
||||
The EditorConfig Python Core can be easily used by text editor plugins written in Python or plugins that can call an external Python interpreter. The EditorConfig Python Core supports Python versions 2.2 to 2.7. Check out the `Vim`_ and `Gedit`_ plugins for example usages of the EditorConfig Python Core.
|
||||
|
||||
.. _`Vim`: https://github.com/editorconfig/editorconfig-vim
|
||||
.. _`Gedit`: https://github.com/editorconfig/editorconfig-gedit
|
||||
|
||||
|
||||
Use as a library
|
||||
----------------
|
||||
|
||||
For instructions on using the EditorConfig Python Core as a Python library see :doc:`usage`.
|
||||
|
||||
|
||||
Using with an external Python interpreter
|
||||
-----------------------------------------
|
||||
|
||||
The EditorConfig Python Core can be used with an external Python interpreter by executing the ``main.py`` file. The ``main.py`` file can be executed like so::
|
||||
|
||||
python editorconfig-core-py/main.py /home/zoidberg/humans/anatomy.md
|
||||
|
||||
For more information on command line usage of the EditorConfig Python Core see :doc:`command_line_usage`.
|
||||
|
||||
|
||||
Bundling EditorConfig Python Core with Plugin
|
||||
---------------------------------------------
|
||||
|
||||
A text editor or IDE plugin will either need to bundle the EditorConfig Python
|
||||
Core with the plugin installation package or the will need to assist the user
|
||||
in installing the EditorConfig Python Core. Below are instructions for
|
||||
bundling the EditorConfig Python Core with plugins.
|
||||
|
||||
Bundling as a Submodule in Git
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Git submodules allow one repository to be included inside another. A submodule
|
||||
stores a remote repositry and commit to use for fetching the embedded
|
||||
repository. Submodules take up very little space in the repository since they
|
||||
do not actually include the code of the embedded repository directly.
|
||||
|
||||
To add EditorConfig Python Core as a submodule in the ``editorconfig-core-py``
|
||||
directory of your repository::
|
||||
|
||||
git submodule add git://github.com/editorconfig/editorconfig-core-py.git editorconfig-core-py
|
||||
|
||||
Then every time the code is checked out the submodule directory should be
|
||||
initialized and updated::
|
||||
|
||||
git submodule update --init
|
||||
|
||||
Bundling as a Subtree in Git
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Git subtrees are convenient because, unlike submodules, they do not require any
|
||||
extra work to be performed when cloning the git repository. Git subtrees
|
||||
include one git codebase as a subdirectory of another.
|
||||
|
||||
Example of using a subtree for the ``editorconfig`` directory from the
|
||||
EditorConfig Python Core repository::
|
||||
|
||||
git remote add -f editorconfig-core-py git://github.com/editorconfig/editorconfig-core-py.git
|
||||
git merge -s ours --no-commit editorconfig-core-py/master
|
||||
git read-tree --prefix=editorconfig -u editorconfig-core-py/master:editorconfig
|
||||
git commit
|
||||
|
||||
For more information on subtrees consult the `subtree merge guide`_ on Github
|
||||
and `Chapter 6.7`_ in the book Pro Git.
|
||||
|
||||
.. _`subtree merge guide`: http://help.github.com/subtree-merge/
|
||||
.. _`Chapter 6.7`: http://git-scm.com/book/ch6-7.html
|
@ -0,0 +1,84 @@
|
||||
=====
|
||||
Usage
|
||||
=====
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
First you will need to install the EditorConfig Python Core package.
|
||||
|
||||
To install from PyPI using pip::
|
||||
|
||||
pip install editorconfig
|
||||
|
||||
Discovering EditorConfig properties
|
||||
-----------------------------------
|
||||
|
||||
The ``get_properties`` function can be used to discover EditorConfig properties
|
||||
for a given file. Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import logging
|
||||
from editorconfig import get_properties, EditorConfigError
|
||||
|
||||
filename = "/home/zoidberg/humans/anatomy.md"
|
||||
|
||||
try:
|
||||
options = get_properties(filename)
|
||||
except EditorConfigError:
|
||||
logging.warning("Error getting EditorConfig properties", exc_info=True)
|
||||
else:
|
||||
for key, value in options.items():
|
||||
print "%s=%s" % (key, value)
|
||||
|
||||
|
||||
The ``get_properties`` method returns a dictionary representing EditorConfig
|
||||
properties found for the given file. If an error occurs while parsing a file
|
||||
an exception will be raised. All raised exceptions will inherit from the
|
||||
``EditorConfigError`` class.
|
||||
|
||||
Handling Exceptions
|
||||
-------------------
|
||||
|
||||
All exceptions raised by EditorConfig will subclass ``EditorConfigError``. To
|
||||
handle certain exceptions specially, catch them first. More exception classes
|
||||
may be added in the future so it is advisable to always handle general
|
||||
``EditorConfigError`` exceptions in case a future version raises an exception
|
||||
that your code does not handle specifically.
|
||||
|
||||
Exceptions module reference
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Exceptions can be found in the ``editorconfig.exceptions`` module. These are
|
||||
the current exception types:
|
||||
|
||||
.. autoexception:: editorconfig.exceptions.EditorConfigError
|
||||
.. autoexception:: editorconfig.exceptions.ParsingError
|
||||
.. autoexception:: editorconfig.exceptions.PathError
|
||||
.. autoexception:: editorconfig.exceptions.VersionError
|
||||
|
||||
Exception handling example
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
An example of custom exception handling:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import logging
|
||||
from editorconfig import get_properties
|
||||
from editorconfig import exceptions
|
||||
|
||||
filename = "/home/zoidberg/myfile.txt"
|
||||
|
||||
try:
|
||||
options = get_properties(filename)
|
||||
except exceptions.ParsingError:
|
||||
logging.warning("Error parsing an .editorconfig file", exc_info=True)
|
||||
except exceptions.PathError:
|
||||
logging.error("Invalid filename specified", exc_info=True)
|
||||
except exceptions.EditorConfigError:
|
||||
logging.error("An unknown EditorConfig error occurred", exc_info=True)
|
||||
|
||||
for key, value in options.iteritems():
|
||||
print "%s=%s" % (key, value)
|
@ -0,0 +1,19 @@
|
||||
"""EditorConfig Python Core"""
|
||||
|
||||
from editorconfig.versiontools import join_version
|
||||
|
||||
VERSION = (0, 11, 3, "final")
|
||||
|
||||
__all__ = ['get_properties', 'EditorConfigError', 'exceptions']
|
||||
|
||||
__version__ = join_version(VERSION)
|
||||
|
||||
|
||||
def get_properties(filename):
|
||||
"""Locate and parse EditorConfig files for the given filename"""
|
||||
handler = EditorConfigHandler(filename)
|
||||
return handler.get_configurations()
|
||||
|
||||
|
||||
from editorconfig.handler import EditorConfigHandler
|
||||
from editorconfig.exceptions import *
|
@ -0,0 +1,18 @@
|
||||
"""EditorConfig Python2/Python3/Jython compatibility utilities"""
|
||||
import sys
|
||||
import types
|
||||
|
||||
__all__ = ['slice', 'u']
|
||||
|
||||
|
||||
if sys.version_info[0] == 2:
|
||||
slice = types.SliceType
|
||||
else:
|
||||
slice = slice
|
||||
|
||||
|
||||
if sys.version_info[0] == 2:
|
||||
import codecs
|
||||
u = lambda s: codecs.unicode_escape_decode(s)[0]
|
||||
else:
|
||||
u = lambda s: s
|
@ -0,0 +1,27 @@
|
||||
"""EditorConfig exception classes
|
||||
|
||||
Licensed under PSF License (see LICENSE.txt file).
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class EditorConfigError(Exception):
|
||||
"""Parent class of all exceptions raised by EditorConfig"""
|
||||
|
||||
|
||||
try:
|
||||
from ConfigParser import ParsingError as _ParsingError
|
||||
except:
|
||||
from configparser import ParsingError as _ParsingError
|
||||
|
||||
|
||||
class ParsingError(_ParsingError, EditorConfigError):
|
||||
"""Error raised if an EditorConfig file could not be parsed"""
|
||||
|
||||
|
||||
class PathError(ValueError, EditorConfigError):
|
||||
"""Error raised if invalid filepath is specified"""
|
||||
|
||||
|
||||
class VersionError(ValueError, EditorConfigError):
|
||||
"""Error raised if invalid version number is specified"""
|
@ -0,0 +1,126 @@
|
||||
"""Filename matching with shell patterns.
|
||||
|
||||
fnmatch(FILENAME, PATTERN) matches according to the local convention.
|
||||
fnmatchcase(FILENAME, 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.)
|
||||
|
||||
Based on code from fnmatch.py file distributed with Python 2.6.
|
||||
|
||||
Licensed under PSF License (see LICENSE.txt file).
|
||||
|
||||
Changes to original fnmatch module:
|
||||
- translate function supports ``*`` and ``**`` similarly to fnmatch C library
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
__all__ = ["fnmatch", "fnmatchcase", "translate"]
|
||||
|
||||
_cache = {}
|
||||
|
||||
|
||||
def fnmatch(name, pat):
|
||||
"""Test whether FILENAME matches 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).
|
||||
"""
|
||||
|
||||
name = os.path.normcase(name).replace(os.sep, "/")
|
||||
return fnmatchcase(name, pat)
|
||||
|
||||
|
||||
def fnmatchcase(name, pat):
|
||||
"""Test whether FILENAME matches PATTERN, including case.
|
||||
|
||||
This is a version of fnmatch() which doesn't case-normalize
|
||||
its arguments.
|
||||
"""
|
||||
|
||||
if not pat in _cache:
|
||||
res = translate(pat)
|
||||
_cache[pat] = re.compile(res)
|
||||
return _cache[pat].match(name) is not None
|
||||
|
||||
|
||||
def translate(pat):
|
||||
"""Translate a shell PATTERN to a regular expression.
|
||||
|
||||
There is no way to quote meta-characters.
|
||||
"""
|
||||
|
||||
i, n = 0, len(pat)
|
||||
res = ''
|
||||
escaped = False
|
||||
while i < n:
|
||||
c = pat[i]
|
||||
i = i + 1
|
||||
if c == '*':
|
||||
j = i
|
||||
if j < n and pat[j] == '*':
|
||||
res = res + '.*'
|
||||
else:
|
||||
res = res + '[^/]*'
|
||||
elif c == '?':
|
||||
res = res + '.'
|
||||
elif c == '[':
|
||||
j = i
|
||||
if j < n and pat[j] == '!':
|
||||
j = j + 1
|
||||
if j < n and pat[j] == ']':
|
||||
j = j + 1
|
||||
while j < n and (pat[j] != ']' or escaped):
|
||||
escaped = pat[j] == '\\' and not escaped
|
||||
j = j + 1
|
||||
if j >= n:
|
||||
res = res + '\\['
|
||||
else:
|
||||
stuff = pat[i:j]
|
||||
i = j + 1
|
||||
if stuff[0] == '!':
|
||||
stuff = '^' + stuff[1:]
|
||||
elif stuff[0] == '^':
|
||||
stuff = '\\' + stuff
|
||||
res = '%s[%s]' % (res, stuff)
|
||||
elif c == '{':
|
||||
j = i
|
||||
groups = []
|
||||
while j < n and pat[j] != '}':
|
||||
k = j
|
||||
while k < n and (pat[k] not in (',', '}') or escaped):
|
||||
escaped = pat[k] == '\\' and not escaped
|
||||
k = k + 1
|
||||
group = pat[j:k]
|
||||
for char in (',', '}', '\\'):
|
||||
group = group.replace('\\' + char, char)
|
||||
groups.append(group)
|
||||
j = k
|
||||
if j < n and pat[j] == ',':
|
||||
j = j + 1
|
||||
if j < n and pat[j] == '}':
|
||||
groups.append('')
|
||||
if j >= n or len(groups) < 2:
|
||||
res = res + '\\{'
|
||||
else:
|
||||
res = '%s(%s)' % (res, '|'.join(map(re.escape, groups)))
|
||||
i = j + 1
|
||||
else:
|
||||
res = res + re.escape(c)
|
||||
return res + '\Z(?ms)'
|
@ -0,0 +1,126 @@
|
||||
"""EditorConfig file handler
|
||||
|
||||
Provides ``EditorConfigHandler`` class for locating and parsing
|
||||
EditorConfig files relevant to a given filepath.
|
||||
|
||||
Licensed under PSF License (see LICENSE.txt file).
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from editorconfig import VERSION
|
||||
from editorconfig.ini import EditorConfigParser
|
||||
from editorconfig.exceptions import PathError, VersionError
|
||||
|
||||
|
||||
__all__ = ['EditorConfigHandler']
|
||||
|
||||
|
||||
def get_filenames(path, filename):
|
||||
"""Yield full filepath for filename in each directory in and above path"""
|
||||
path_list = []
|
||||
while True:
|
||||
path_list.append(os.path.join(path, filename))
|
||||
newpath = os.path.dirname(path)
|
||||
if path == newpath:
|
||||
break
|
||||
path = newpath
|
||||
return path_list
|
||||
|
||||
|
||||
class EditorConfigHandler(object):
|
||||
|
||||
"""
|
||||
Allows locating and parsing of EditorConfig files for given filename
|
||||
|
||||
In addition to the constructor a single public method is provided,
|
||||
``get_configurations`` which returns the EditorConfig options for
|
||||
the ``filepath`` specified to the constructor.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, filepath, conf_filename='.editorconfig',
|
||||
version=VERSION):
|
||||
"""Create EditorConfigHandler for matching given filepath"""
|
||||
self.filepath = filepath
|
||||
self.conf_filename = conf_filename
|
||||
self.version = version
|
||||
self.options = None
|
||||
|
||||
def get_configurations(self):
|
||||
|
||||
"""
|
||||
Find EditorConfig files and return all options matching filepath
|
||||
|
||||
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
|
||||
|
||||
"""
|
||||
|
||||
self.check_assertions()
|
||||
path, filename = os.path.split(self.filepath)
|
||||
conf_files = get_filenames(path, self.conf_filename)
|
||||
|
||||
# Attempt to find and parse every EditorConfig file in filetree
|
||||
for filename in conf_files:
|
||||
parser = EditorConfigParser(self.filepath)
|
||||
parser.read(filename)
|
||||
|
||||
# Merge new EditorConfig file's options into current options
|
||||
old_options = self.options
|
||||
self.options = parser.options
|
||||
if old_options:
|
||||
self.options.update(old_options)
|
||||
|
||||
# Stop parsing if parsed file has a ``root = true`` option
|
||||
if parser.root_file:
|
||||
break
|
||||
|
||||
self.preprocess_values()
|
||||
return self.options
|
||||
|
||||
def check_assertions(self):
|
||||
|
||||
"""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.")
|
||||
|
||||
# Raise ``VersionError`` if version specified is greater than current
|
||||
if self.version is not None and self.version[:3] > VERSION[:3]:
|
||||
raise VersionError(
|
||||
"Required version is greater than the current version.")
|
||||
|
||||
def preprocess_values(self):
|
||||
|
||||
"""Preprocess option values for consumption by plugins"""
|
||||
|
||||
opts = self.options
|
||||
|
||||
# Lowercase option value for certain options
|
||||
for name in ["end_of_line", "indent_style", "indent_size",
|
||||
"insert_final_newline", "trim_trailing_whitespace", "charset"]:
|
||||
if name in opts:
|
||||
opts[name] = opts[name].lower()
|
||||
|
||||
# Set indent_size to "tab" if indent_size is unspecified and
|
||||
# indent_style is set to "tab".
|
||||
if (opts.get("indent_style") == "tab" and
|
||||
not "indent_size" in opts and self.version >= (0, 10, 0)):
|
||||
opts["indent_size"] = "tab"
|
||||
|
||||
# Set tab_width to indent_size if indent_size is specified and
|
||||
# tab_width is unspecified
|
||||
if ("indent_size" in opts and "tab_width" not in opts and
|
||||
opts["indent_size"] != "tab"):
|
||||
opts["tab_width"] = opts["indent_size"]
|
||||
|
||||
# Set indent_size to tab_width if indent_size is "tab"
|
||||
if ("indent_size" in opts and "tab_width" in opts and
|
||||
opts["indent_size"] == "tab"):
|
||||
opts["indent_size"] = opts["tab_width"]
|
@ -0,0 +1,150 @@
|
||||
"""EditorConfig file parser
|
||||
|
||||
Based on code from ConfigParser.py file distributed with Python 2.6.
|
||||
|
||||
Licensed under PSF License (see LICENSE.txt 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
|
||||
|
||||
"""
|
||||
|
||||
import re
|
||||
from codecs import open
|
||||
import posixpath
|
||||
from os import sep
|
||||
from os.path import normcase, dirname
|
||||
|
||||
from editorconfig.exceptions import ParsingError
|
||||
from editorconfig.fnmatch import fnmatch
|
||||
from editorconfig.odict import OrderedDict
|
||||
from editorconfig.compat import u
|
||||
|
||||
|
||||
__all__ = ["ParsingError", "EditorConfigParser"]
|
||||
|
||||
|
||||
class EditorConfigParser(object):
|
||||
|
||||
"""Parser for EditorConfig-style configuration files
|
||||
|
||||
Based on RawConfigParser from ConfigParser.py in Python 2.6.
|
||||
"""
|
||||
|
||||
# Regular expressions for parsing section headers and options.
|
||||
# Allow ``]`` and escaped ``;`` and ``#`` characters in section headers
|
||||
SECTCRE = re.compile(
|
||||
r'\s*\[' # [
|
||||
r'(?P<header>([^#;]|\\#|\\;)+)' # very permissive!
|
||||
r'\]' # ]
|
||||
)
|
||||
# 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
|
||||
OPTCRE = re.compile(
|
||||
r'\s*(?P<option>[^:=\s][^:=]*)'
|
||||
r'\s*(?P<vi>[:=])\s*'
|
||||
r'(?P<value>.*)$'
|
||||
)
|
||||
|
||||
def __init__(self, filename):
|
||||
self.filename = filename
|
||||
self.options = OrderedDict()
|
||||
self.root_file = False
|
||||
|
||||
def matches_filename(self, config_filename, glob):
|
||||
"""Return True if section glob matches filename"""
|
||||
config_dirname = normcase(dirname(config_filename)).replace(sep, '/')
|
||||
glob = glob.replace("\\#", "#")
|
||||
glob = glob.replace("\\;", ";")
|
||||
if '/' in glob:
|
||||
if glob.find('/') == 0:
|
||||
glob = glob[1:]
|
||||
glob = posixpath.join(config_dirname, glob)
|
||||
else:
|
||||
glob = posixpath.join('**/', glob)
|
||||
return fnmatch(self.filename, glob)
|
||||
|
||||
def read(self, filename):
|
||||
"""Read and parse single EditorConfig file"""
|
||||
try:
|
||||
fp = open(filename, encoding='utf-8')
|
||||
except IOError:
|
||||
return
|
||||
self._read(fp, filename)
|
||||
fp.close()
|
||||
|
||||
def _read(self, fp, fpname):
|
||||
"""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.
|
||||
"""
|
||||
in_section = False
|
||||
matching_section = False
|
||||
optname = None
|
||||
lineno = 0
|
||||
e = None # None, or an exception
|
||||
while True:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
if lineno == 0 and line.startswith(u('\ufeff')):
|
||||
line = line[1:] # Strip UTF-8 BOM
|
||||
lineno = lineno + 1
|
||||
# comment or blank line?
|
||||
if line.strip() == '' or line[0] in '#;':
|
||||
continue
|
||||
# a section header or option header?
|
||||
else:
|
||||
# is it a section header?
|
||||
mo = self.SECTCRE.match(line)
|
||||
if mo:
|
||||
sectname = mo.group('header')
|
||||
in_section = True
|
||||
matching_section = self.matches_filename(fpname, sectname)
|
||||
# So sections can't start with a continuation line
|
||||
optname = None
|
||||
# an option line?
|
||||
else:
|
||||
mo = self.OPTCRE.match(line)
|
||||
if mo:
|
||||
optname, vi, optval = mo.group('option', 'vi', 'value')
|
||||
if ';' in optval or '#' in optval:
|
||||
# ';' and '#' are comment delimiters only if
|
||||
# preceeded by a spacing character
|
||||
m = re.search('(.*?) [;#]', optval)
|
||||
if m:
|
||||
optval = m.group(1)
|
||||
optval = optval.strip()
|
||||
# allow empty values
|
||||
if optval == '""':
|
||||
optval = ''
|
||||
optname = self.optionxform(optname.rstrip())
|
||||
if not in_section and optname == 'root':
|
||||
self.root_file = (optval.lower() == 'true')
|
||||
if matching_section:
|
||||
self.options[optname] = optval
|
||||
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
|
||||
if not e:
|
||||
e = ParsingError(fpname)
|
||||
e.append(lineno, repr(line))
|
||||
# if any parsing errors occurred, raise an exception
|
||||
if e:
|
||||
raise e
|
||||
|
||||
def optionxform(self, optionstr):
|
||||
return optionstr.lower()
|
@ -0,0 +1,76 @@
|
||||
"""EditorConfig command line interface
|
||||
|
||||
Licensed under PSF License (see LICENSE.txt file).
|
||||
|
||||
"""
|
||||
|
||||
import getopt
|
||||
import sys
|
||||
|
||||
from editorconfig import __version__, VERSION
|
||||
from editorconfig.versiontools import split_version
|
||||
from editorconfig.handler import EditorConfigHandler
|
||||
from editorconfig.exceptions import ParsingError, PathError, VersionError
|
||||
|
||||
|
||||
def version():
|
||||
print("EditorConfig Python Core Version %s" % __version__)
|
||||
|
||||
|
||||
def usage(command, error=False):
|
||||
if error:
|
||||
out = sys.stderr
|
||||
else:
|
||||
out = sys.stdout
|
||||
out.write("%s [OPTIONS] FILENAME\n" % command)
|
||||
out.write('-f '
|
||||
'Specify conf filename other than ".editorconfig".\n')
|
||||
out.write("-b "
|
||||
"Specify version (used by devs to test compatibility).\n")
|
||||
out.write("-h OR --help Print this help message.\n")
|
||||
out.write("-v OR --version Display version information.\n")
|
||||
|
||||
|
||||
def main():
|
||||
command_name = sys.argv[0]
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "vhb:f:", ["version", "help"])
|
||||
except getopt.GetoptError:
|
||||
print(str(sys.exc_info()[1])) # For Python 2/3 compatibility
|
||||
usage(command_name, error=True)
|
||||
sys.exit(2)
|
||||
|
||||
version_tuple = VERSION
|
||||
conf_filename = '.editorconfig'
|
||||
|
||||
for option, arg in opts:
|
||||
if option in ('-h', '--help'):
|
||||
usage(command_name)
|
||||
sys.exit()
|
||||
if option in ('-v', '--version'):
|
||||
version()
|
||||
sys.exit()
|
||||
if option == '-f':
|
||||
conf_filename = arg
|
||||
if option == '-b':
|
||||
version_tuple = split_version(arg)
|
||||
if version_tuple is None:
|
||||
sys.exit("Invalid version number: %s" % arg)
|
||||
|
||||
if len(args) < 1:
|
||||
usage(command_name, error=True)
|
||||
sys.exit(2)
|
||||
filenames = args
|
||||
multiple_files = len(args) > 1
|
||||
|
||||
for filename in filenames:
|
||||
handler = EditorConfigHandler(filename, conf_filename, version_tuple)
|
||||
try:
|
||||
options = handler.get_configurations()
|
||||
except (ParsingError, PathError, VersionError):
|
||||
print(str(sys.exc_info()[1])) # For Python 2/3 compatibility
|
||||
sys.exit(2)
|
||||
if multiple_files:
|
||||
print("[%s]" % filename)
|
||||
for key, value in options.items():
|
||||
print("%s=%s" % (key, value))
|
@ -0,0 +1,899 @@
|
||||
"""odict.py: An Ordered Dictionary object"""
|
||||
# Copyright (C) 2005 Nicola Larosa, Michael Foord
|
||||
# E-mail: nico AT tekNico DOT net, fuzzyman AT voidspace DOT org DOT uk
|
||||
# Copyright (c) 2003-2010, Michael Foord
|
||||
# E-mail : fuzzyman AT voidspace DOT org DOT uk
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * 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.
|
||||
#
|
||||
# * Neither the name of Michael Foord nor the name of Voidspace
|
||||
# may be used to endorse or promote products derived from this
|
||||
# software without specific prior written permission.
|
||||
#
|
||||
# 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
|
||||
# OWNER 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.
|
||||
|
||||
|
||||
from __future__ import generators
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
from editorconfig.compat import slice
|
||||
|
||||
|
||||
__docformat__ = "restructuredtext en"
|
||||
__all__ = ['OrderedDict']
|
||||
|
||||
|
||||
INTP_VER = sys.version_info[:2]
|
||||
if INTP_VER < (2, 2):
|
||||
raise RuntimeError("Python v.2.2 or later required")
|
||||
|
||||
|
||||
class OrderedDict(dict):
|
||||
"""
|
||||
A class of dictionary that keeps the insertion order of keys.
|
||||
|
||||
All appropriate methods return keys, items, or values in an ordered way.
|
||||
|
||||
All normal dictionary methods are available. Update and comparison is
|
||||
restricted to other OrderedDict objects.
|
||||
|
||||
Various sequence methods are available, including the ability to explicitly
|
||||
mutate the key ordering.
|
||||
|
||||
__contains__ tests:
|
||||
|
||||
>>> d = OrderedDict(((1, 3),))
|
||||
>>> 1 in d
|
||||
1
|
||||
>>> 4 in d
|
||||
0
|
||||
|
||||
__getitem__ tests:
|
||||
|
||||
>>> OrderedDict(((1, 3), (3, 2), (2, 1)))[2]
|
||||
1
|
||||
>>> OrderedDict(((1, 3), (3, 2), (2, 1)))[4]
|
||||
Traceback (most recent call last):
|
||||
KeyError: 4
|
||||
|
||||
__len__ tests:
|
||||
|
||||
>>> len(OrderedDict())
|
||||
0
|
||||
>>> len(OrderedDict(((1, 3), (3, 2), (2, 1))))
|
||||
3
|
||||
|
||||
get tests:
|
||||
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d.get(1)
|
||||
3
|
||||
>>> d.get(4) is None
|
||||
1
|
||||
>>> d.get(4, 5)
|
||||
5
|
||||
>>> d
|
||||
OrderedDict([(1, 3), (3, 2), (2, 1)])
|
||||
|
||||
has_key tests:
|
||||
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d.has_key(1)
|
||||
1
|
||||
>>> d.has_key(4)
|
||||
0
|
||||
"""
|
||||
|
||||
def __init__(self, init_val=(), strict=False):
|
||||
"""
|
||||
Create a new ordered dictionary. Cannot init from a normal dict,
|
||||
nor from kwargs, since items order is undefined in those cases.
|
||||
|
||||
If the ``strict`` keyword argument is ``True`` (``False`` is the
|
||||
default) then when doing slice assignment - the ``OrderedDict`` you are
|
||||
assigning from *must not* contain any keys in the remaining dict.
|
||||
|
||||
>>> OrderedDict()
|
||||
OrderedDict([])
|
||||
>>> OrderedDict({1: 1})
|
||||
Traceback (most recent call last):
|
||||
TypeError: undefined order, cannot get items from dict
|
||||
>>> OrderedDict({1: 1}.items())
|
||||
OrderedDict([(1, 1)])
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d
|
||||
OrderedDict([(1, 3), (3, 2), (2, 1)])
|
||||
>>> OrderedDict(d)
|
||||
OrderedDict([(1, 3), (3, 2), (2, 1)])
|
||||
"""
|
||||
self.strict = strict
|
||||
dict.__init__(self)
|
||||
if isinstance(init_val, OrderedDict):
|
||||
self._sequence = init_val.keys()
|
||||
dict.update(self, init_val)
|
||||
elif isinstance(init_val, dict):
|
||||
# we lose compatibility with other ordered dict types this way
|
||||
raise TypeError('undefined order, cannot get items from dict')
|
||||
else:
|
||||
self._sequence = []
|
||||
self.update(init_val)
|
||||
|
||||
### Special methods ###
|
||||
|
||||
def __delitem__(self, key):
|
||||
"""
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> del d[3]
|
||||
>>> d
|
||||
OrderedDict([(1, 3), (2, 1)])
|
||||
>>> del d[3]
|
||||
Traceback (most recent call last):
|
||||
KeyError: 3
|
||||
>>> d[3] = 2
|
||||
>>> d
|
||||
OrderedDict([(1, 3), (2, 1), (3, 2)])
|
||||
>>> del d[0:1]
|
||||
>>> d
|
||||
OrderedDict([(2, 1), (3, 2)])
|
||||
"""
|
||||
if isinstance(key, slice):
|
||||
# FIXME: efficiency?
|
||||
keys = self._sequence[key]
|
||||
for entry in keys:
|
||||
dict.__delitem__(self, entry)
|
||||
del self._sequence[key]
|
||||
else:
|
||||
# do the dict.__delitem__ *first* as it raises
|
||||
# the more appropriate error
|
||||
dict.__delitem__(self, key)
|
||||
self._sequence.remove(key)
|
||||
|
||||
def __eq__(self, other):
|
||||
"""
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d == OrderedDict(d)
|
||||
True
|
||||
>>> d == OrderedDict(((1, 3), (2, 1), (3, 2)))
|
||||
False
|
||||
>>> d == OrderedDict(((1, 0), (3, 2), (2, 1)))
|
||||
False
|
||||
>>> d == OrderedDict(((0, 3), (3, 2), (2, 1)))
|
||||
False
|
||||
>>> d == dict(d)
|
||||
False
|
||||
>>> d == False
|
||||
False
|
||||
"""
|
||||
if isinstance(other, OrderedDict):
|
||||
# FIXME: efficiency?
|
||||
# Generate both item lists for each compare
|
||||
return (self.items() == other.items())
|
||||
else:
|
||||
return False
|
||||
|
||||
def __lt__(self, other):
|
||||
"""
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
|
||||
>>> c < d
|
||||
True
|
||||
>>> d < c
|
||||
False
|
||||
>>> d < dict(c)
|
||||
Traceback (most recent call last):
|
||||
TypeError: Can only compare with other OrderedDicts
|
||||
"""
|
||||
if not isinstance(other, OrderedDict):
|
||||
raise TypeError('Can only compare with other OrderedDicts')
|
||||
# FIXME: efficiency?
|
||||
# Generate both item lists for each compare
|
||||
return (self.items() < other.items())
|
||||
|
||||
def __le__(self, other):
|
||||
"""
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
|
||||
>>> e = OrderedDict(d)
|
||||
>>> c <= d
|
||||
True
|
||||
>>> d <= c
|
||||
False
|
||||
>>> d <= dict(c)
|
||||
Traceback (most recent call last):
|
||||
TypeError: Can only compare with other OrderedDicts
|
||||
>>> d <= e
|
||||
True
|
||||
"""
|
||||
if not isinstance(other, OrderedDict):
|
||||
raise TypeError('Can only compare with other OrderedDicts')
|
||||
# FIXME: efficiency?
|
||||
# Generate both item lists for each compare
|
||||
return (self.items() <= other.items())
|
||||
|
||||
def __ne__(self, other):
|
||||
"""
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d != OrderedDict(d)
|
||||
False
|
||||
>>> d != OrderedDict(((1, 3), (2, 1), (3, 2)))
|
||||
True
|
||||
>>> d != OrderedDict(((1, 0), (3, 2), (2, 1)))
|
||||
True
|
||||
>>> d == OrderedDict(((0, 3), (3, 2), (2, 1)))
|
||||
False
|
||||
>>> d != dict(d)
|
||||
True
|
||||
>>> d != False
|
||||
True
|
||||
"""
|
||||
if isinstance(other, OrderedDict):
|
||||
# FIXME: efficiency?
|
||||
# Generate both item lists for each compare
|
||||
return not (self.items() == other.items())
|
||||
else:
|
||||
return True
|
||||
|
||||
def __gt__(self, other):
|
||||
"""
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
|
||||
>>> d > c
|
||||
True
|
||||
>>> c > d
|
||||
False
|
||||
>>> d > dict(c)
|
||||
Traceback (most recent call last):
|
||||
TypeError: Can only compare with other OrderedDicts
|
||||
"""
|
||||
if not isinstance(other, OrderedDict):
|
||||
raise TypeError('Can only compare with other OrderedDicts')
|
||||
# FIXME: efficiency?
|
||||
# Generate both item lists for each compare
|
||||
return (self.items() > other.items())
|
||||
|
||||
def __ge__(self, other):
|
||||
"""
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
|
||||
>>> e = OrderedDict(d)
|
||||
>>> c >= d
|
||||
False
|
||||
>>> d >= c
|
||||
True
|
||||
>>> d >= dict(c)
|
||||
Traceback (most recent call last):
|
||||
TypeError: Can only compare with other OrderedDicts
|
||||
>>> e >= d
|
||||
True
|
||||
"""
|
||||
if not isinstance(other, OrderedDict):
|
||||
raise TypeError('Can only compare with other OrderedDicts')
|
||||
# FIXME: efficiency?
|
||||
# Generate both item lists for each compare
|
||||
return (self.items() >= other.items())
|
||||
|
||||
def __repr__(self):
|
||||
"""
|
||||
Used for __repr__ and __str__
|
||||
|
||||
>>> r1 = repr(OrderedDict((('a', 'b'), ('c', 'd'), ('e', 'f'))))
|
||||
>>> r1
|
||||
"OrderedDict([('a', 'b'), ('c', 'd'), ('e', 'f')])"
|
||||
>>> r2 = repr(OrderedDict((('a', 'b'), ('e', 'f'), ('c', 'd'))))
|
||||
>>> r2
|
||||
"OrderedDict([('a', 'b'), ('e', 'f'), ('c', 'd')])"
|
||||
>>> r1 == str(OrderedDict((('a', 'b'), ('c', 'd'), ('e', 'f'))))
|
||||
True
|
||||
>>> r2 == str(OrderedDict((('a', 'b'), ('e', 'f'), ('c', 'd'))))
|
||||
True
|
||||
"""
|
||||
return '%s([%s])' % (self.__class__.__name__, ', '.join(
|
||||
['(%r, %r)' % (key, self[key]) for key in self._sequence]))
|
||||
|
||||
def __setitem__(self, key, val):
|
||||
"""
|
||||
Allows slice assignment, so long as the slice is an OrderedDict
|
||||
>>> d = OrderedDict()
|
||||
>>> d['a'] = 'b'
|
||||
>>> d['b'] = 'a'
|
||||
>>> d[3] = 12
|
||||
>>> d
|
||||
OrderedDict([('a', 'b'), ('b', 'a'), (3, 12)])
|
||||
>>> d[:] = OrderedDict(((1, 2), (2, 3), (3, 4)))
|
||||
>>> d
|
||||
OrderedDict([(1, 2), (2, 3), (3, 4)])
|
||||
>>> d[::2] = OrderedDict(((7, 8), (9, 10)))
|
||||
>>> d
|
||||
OrderedDict([(7, 8), (2, 3), (9, 10)])
|
||||
>>> d = OrderedDict(((0, 1), (1, 2), (2, 3), (3, 4)))
|
||||
>>> d[1:3] = OrderedDict(((1, 2), (5, 6), (7, 8)))
|
||||
>>> d
|
||||
OrderedDict([(0, 1), (1, 2), (5, 6), (7, 8), (3, 4)])
|
||||
>>> d = OrderedDict(((0, 1), (1, 2), (2, 3), (3, 4)), strict=True)
|
||||
>>> d[1:3] = OrderedDict(((1, 2), (5, 6), (7, 8)))
|
||||
>>> d
|
||||
OrderedDict([(0, 1), (1, 2), (5, 6), (7, 8), (3, 4)])
|
||||
|
||||
>>> a = OrderedDict(((0, 1), (1, 2), (2, 3)), strict=True)
|
||||
>>> a[3] = 4
|
||||
>>> a
|
||||
OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
|
||||
>>> a[::1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
|
||||
>>> a
|
||||
OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
|
||||
>>> a[:2] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)])
|
||||
Traceback (most recent call last):
|
||||
ValueError: slice assignment must be from unique keys
|
||||
>>> a = OrderedDict(((0, 1), (1, 2), (2, 3)))
|
||||
>>> a[3] = 4
|
||||
>>> a
|
||||
OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
|
||||
>>> a[::1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
|
||||
>>> a
|
||||
OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
|
||||
>>> a[:2] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
|
||||
>>> a
|
||||
OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
|
||||
>>> a[::-1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
|
||||
>>> a
|
||||
OrderedDict([(3, 4), (2, 3), (1, 2), (0, 1)])
|
||||
|
||||
>>> d = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
|
||||
>>> d[:1] = 3
|
||||
Traceback (most recent call last):
|
||||
TypeError: slice assignment requires an OrderedDict
|
||||
|
||||
>>> d = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
|
||||
>>> d[:1] = OrderedDict([(9, 8)])
|
||||
>>> d
|
||||
OrderedDict([(9, 8), (1, 2), (2, 3), (3, 4)])
|
||||
"""
|
||||
if isinstance(key, slice):
|
||||
if not isinstance(val, OrderedDict):
|
||||
# FIXME: allow a list of tuples?
|
||||
raise TypeError('slice assignment requires an OrderedDict')
|
||||
keys = self._sequence[key]
|
||||
# NOTE: Could use ``range(*key.indices(len(self._sequence)))``
|
||||
indexes = range(len(self._sequence))[key]
|
||||
if key.step is None:
|
||||
# NOTE: new slice may not be the same size as the one being
|
||||
# overwritten !
|
||||
# NOTE: What is the algorithm for an impossible slice?
|
||||
# e.g. d[5:3]
|
||||
pos = key.start or 0
|
||||
del self[key]
|
||||
newkeys = val.keys()
|
||||
for k in newkeys:
|
||||
if k in self:
|
||||
if self.strict:
|
||||
raise ValueError('slice assignment must be from '
|
||||
'unique keys')
|
||||
else:
|
||||
# NOTE: This removes duplicate keys *first*
|
||||
# so start position might have changed?
|
||||
del self[k]
|
||||
self._sequence = (self._sequence[:pos] + newkeys +
|
||||
self._sequence[pos:])
|
||||
dict.update(self, val)
|
||||
else:
|
||||
# extended slice - length of new slice must be the same
|
||||
# as the one being replaced
|
||||
if len(keys) != len(val):
|
||||
raise ValueError('attempt to assign sequence of size %s '
|
||||
'to extended slice of size %s' % (len(val), len(keys)))
|
||||
# FIXME: efficiency?
|
||||
del self[key]
|
||||
item_list = zip(indexes, val.items())
|
||||
# smallest indexes first - higher indexes not guaranteed to
|
||||
# exist
|
||||
item_list.sort()
|
||||
for pos, (newkey, newval) in item_list:
|
||||
if self.strict and newkey in self:
|
||||
raise ValueError('slice assignment must be from unique'
|
||||
' keys')
|
||||
self.insert(pos, newkey, newval)
|
||||
else:
|
||||
if key not in self:
|
||||
self._sequence.append(key)
|
||||
dict.__setitem__(self, key, val)
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""
|
||||
Allows slicing. Returns an OrderedDict if you slice.
|
||||
>>> b = OrderedDict([(7, 0), (6, 1), (5, 2), (4, 3), (3, 4), (2, 5), (1, 6)])
|
||||
>>> b[::-1]
|
||||
OrderedDict([(1, 6), (2, 5), (3, 4), (4, 3), (5, 2), (6, 1), (7, 0)])
|
||||
>>> b[2:5]
|
||||
OrderedDict([(5, 2), (4, 3), (3, 4)])
|
||||
>>> type(b[2:4])
|
||||
<class '__main__.OrderedDict'>
|
||||
"""
|
||||
if isinstance(key, slice):
|
||||
# FIXME: does this raise the error we want?
|
||||
keys = self._sequence[key]
|
||||
# FIXME: efficiency?
|
||||
return OrderedDict([(entry, self[entry]) for entry in keys])
|
||||
else:
|
||||
return dict.__getitem__(self, key)
|
||||
|
||||
__str__ = __repr__
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
"""
|
||||
Implemented so that accesses to ``sequence`` raise a warning and are
|
||||
diverted to the new ``setkeys`` method.
|
||||
"""
|
||||
if name == 'sequence':
|
||||
warnings.warn('Use of the sequence attribute is deprecated.'
|
||||
' Use the keys method instead.', DeprecationWarning)
|
||||
# NOTE: doesn't return anything
|
||||
self.setkeys(value)
|
||||
else:
|
||||
# FIXME: do we want to allow arbitrary setting of attributes?
|
||||
# Or do we want to manage it?
|
||||
object.__setattr__(self, name, value)
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""
|
||||
Implemented so that access to ``sequence`` raises a warning.
|
||||
|
||||
>>> d = OrderedDict()
|
||||
>>> d.sequence
|
||||
[]
|
||||
"""
|
||||
if name == 'sequence':
|
||||
warnings.warn('Use of the sequence attribute is deprecated.'
|
||||
' Use the keys method instead.', DeprecationWarning)
|
||||
# NOTE: Still (currently) returns a direct reference. Need to
|
||||
# because code that uses sequence will expect to be able to
|
||||
# mutate it in place.
|
||||
return self._sequence
|
||||
else:
|
||||
# raise the appropriate error
|
||||
raise AttributeError("OrderedDict has no '%s' attribute" % name)
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
"""
|
||||
To allow deepcopy to work with OrderedDict.
|
||||
|
||||
>>> from copy import deepcopy
|
||||
>>> a = OrderedDict([(1, 1), (2, 2), (3, 3)])
|
||||
>>> a['test'] = {}
|
||||
>>> b = deepcopy(a)
|
||||
>>> b == a
|
||||
True
|
||||
>>> b is a
|
||||
False
|
||||
>>> a['test'] is b['test']
|
||||
False
|
||||
"""
|
||||
from copy import deepcopy
|
||||
return self.__class__(deepcopy(self.items(), memo), self.strict)
|
||||
|
||||
### Read-only methods ###
|
||||
|
||||
def copy(self):
|
||||
"""
|
||||
>>> OrderedDict(((1, 3), (3, 2), (2, 1))).copy()
|
||||
OrderedDict([(1, 3), (3, 2), (2, 1)])
|
||||
"""
|
||||
return OrderedDict(self)
|
||||
|
||||
def items(self):
|
||||
"""
|
||||
``items`` returns a list of tuples representing all the
|
||||
``(key, value)`` pairs in the dictionary.
|
||||
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d.items()
|
||||
[(1, 3), (3, 2), (2, 1)]
|
||||
>>> d.clear()
|
||||
>>> d.items()
|
||||
[]
|
||||
"""
|
||||
return zip(self._sequence, self.values())
|
||||
|
||||
def keys(self):
|
||||
"""
|
||||
Return a list of keys in the ``OrderedDict``.
|
||||
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d.keys()
|
||||
[1, 3, 2]
|
||||
"""
|
||||
return self._sequence[:]
|
||||
|
||||
def values(self, values=None):
|
||||
"""
|
||||
Return a list of all the values in the OrderedDict.
|
||||
|
||||
Optionally you can pass in a list of values, which will replace the
|
||||
current list. The value list must be the same len as the OrderedDict.
|
||||
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d.values()
|
||||
[3, 2, 1]
|
||||
"""
|
||||
return [self[key] for key in self._sequence]
|
||||
|
||||
def iteritems(self):
|
||||
"""
|
||||
>>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iteritems()
|
||||
>>> ii.next()
|
||||
(1, 3)
|
||||
>>> ii.next()
|
||||
(3, 2)
|
||||
>>> ii.next()
|
||||
(2, 1)
|
||||
>>> ii.next()
|
||||
Traceback (most recent call last):
|
||||
StopIteration
|
||||
"""
|
||||
def make_iter(self=self):
|
||||
keys = self.iterkeys()
|
||||
while True:
|
||||
key = keys.next()
|
||||
yield (key, self[key])
|
||||
return make_iter()
|
||||
|
||||
def iterkeys(self):
|
||||
"""
|
||||
>>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iterkeys()
|
||||
>>> ii.next()
|
||||
1
|
||||
>>> ii.next()
|
||||
3
|
||||
>>> ii.next()
|
||||
2
|
||||
>>> ii.next()
|
||||
Traceback (most recent call last):
|
||||
StopIteration
|
||||
"""
|
||||
return iter(self._sequence)
|
||||
|
||||
__iter__ = iterkeys
|
||||
|
||||
def itervalues(self):
|
||||
"""
|
||||
>>> iv = OrderedDict(((1, 3), (3, 2), (2, 1))).itervalues()
|
||||
>>> iv.next()
|
||||
3
|
||||
>>> iv.next()
|
||||
2
|
||||
>>> iv.next()
|
||||
1
|
||||
>>> iv.next()
|
||||
Traceback (most recent call last):
|
||||
StopIteration
|
||||
"""
|
||||
def make_iter(self=self):
|
||||
keys = self.iterkeys()
|
||||
while True:
|
||||
yield self[keys.next()]
|
||||
return make_iter()
|
||||
|
||||
### Read-write methods ###
|
||||
|
||||
def clear(self):
|
||||
"""
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d.clear()
|
||||
>>> d
|
||||
OrderedDict([])
|
||||
"""
|
||||
dict.clear(self)
|
||||
self._sequence = []
|
||||
|
||||
def pop(self, key, *args):
|
||||
"""
|
||||
No dict.pop in Python 2.2, gotta reimplement it
|
||||
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d.pop(3)
|
||||
2
|
||||
>>> d
|
||||
OrderedDict([(1, 3), (2, 1)])
|
||||
>>> d.pop(4)
|
||||
Traceback (most recent call last):
|
||||
KeyError: 4
|
||||
>>> d.pop(4, 0)
|
||||
0
|
||||
>>> d.pop(4, 0, 1)
|
||||
Traceback (most recent call last):
|
||||
TypeError: pop expected at most 2 arguments, got 3
|
||||
"""
|
||||
if len(args) > 1:
|
||||
raise TypeError('pop expected at most 2 arguments, got %s' %
|
||||
(len(args) + 1))
|
||||
if key in self:
|
||||
val = self[key]
|
||||
del self[key]
|
||||
else:
|
||||
try:
|
||||
val = args[0]
|
||||
except IndexError:
|
||||
raise KeyError(key)
|
||||
return val
|
||||
|
||||
def popitem(self, i=-1):
|
||||
"""
|
||||
Delete and return an item specified by index, not a random one as in
|
||||
dict. The index is -1 by default (the last item).
|
||||
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d.popitem()
|
||||
(2, 1)
|
||||
>>> d
|
||||
OrderedDict([(1, 3), (3, 2)])
|
||||
>>> d.popitem(0)
|
||||
(1, 3)
|
||||
>>> OrderedDict().popitem()
|
||||
Traceback (most recent call last):
|
||||
KeyError: 'popitem(): dictionary is empty'
|
||||
>>> d.popitem(2)
|
||||
Traceback (most recent call last):
|
||||
IndexError: popitem(): index 2 not valid
|
||||
"""
|
||||
if not self._sequence:
|
||||
raise KeyError('popitem(): dictionary is empty')
|
||||
try:
|
||||
key = self._sequence[i]
|
||||
except IndexError:
|
||||
raise IndexError('popitem(): index %s not valid' % i)
|
||||
return (key, self.pop(key))
|
||||
|
||||
def setdefault(self, key, defval=None):
|
||||
"""
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d.setdefault(1)
|
||||
3
|
||||
>>> d.setdefault(4) is None
|
||||
True
|
||||
>>> d
|
||||
OrderedDict([(1, 3), (3, 2), (2, 1), (4, None)])
|
||||
>>> d.setdefault(5, 0)
|
||||
0
|
||||
>>> d
|
||||
OrderedDict([(1, 3), (3, 2), (2, 1), (4, None), (5, 0)])
|
||||
"""
|
||||
if key in self:
|
||||
return self[key]
|
||||
else:
|
||||
self[key] = defval
|
||||
return defval
|
||||
|
||||
def update(self, from_od):
|
||||
"""
|
||||
Update from another OrderedDict or sequence of (key, value) pairs
|
||||
|
||||
>>> d = OrderedDict(((1, 0), (0, 1)))
|
||||
>>> d.update(OrderedDict(((1, 3), (3, 2), (2, 1))))
|
||||
>>> d
|
||||
OrderedDict([(1, 3), (0, 1), (3, 2), (2, 1)])
|
||||
>>> d.update({4: 4})
|
||||
Traceback (most recent call last):
|
||||
TypeError: undefined order, cannot get items from dict
|
||||
>>> d.update((4, 4))
|
||||
Traceback (most recent call last):
|
||||
TypeError: cannot convert dictionary update sequence element "4" to a 2-item sequence
|
||||
"""
|
||||
if isinstance(from_od, OrderedDict):
|
||||
for key, val in from_od.items():
|
||||
self[key] = val
|
||||
elif isinstance(from_od, dict):
|
||||
# we lose compatibility with other ordered dict types this way
|
||||
raise TypeError('undefined order, cannot get items from dict')
|
||||
else:
|
||||
# FIXME: efficiency?
|
||||
# sequence of 2-item sequences, or error
|
||||
for item in from_od:
|
||||
try:
|
||||
key, val = item
|
||||
except TypeError:
|
||||
raise TypeError('cannot convert dictionary update'
|
||||
' sequence element "%s" to a 2-item sequence' % item)
|
||||
self[key] = val
|
||||
|
||||
def rename(self, old_key, new_key):
|
||||
"""
|
||||
Rename the key for a given value, without modifying sequence order.
|
||||
|
||||
For the case where new_key already exists this raise an exception,
|
||||
since if new_key exists, it is ambiguous as to what happens to the
|
||||
associated values, and the position of new_key in the sequence.
|
||||
|
||||
>>> od = OrderedDict()
|
||||
>>> od['a'] = 1
|
||||
>>> od['b'] = 2
|
||||
>>> od.items()
|
||||
[('a', 1), ('b', 2)]
|
||||
>>> od.rename('b', 'c')
|
||||
>>> od.items()
|
||||
[('a', 1), ('c', 2)]
|
||||
>>> od.rename('c', 'a')
|
||||
Traceback (most recent call last):
|
||||
ValueError: New key already exists: 'a'
|
||||
>>> od.rename('d', 'b')
|
||||
Traceback (most recent call last):
|
||||
KeyError: 'd'
|
||||
"""
|
||||
if new_key == old_key:
|
||||
# no-op
|
||||
return
|
||||
if new_key in self:
|
||||
raise ValueError("New key already exists: %r" % new_key)
|
||||
# rename sequence entry
|
||||
value = self[old_key]
|
||||
old_idx = self._sequence.index(old_key)
|
||||
self._sequence[old_idx] = new_key
|
||||
# rename internal dict entry
|
||||
dict.__delitem__(self, old_key)
|
||||
dict.__setitem__(self, new_key, value)
|
||||
|
||||
def setitems(self, items):
|
||||
"""
|
||||
This method allows you to set the items in the dict.
|
||||
|
||||
It takes a list of tuples - of the same sort returned by the ``items``
|
||||
method.
|
||||
|
||||
>>> d = OrderedDict()
|
||||
>>> d.setitems(((3, 1), (2, 3), (1, 2)))
|
||||
>>> d
|
||||
OrderedDict([(3, 1), (2, 3), (1, 2)])
|
||||
"""
|
||||
self.clear()
|
||||
# FIXME: this allows you to pass in an OrderedDict as well :-)
|
||||
self.update(items)
|
||||
|
||||
def setkeys(self, keys):
|
||||
"""
|
||||
``setkeys`` all ows you to pass in a new list of keys which will
|
||||
replace the current set. This must contain the same set of keys, but
|
||||
need not be in the same order.
|
||||
|
||||
If you pass in new keys that don't match, a ``KeyError`` will be
|
||||
raised.
|
||||
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d.keys()
|
||||
[1, 3, 2]
|
||||
>>> d.setkeys((1, 2, 3))
|
||||
>>> d
|
||||
OrderedDict([(1, 3), (2, 1), (3, 2)])
|
||||
>>> d.setkeys(['a', 'b', 'c'])
|
||||
Traceback (most recent call last):
|
||||
KeyError: 'Keylist is not the same as current keylist.'
|
||||
"""
|
||||
# FIXME: Efficiency? (use set for Python 2.4 :-)
|
||||
# NOTE: list(keys) rather than keys[:] because keys[:] returns
|
||||
# a tuple, if keys is a tuple.
|
||||
kcopy = list(keys)
|
||||
kcopy.sort()
|
||||
self._sequence.sort()
|
||||
if kcopy != self._sequence:
|
||||
raise KeyError('Keylist is not the same as current keylist.')
|
||||
# NOTE: This makes the _sequence attribute a new object, instead
|
||||
# of changing it in place.
|
||||
# FIXME: efficiency?
|
||||
self._sequence = list(keys)
|
||||
|
||||
def setvalues(self, values):
|
||||
"""
|
||||
You can pass in a list of values, which will replace the
|
||||
current list. The value list must be the same len as the OrderedDict.
|
||||
|
||||
(Or a ``ValueError`` is raised.)
|
||||
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d.setvalues((1, 2, 3))
|
||||
>>> d
|
||||
OrderedDict([(1, 1), (3, 2), (2, 3)])
|
||||
>>> d.setvalues([6])
|
||||
Traceback (most recent call last):
|
||||
ValueError: Value list is not the same length as the OrderedDict.
|
||||
"""
|
||||
if len(values) != len(self):
|
||||
# FIXME: correct error to raise?
|
||||
raise ValueError('Value list is not the same length as the '
|
||||
'OrderedDict.')
|
||||
self.update(zip(self, values))
|
||||
|
||||
### Sequence Methods ###
|
||||
|
||||
def index(self, key):
|
||||
"""
|
||||
Return the position of the specified key in the OrderedDict.
|
||||
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d.index(3)
|
||||
1
|
||||
>>> d.index(4)
|
||||
Traceback (most recent call last):
|
||||
ValueError: 4 is not in list
|
||||
"""
|
||||
return self._sequence.index(key)
|
||||
|
||||
def insert(self, index, key, value):
|
||||
"""
|
||||
Takes ``index``, ``key``, and ``value`` as arguments.
|
||||
|
||||
Sets ``key`` to ``value``, so that ``key`` is at position ``index`` in
|
||||
the OrderedDict.
|
||||
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d.insert(0, 4, 0)
|
||||
>>> d
|
||||
OrderedDict([(4, 0), (1, 3), (3, 2), (2, 1)])
|
||||
>>> d.insert(0, 2, 1)
|
||||
>>> d
|
||||
OrderedDict([(2, 1), (4, 0), (1, 3), (3, 2)])
|
||||
>>> d.insert(8, 8, 1)
|
||||
>>> d
|
||||
OrderedDict([(2, 1), (4, 0), (1, 3), (3, 2), (8, 1)])
|
||||
"""
|
||||
if key in self:
|
||||
# FIXME: efficiency?
|
||||
del self[key]
|
||||
self._sequence.insert(index, key)
|
||||
dict.__setitem__(self, key, value)
|
||||
|
||||
def reverse(self):
|
||||
"""
|
||||
Reverse the order of the OrderedDict.
|
||||
|
||||
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
|
||||
>>> d.reverse()
|
||||
>>> d
|
||||
OrderedDict([(2, 1), (3, 2), (1, 3)])
|
||||
"""
|
||||
self._sequence.reverse()
|
||||
|
||||
def sort(self, *args, **kwargs):
|
||||
"""
|
||||
Sort the key order in the OrderedDict.
|
||||
|
||||
This method takes the same arguments as the ``list.sort`` method on
|
||||
your version of Python.
|
||||
|
||||
>>> d = OrderedDict(((4, 1), (2, 2), (3, 3), (1, 4)))
|
||||
>>> d.sort()
|
||||
>>> d
|
||||
OrderedDict([(1, 4), (2, 2), (3, 3), (4, 1)])
|
||||
"""
|
||||
self._sequence.sort(*args, **kwargs)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# turn off warnings for tests
|
||||
warnings.filterwarnings('ignore')
|
||||
# run the code tests in doctest format
|
||||
import doctest
|
||||
m = sys.modules.get('__main__')
|
||||
globs = m.__dict__.copy()
|
||||
globs.update({
|
||||
'INTP_VER': INTP_VER,
|
||||
})
|
||||
doctest.testmod(m, globs=globs)
|
@ -0,0 +1,35 @@
|
||||
"""EditorConfig version tools
|
||||
|
||||
Provides ``join_version`` and ``split_version`` classes for converting
|
||||
__version__ strings to VERSION tuples and vice versa.
|
||||
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
|
||||
__all__ = ['join_version', 'split_version']
|
||||
|
||||
|
||||
_version_re = re.compile(r'^(\d+)\.(\d+)\.(\d+)(\..*)?$', re.VERBOSE)
|
||||
|
||||
|
||||
def join_version(version_tuple):
|
||||
"""Return a string representation of version from given VERSION tuple"""
|
||||
version = "%s.%s.%s" % version_tuple[:3]
|
||||
if version_tuple[3] != "final":
|
||||
version += "-%s" % version_tuple[3]
|
||||
return version
|
||||
|
||||
|
||||
def split_version(version):
|
||||
"""Return VERSION tuple for given string representation of version"""
|
||||
match = _version_re.search(version)
|
||||
if not match:
|
||||
return None
|
||||
else:
|
||||
split_version = list(match.groups())
|
||||
if split_version[3] is None:
|
||||
split_version[3] = "final"
|
||||
split_version = list(map(int, split_version[:3])) + split_version[3:]
|
||||
return tuple(split_version)
|
@ -0,0 +1,9 @@
|
||||
[*.java]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = LF
|
||||
|
||||
[*.xml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = LF
|
@ -0,0 +1,5 @@
|
||||
*.class
|
||||
/classes
|
||||
/build
|
||||
/tmp
|
||||
/doc
|
@ -0,0 +1,192 @@
|
||||
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
||||
--------------------------------------------
|
||||
|
||||
1. This LICENSE AGREEMENT is between the Python Software Foundation
|
||||
("PSF"), and the Individual or Organization ("Licensee") accessing and
|
||||
otherwise using this software ("Python") 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 alone or in any derivative version,
|
||||
provided, however, that PSF's License Agreement and PSF's notice of copyright,
|
||||
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
Python Software Foundation; All Rights Reserved" are retained in Python 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 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.
|
||||
|
||||
4. PSF is making Python 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 WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
|
||||
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, Licensee
|
||||
agrees to be bound by the terms and conditions of this License
|
||||
Agreement.
|
||||
|
||||
|
||||
BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
|
||||
-------------------------------------------
|
||||
|
||||
BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
|
||||
|
||||
1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
|
||||
office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
|
||||
Individual or Organization ("Licensee") accessing and otherwise using
|
||||
this software in source or binary form and its associated
|
||||
documentation ("the Software").
|
||||
|
||||
2. Subject to the terms and conditions of this BeOpen Python License
|
||||
Agreement, BeOpen hereby grants Licensee a non-exclusive,
|
||||
royalty-free, world-wide license to reproduce, analyze, test, perform
|
||||
and/or display publicly, prepare derivative works, distribute, and
|
||||
otherwise use the Software alone or in any derivative version,
|
||||
provided, however, that the BeOpen Python License is retained in the
|
||||
Software, alone or in any derivative version prepared by Licensee.
|
||||
|
||||
3. BeOpen is making the Software available to Licensee on an "AS IS"
|
||||
basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
|
||||
SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
|
||||
AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
|
||||
DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
|
||||
5. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
|
||||
6. This License Agreement shall be governed by and interpreted in all
|
||||
respects by the law of the State of California, excluding conflict of
|
||||
law provisions. Nothing in this License Agreement shall be deemed to
|
||||
create any relationship of agency, partnership, or joint venture
|
||||
between BeOpen and Licensee. This License Agreement does not grant
|
||||
permission to use BeOpen trademarks or trade names in a trademark
|
||||
sense to endorse or promote products or services of Licensee, or any
|
||||
third party. As an exception, the "BeOpen Python" logos available at
|
||||
http://www.pythonlabs.com/logos.html may be used according to the
|
||||
permissions granted on that web page.
|
||||
|
||||
7. By copying, installing or otherwise using the software, Licensee
|
||||
agrees to be bound by the terms and conditions of this License
|
||||
Agreement.
|
||||
|
||||
|
||||
CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
|
||||
---------------------------------------
|
||||
|
||||
1. This LICENSE AGREEMENT is between the Corporation for National
|
||||
Research Initiatives, having an office at 1895 Preston White Drive,
|
||||
Reston, VA 20191 ("CNRI"), and the Individual or Organization
|
||||
("Licensee") accessing and otherwise using Python 1.6.1 software in
|
||||
source or binary form and its associated documentation.
|
||||
|
||||
2. Subject to the terms and conditions of this License Agreement, CNRI
|
||||
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 1.6.1
|
||||
alone or in any derivative version, provided, however, that CNRI's
|
||||
License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
|
||||
1995-2001 Corporation for National Research Initiatives; All Rights
|
||||
Reserved" are retained in Python 1.6.1 alone or in any derivative
|
||||
version prepared by Licensee. Alternately, in lieu of CNRI's License
|
||||
Agreement, Licensee may substitute the following text (omitting the
|
||||
quotes): "Python 1.6.1 is made available subject to the terms and
|
||||
conditions in CNRI's License Agreement. This Agreement together with
|
||||
Python 1.6.1 may be located on the Internet using the following
|
||||
unique, persistent identifier (known as a handle): 1895.22/1013. This
|
||||
Agreement may also be obtained from a proxy server on the Internet
|
||||
using the following URL: http://hdl.handle.net/1895.22/1013".
|
||||
|
||||
3. In the event Licensee prepares a derivative work that is based on
|
||||
or incorporates Python 1.6.1 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 1.6.1.
|
||||
|
||||
4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
|
||||
basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||
1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
|
||||
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. This License Agreement shall be governed by the federal
|
||||
intellectual property law of the United States, including without
|
||||
limitation the federal copyright law, and, to the extent such
|
||||
U.S. federal law does not apply, by the law of the Commonwealth of
|
||||
Virginia, excluding Virginia's conflict of law provisions.
|
||||
Notwithstanding the foregoing, with regard to derivative works based
|
||||
on Python 1.6.1 that incorporate non-separable material that was
|
||||
previously distributed under the GNU General Public License (GPL), the
|
||||
law of the Commonwealth of Virginia shall govern this License
|
||||
Agreement only as to issues arising under or with respect to
|
||||
Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
|
||||
License Agreement shall be deemed to create any relationship of
|
||||
agency, partnership, or joint venture between CNRI and Licensee. This
|
||||
License Agreement does not grant permission to use CNRI trademarks or
|
||||
trade name in a trademark sense to endorse or promote products or
|
||||
services of Licensee, or any third party.
|
||||
|
||||
8. By clicking on the "ACCEPT" button where indicated, or by copying,
|
||||
installing or otherwise using Python 1.6.1, Licensee agrees to be
|
||||
bound by the terms and conditions of this License Agreement.
|
||||
|
||||
ACCEPT
|
||||
|
||||
|
||||
CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
|
||||
--------------------------------------------------
|
||||
|
||||
Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
|
||||
The Netherlands. All rights reserved.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the name of Stichting Mathematisch
|
||||
Centrum or CWI not be used in advertising or publicity pertaining to
|
||||
distribution of the software without specific, written prior
|
||||
permission.
|
||||
|
||||
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
||||
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
|
||||
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
@ -0,0 +1,60 @@
|
||||
# EditorConfig Java Binding
|
||||
|
||||
This directory is for [EditorConfig][] Core Java Binding. This binding is a
|
||||
Java wrapper for [EditorConfig Python Core][], made possible by [Jython][].
|
||||
|
||||
## EditorConfig Project
|
||||
|
||||
EditorConfig makes it easy to maintain the correct coding style when switching
|
||||
between different text editors and between different projects. The
|
||||
EditorConfig project maintains a file format and plugins for various text
|
||||
editors which allow this file format to be read and used by those editors. For
|
||||
information on the file format and supported text editors, see the
|
||||
[EditorConfig website][EditorConfig].
|
||||
|
||||
## Build the Library and Generate the Doc
|
||||
|
||||
With [Ant][]:
|
||||
|
||||
cd /path/to/editorconfig-core-py/java-binding
|
||||
ant && ant doc
|
||||
|
||||
The built jar file is in the `build` directory and the documentation is in the
|
||||
`doc` directory.
|
||||
|
||||
## Use as a Library
|
||||
|
||||
A basic example:
|
||||
|
||||
```java
|
||||
EditorConfig ec = new EditorConfig();
|
||||
List<EditorConfig.OutPair> l = null;
|
||||
try {
|
||||
l = ec.getProperties("/home/user/src/editorconfig-core-py/a.py");
|
||||
} catch(EditorConfigException e) {
|
||||
System.out.println(e);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
for(int i = 0; i < l.size(); ++i) {
|
||||
System.out.println(l.get(i).getKey() + "=" + l.get(i).getVal());
|
||||
}
|
||||
```
|
||||
|
||||
A more complex example is in the `example` directory. There is an
|
||||
[online documentation][] for API details, or you could run `ant doc` to
|
||||
generate html documentation. The generated documentation will locate in `doc`
|
||||
directory.
|
||||
|
||||
## License
|
||||
|
||||
All source files of the Java binding are distributed under the PSF license. See
|
||||
LICENSE.txt for details.
|
||||
|
||||
Copyright (C) 2012, EditorConfig Team
|
||||
|
||||
[Ant]: http://ant.apache.org
|
||||
[EditorConfig Python Core]: https://github.com/editorconfig/editorconfig-core-py
|
||||
[EditorConfig]: http://editorconfig.org
|
||||
[Jython]: http://www.jython.org
|
||||
[online documentation]: http://javadocs.editorconfig.org
|
@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" ?>
|
||||
|
||||
<project name="EditorConfigJava" default="all" basedir=".">
|
||||
|
||||
<property name="tmp.dir" value="${basedir}/tmp" />
|
||||
<property name="editorconfig.py.dir" value="./.." />
|
||||
<property name="build.dir" value="./build" />
|
||||
|
||||
<path id="jython.path">
|
||||
<pathelement location="${tmp.dir}/jython.jar" />
|
||||
</path>
|
||||
|
||||
<!-- Build EditorConfig Java wrapper -->
|
||||
<target name="build-java-wrapper">
|
||||
<mkdir dir="./classes" />
|
||||
<javac srcdir="./src" destdir="./classes">
|
||||
<classpath refid="jython.path" />
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Download jython installer -->
|
||||
<property name="jython.url" value="http://downloads.sourceforge.net/project/jython/jython/2.2.1/jython_installer-2.2.1.jar?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fjython%2Ffiles%2Fjython%2F2.2.1%2F&ts=1338203268" />
|
||||
<target name="download-jython">
|
||||
<mkdir dir="${tmp.dir}" />
|
||||
<get src="${jython.url}" dest="${tmp.dir}/jython_installer.jar" usetimestamp="true" verbose="true" />
|
||||
</target>
|
||||
|
||||
<!-- unpack jython installer -->
|
||||
<target name="unpack-jython" depends="download-jython">
|
||||
<java jar="${tmp.dir}/jython_installer.jar" fork="true">
|
||||
<arg value="-s" />
|
||||
<arg value="-v" />
|
||||
<arg value="-d" />
|
||||
<arg value="${tmp.dir}/install" />
|
||||
<arg value="-t" />
|
||||
<arg value="standalone" />
|
||||
</java>
|
||||
<move file="${tmp.dir}/install/jython.jar" todir="${tmp.dir}" />
|
||||
</target>
|
||||
|
||||
<!-- pack jython EditorConfig -->
|
||||
<target name="pack-jython-editorconfig" depends="unpack-jython,build-java-wrapper">
|
||||
<mkdir dir="${build.dir}" />
|
||||
<jar destfile="${build.dir}/editorconfig.jar">
|
||||
<fileset dir="./classes">
|
||||
<include name="**/*.class" />
|
||||
</fileset>
|
||||
<zipfileset src="${tmp.dir}/jython.jar" />
|
||||
<zipfileset dir="${editorconfig.py.dir}" prefix="Lib/">
|
||||
<include name="editorconfig/**.py" />
|
||||
</zipfileset>
|
||||
<fileset file="./README.md" />
|
||||
<fileset file="./LICENSE.txt" />
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="doc" depends="unpack-jython">
|
||||
<mkdir dir="./doc" />
|
||||
<javadoc sourcepath="./src" destdir="./doc" locale="en_US"
|
||||
windowtitle="EditorConfig Java Library API Documentation"
|
||||
linksource="true" nodeprecatedlist="true">
|
||||
<classpath>
|
||||
<fileset file="${tmp.dir}/jython.jar" />
|
||||
</classpath>
|
||||
|
||||
<link href="http://docs.oracle.com/javase/6/docs/api/" />
|
||||
</javadoc>
|
||||
</target>
|
||||
|
||||
<target name="clean">
|
||||
<delete dir="build" />
|
||||
<delete dir="classes" />
|
||||
<delete dir="tmp" />
|
||||
</target>
|
||||
|
||||
<target name="all" depends="pack-jython-editorconfig">
|
||||
</target>
|
||||
</project>
|
@ -0,0 +1,23 @@
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineFactory;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import java.util.List;
|
||||
import org.editorconfig.core.*;
|
||||
|
||||
public class TestEditorConfig {
|
||||
public static void main(String[] args) throws EditorConfigException {
|
||||
EditorConfig ec = new EditorConfig();
|
||||
List<EditorConfig.OutPair> l = null;
|
||||
try {
|
||||
l = ec.getProperties(System.getProperty("user.dir") + "/a.py");
|
||||
} catch(EditorConfigException e) {
|
||||
System.out.println(e);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
for(int i = 0; i < l.size(); ++i) {
|
||||
System.out.println(l.get(i).getKey() + "=" + l.get(i).getVal());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
@echo off
|
||||
|
||||
SETLOCAL
|
||||
|
||||
set LOCAL_CLASSPATH="../build/editorconfig.jar;.;%CLASSPATH%"
|
||||
javac -cp %LOCAL_CLASSPATH% TestEditorConfig.java
|
||||
java -cp %LOCAL_CLASSPATH% TestEditorConfig
|
||||
|
||||
ENDLOCAL
|
@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
CLASSPATH="../build/editorconfig.jar:.:$CLASSPATH"
|
||||
javac -cp $CLASSPATH TestEditorConfig.java
|
||||
java -cp $CLASSPATH TestEditorConfig
|
@ -0,0 +1,155 @@
|
||||
package org.editorconfig.core;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import org.python.core.Py;
|
||||
import org.python.core.PyString;
|
||||
import org.python.core.PySystemState;
|
||||
import org.python.util.PythonInterpreter;
|
||||
|
||||
/**
|
||||
* EditorConfig handler
|
||||
*/
|
||||
public class EditorConfig {
|
||||
|
||||
private PythonInterpreter pyInterp;
|
||||
|
||||
/**
|
||||
* String-String pair to store the parsing result.
|
||||
*/
|
||||
public class OutPair {
|
||||
private String key;
|
||||
private String val;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
OutPair(String key, String val) {
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the key of the current pair.
|
||||
*/
|
||||
public String getKey() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of the current pair.
|
||||
*/
|
||||
public String getVal() {
|
||||
return this.val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* EditorConfig constructor.
|
||||
*
|
||||
* @throws PythonException If a Jython exception happens.
|
||||
*
|
||||
* @see #EditorConfig(List)
|
||||
*/
|
||||
public EditorConfig()
|
||||
throws PythonException {
|
||||
|
||||
this(null);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* EditorConfig constructor.
|
||||
*
|
||||
* Same as {@link #EditorConfig()}, but with an additional parameter
|
||||
* {@code jarLocations}.
|
||||
*
|
||||
* @param jarLocations The possible locations of {@code editorconfig.jar}
|
||||
* file. This parameter is used in some cases, {@code editorconfig.jar}
|
||||
* cannot locate itself (e.g. java program launched in GNOME desktop
|
||||
* environment may have this kind of issue). However, some modules are
|
||||
* packed in {@code editorconfig.jar} file, so this file must be located
|
||||
* for this library to work correctly.
|
||||
*
|
||||
* @see #EditorConfig()
|
||||
*/
|
||||
public EditorConfig(List<String> jarLocations)
|
||||
throws PythonException {
|
||||
pyInterp = new PythonInterpreter(null, new PySystemState());
|
||||
PySystemState pySysStat = Py.getSystemState();
|
||||
|
||||
// Add all "jarLocations/Lib" to sys.path
|
||||
if(jarLocations != null)
|
||||
for(String jarPath : jarLocations)
|
||||
pySysStat.path.append(new PyString(jarPath + "/Lib"));
|
||||
|
||||
pyInterp.exec("from editorconfig import get_properties");
|
||||
pyInterp.exec("from editorconfig import exceptions");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse editorconfig files corresponding to the file path given by
|
||||
* filename, and return the parsing result.
|
||||
*
|
||||
* @param filename The full path to be parsed. The path is usually the path
|
||||
* of the file which is currently edited by the editor.
|
||||
*
|
||||
* @return The parsing result stored in a list of {@link
|
||||
* EditorConfig.OutPair}.
|
||||
*
|
||||
* @throws org.editorconfig.core.ParsingException If an
|
||||
* {@code .editorconfig} file could not be parsed
|
||||
*
|
||||
* @throws org.editorconfig.core.PathException If an invalid file path is
|
||||
* specified as {@code filename}
|
||||
*
|
||||
* @throws org.editorconfig.core.EditorConfigException If an EditorConfig
|
||||
* exception occurs. Usually one of {@link ParsingException} or {@link
|
||||
* PathException}.
|
||||
*
|
||||
* @throws org.editorconfig.core.PythonException If a Jython exception happens.
|
||||
*
|
||||
*/
|
||||
public List<OutPair> getProperties(String filename)
|
||||
throws EditorConfigException {
|
||||
|
||||
pyInterp.exec("try:\n" +
|
||||
"\toptions = get_properties(r\"\"\"" + filename + "\"\"\")\n" +
|
||||
"except exceptions.ParsingError:\n" +
|
||||
"\te = 'ParsingError'\n" +
|
||||
"except exceptions.PathError:\n" +
|
||||
"\te = 'PathError'\n" +
|
||||
"except exceptions.VersionError:\n" +
|
||||
"\te = 'VersionError'\n" +
|
||||
"except exceptions.EditorConfigError:\n" +
|
||||
"\te = 'EditorConfigError'\n" +
|
||||
"else:\n" +
|
||||
"\te = 'None'");
|
||||
|
||||
String except = pyInterp.get("e").toString();
|
||||
if(except.equals("ParsingError"))
|
||||
throw new ParsingException("Failed to parse .editorconfig file.");
|
||||
else if(except.equals("PathError"))
|
||||
throw new PathException("Invalid file name specified. Must be absolute path.");
|
||||
else if(except.equals("VersionError"))
|
||||
throw new VersionException("Invalid Version Specified.");
|
||||
|
||||
pyInterp.exec("option_count = len(options)");
|
||||
pyInterp.exec("option_items = options.items()");
|
||||
|
||||
LinkedList<OutPair> retList = new LinkedList<OutPair>();
|
||||
int count = Integer.parseInt(pyInterp.get("option_count").toString());
|
||||
for(int i = 0; i < count; ++i) {
|
||||
pyInterp.exec("option_key = option_items[" + i + "][0]");
|
||||
pyInterp.exec("option_item = option_items[" + i + "][1]");
|
||||
OutPair op = new OutPair(
|
||||
pyInterp.get("option_key").toString(),
|
||||
pyInterp.get("option_item").toString());
|
||||
|
||||
retList.add(op);
|
||||
}
|
||||
|
||||
return retList;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package org.editorconfig.core;
|
||||
|
||||
|
||||
/**
|
||||
* The base class of all EditorConfig exceptions.
|
||||
*/
|
||||
abstract public class EditorConfigException extends Exception {
|
||||
EditorConfigException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package org.editorconfig.core;
|
||||
|
||||
/**
|
||||
* Exception throwed by {@link EditorConfig#getProperties(String)} if an
|
||||
* EditorConfig file could not be parsed
|
||||
*/
|
||||
public class ParsingException extends EditorConfigException {
|
||||
|
||||
ParsingException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package org.editorconfig.core;
|
||||
|
||||
|
||||
/**
|
||||
* Exception throwed by {@link EditorConfig#getProperties(String)} if an
|
||||
* invalid file path is specified
|
||||
*/
|
||||
public class PathException extends EditorConfigException {
|
||||
|
||||
PathException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package org.editorconfig.core;
|
||||
|
||||
|
||||
/**
|
||||
* Exception throwed by {@link EditorConfig#EditorConfig()} if an exception
|
||||
* from the internal Python interpreter (Jython) is thrown
|
||||
*/
|
||||
public class PythonException extends EditorConfigException {
|
||||
|
||||
PythonException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package org.editorconfig.core;
|
||||
|
||||
/**
|
||||
* Exception throwed by {@link EditorConfig#getProperties(String)} if an
|
||||
* invalid version number is specified
|
||||
*/
|
||||
public class VersionException extends EditorConfigException {
|
||||
|
||||
VersionException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Provides the Java API for accessing
|
||||
* <a href="http://editorconfig.org">EditorConfig</a> Core
|
||||
* (For the purpose and usage of EditorConfig, see
|
||||
* <a href="http://editorconfig.org">EditorConfig</a> homepage for details).
|
||||
*/
|
||||
|
||||
package org.editorconfig.core;
|
@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
|
||||
from editorconfig.main import main
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -0,0 +1,18 @@
|
||||
from setuptools import setup
|
||||
import editorconfig
|
||||
|
||||
setup(
|
||||
name='EditorConfig',
|
||||
version=editorconfig.__version__,
|
||||
author='EditorConfig Team',
|
||||
packages=['editorconfig'],
|
||||
url='http://editorconfig.org/',
|
||||
license='LICENSE.txt',
|
||||
description='EditorConfig File Locator and Interpreter for Python',
|
||||
long_description=open('README.rst').read(),
|
||||
entry_points = {
|
||||
'console_scripts': [
|
||||
'editorconfig = editorconfig.main:main',
|
||||
]
|
||||
},
|
||||
)
|
@ -0,0 +1,564 @@
|
||||
" Copyright (c) 2011-2012 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
|
||||
if !exists('g:EditorConfig_exec_path')
|
||||
let g:EditorConfig_exec_path = ''
|
||||
endif
|
||||
|
||||
if !exists('g:EditorConfig_python_files_dir')
|
||||
let g:EditorConfig_python_files_dir = 'plugin/editorconfig-core-py'
|
||||
endif
|
||||
|
||||
if !exists('g:EditorConfig_verbose')
|
||||
let g:EditorConfig_verbose = 0
|
||||
endif
|
||||
|
||||
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
|
||||
|
||||
function! s:FindPythonInterp() " {{{1
|
||||
" Find python interp. If found, return python command; if not found, return ''
|
||||
|
||||
if has('unix')
|
||||
let l:searching_list = [
|
||||
\ 'python',
|
||||
\ 'python27',
|
||||
\ 'python26',
|
||||
\ 'python25',
|
||||
\ 'python24',
|
||||
\ '/usr/local/bin/python',
|
||||
\ '/usr/local/bin/python27',
|
||||
\ '/usr/local/bin/python26',
|
||||
\ '/usr/local/bin/python25',
|
||||
\ '/usr/local/bin/python24',
|
||||
\ '/usr/bin/python',
|
||||
\ '/usr/bin/python27',
|
||||
\ '/usr/bin/python26',
|
||||
\ '/usr/bin/python25',
|
||||
\ '/usr/bin/python24']
|
||||
elseif has('win32')
|
||||
let l:searching_list = [
|
||||
\ 'python',
|
||||
\ 'python27',
|
||||
\ 'python26',
|
||||
\ 'python25',
|
||||
\ 'python24',
|
||||
\ 'C:\Python27\python.exe',
|
||||
\ 'C:\Python26\python.exe',
|
||||
\ 'C:\Python25\python.exe',
|
||||
\ 'C:\Python24\python.exe']
|
||||
endif
|
||||
|
||||
for possible_python_interp in l:searching_list
|
||||
if executable(possible_python_interp)
|
||||
return possible_python_interp
|
||||
endif
|
||||
endfor
|
||||
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:FindPythonFiles() " {{{1
|
||||
" Find EditorConfig Core python files
|
||||
|
||||
" On Windows, we still use slash rather than backslash
|
||||
let l:old_shellslash = &shellslash
|
||||
set shellslash
|
||||
|
||||
let l:python_core_files_dir = substitute(
|
||||
\ findfile(g:EditorConfig_python_files_dir . '/main.py',
|
||||
\ ','.&runtimepath), '/main.py$', '', '')
|
||||
|
||||
if empty(l:python_core_files_dir)
|
||||
return ''
|
||||
endif
|
||||
|
||||
" expand python core file path to full path, and remove the appending '/'
|
||||
let l:python_core_files_dir = substitute(
|
||||
\ fnamemodify(l:python_core_files_dir, ':p'), '/$', '', '')
|
||||
|
||||
let &shellslash = l:old_shellslash
|
||||
|
||||
return l:python_core_files_dir
|
||||
endfunction
|
||||
|
||||
" Mode initialization functions {{{1
|
||||
function! s:InitializeExternalCommand() " {{{2
|
||||
" Initialize external_command mode
|
||||
|
||||
let s:EditorConfig_exec_path = ''
|
||||
|
||||
" User has specified an EditorConfig command. Use that one.
|
||||
if exists('g:EditorConfig_exec_path') &&
|
||||
\ !empty(g:EditorConfig_exec_path)
|
||||
if executable(g:EditorConfig_exec_path)
|
||||
let s:EditorConfig_exec_path = g:EditorConfig_exec_path
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
endif
|
||||
endif
|
||||
|
||||
" User does not specify an EditorConfig command. Let's search for it.
|
||||
if has('unix')
|
||||
let l:searching_list = [
|
||||
\ 'editorconfig',
|
||||
\ '/usr/local/bin/editorconfig',
|
||||
\ '/usr/bin/editorconfig',
|
||||
\ '/opt/bin/editorconfig',
|
||||
\ '/opt/editorconfig/bin/editorconfig',
|
||||
\ 'editorconfig.py',
|
||||
\ '/usr/local/bin/editorconfig.py',
|
||||
\ '/usr/bin/editorconfig.py',
|
||||
\ '/opt/bin/editorconfig.py',
|
||||
\ '/opt/editorconfig/bin/editorconfig.py']
|
||||
elseif has('win32')
|
||||
let l:searching_list = [
|
||||
\ 'editorconfig',
|
||||
\ 'C:\editorconfig\bin\editorconfig',
|
||||
\ 'D:\editorconfig\bin\editorconfig',
|
||||
\ 'E:\editorconfig\bin\editorconfig',
|
||||
\ 'F:\editorconfig\bin\editorconfig',
|
||||
\ 'C:\Program Files\editorconfig\bin\editorconfig',
|
||||
\ 'D:\Program Files\editorconfig\bin\editorconfig',
|
||||
\ 'E:\Program Files\editorconfig\bin\editorconfig',
|
||||
\ 'F:\Program Files\editorconfig\bin\editorconfig',
|
||||
\ 'editorconfig.py']
|
||||
endif
|
||||
|
||||
" search for editorconfig core executable
|
||||
for possible_cmd in l:searching_list
|
||||
if executable(possible_cmd)
|
||||
let s:EditorConfig_exec_path = possible_cmd
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
|
||||
if empty(s:EditorConfig_exec_path)
|
||||
return 2
|
||||
endif
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:InitializePythonExternal() " {{{2
|
||||
" Initialize external python. Before calling this function, please make sure
|
||||
" s:FindPythonFiles is called and the return value is set to
|
||||
" s:editorconfig_core_py_dir
|
||||
|
||||
if !exists('s:editorconfig_core_py_dir') ||
|
||||
\ empty(s:editorconfig_core_py_dir)
|
||||
return 2
|
||||
endif
|
||||
|
||||
" Find python interp
|
||||
if !exists('g:editorconfig_python_interp') ||
|
||||
\ empty('g:editorconfig_python_interp')
|
||||
let s:editorconfig_python_interp = s:FindPythonInterp()
|
||||
endif
|
||||
|
||||
if empty(s:editorconfig_python_interp) ||
|
||||
\ !executable(s:editorconfig_python_interp)
|
||||
return 1
|
||||
endif
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:InitializePythonBuiltin(editorconfig_core_py_dir) " {{{2
|
||||
" Initialize builtin python. The parameter is the Python Core directory
|
||||
|
||||
if exists('s:builtin_python_initialized') && s:builtin_python_initialized
|
||||
return 0
|
||||
endif
|
||||
|
||||
let s:builtin_python_initialized = 1
|
||||
|
||||
let l:ret = 0
|
||||
|
||||
if !has('python')
|
||||
return 1
|
||||
endif
|
||||
|
||||
python << EEOOFF
|
||||
|
||||
try:
|
||||
import vim
|
||||
import sys
|
||||
except:
|
||||
vim.command('let l:ret = 2')
|
||||
|
||||
EEOOFF
|
||||
|
||||
if l:ret != 0
|
||||
return l:ret
|
||||
endif
|
||||
|
||||
python << EEOOFF
|
||||
|
||||
try:
|
||||
sys.path.insert(0, vim.eval('a:editorconfig_core_py_dir'))
|
||||
|
||||
import editorconfig
|
||||
import editorconfig.exceptions as editorconfig_except
|
||||
|
||||
except:
|
||||
vim.command('let l:ret = 3')
|
||||
|
||||
del sys.path[0]
|
||||
|
||||
ec_data = {} # used in order to keep clean Python namespace
|
||||
|
||||
EEOOFF
|
||||
|
||||
if l:ret != 0
|
||||
return l:ret
|
||||
endif
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" Do some initalization for the case that the user has specified core mode {{{1
|
||||
if !empty(s:editorconfig_core_mode)
|
||||
|
||||
if s:editorconfig_core_mode == 'external_command'
|
||||
if s:InitializeExternalCommand()
|
||||
echo 'EditorConfig: Failed to initialize external_command mode'
|
||||
finish
|
||||
endif
|
||||
else
|
||||
let s:editorconfig_core_py_dir = s:FindPythonFiles()
|
||||
|
||||
if empty(s:editorconfig_core_py_dir)
|
||||
echo 'EditorConfig: '.
|
||||
\ 'EditorConfig Python Core files could not be found.'
|
||||
finish
|
||||
endif
|
||||
|
||||
if s:editorconfig_core_mode == 'python_builtin' &&
|
||||
\ s:InitializePythonBuiltin(s:editorconfig_core_py_dir)
|
||||
echo 'EditorConfig: Failed to initialize vim built-in python.'
|
||||
finish
|
||||
elseif s:editorconfig_core_mode == 'python_external' &&
|
||||
\ s:InitializePythonExternal()
|
||||
echo 'EditorConfig: Failed to find external Python interpreter.'
|
||||
finish
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
" Determine the editorconfig_core_mode we should use {{{1
|
||||
while 1
|
||||
" If user has specified a mode, just break
|
||||
if exists('s:editorconfig_core_mode') && !empty(s:editorconfig_core_mode)
|
||||
break
|
||||
endif
|
||||
|
||||
" Find Python core files. If not found, we try external_command mode
|
||||
let s:editorconfig_core_py_dir = s:FindPythonFiles()
|
||||
if empty(s:editorconfig_core_py_dir) " python files are not found
|
||||
if !s:InitializeExternalCommand()
|
||||
let s:editorconfig_core_mode = 'external_command'
|
||||
endif
|
||||
break
|
||||
endif
|
||||
|
||||
" Builtin python mode first
|
||||
if !s:InitializePythonBuiltin(s:editorconfig_core_py_dir)
|
||||
let s:editorconfig_core_mode = 'python_builtin'
|
||||
break
|
||||
endif
|
||||
|
||||
" Then external_command mode
|
||||
if !s:InitializeExternalCommand()
|
||||
let s:editorconfig_core_mode = 'external_command'
|
||||
break
|
||||
endif
|
||||
|
||||
" Finally external python mode
|
||||
if !s:InitializePythonExternal()
|
||||
let s:editorconfig_core_mode = 'python_external'
|
||||
break
|
||||
endif
|
||||
|
||||
break
|
||||
endwhile
|
||||
|
||||
" No EditorConfig Core is available
|
||||
if empty(s:editorconfig_core_mode)
|
||||
echo "EditorConfig: ".
|
||||
\ "No EditorConfig Core is available. The plugin won't work."
|
||||
finish
|
||||
endif
|
||||
|
||||
function! s:UseConfigFiles()
|
||||
if s:editorconfig_core_mode == 'external_command'
|
||||
call s:UseConfigFiles_ExternalCommand()
|
||||
elseif s:editorconfig_core_mode == 'python_builtin'
|
||||
call s:UseConfigFiles_Python_Builtin()
|
||||
elseif s:editorconfig_core_mode == 'python_external'
|
||||
call s:UseConfigFiles_Python_External()
|
||||
else
|
||||
echohl Error |
|
||||
\ echo "Unknown EditorConfig Core: " .
|
||||
\ s:editorconfig_core_mode |
|
||||
\ echohl None
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" command, autoload {{{1
|
||||
command! EditorConfigReload call s:UseConfigFiles() " Reload EditorConfig files
|
||||
augroup editorconfig
|
||||
autocmd! editorconfig
|
||||
autocmd editorconfig BufNewFile,BufReadPost * call s:UseConfigFiles()
|
||||
autocmd editorconfig BufNewFile,BufRead .editorconfig set filetype=dosini
|
||||
|
||||
augroup END
|
||||
|
||||
" UseConfigFiles function for different mode {{{1
|
||||
function! s:UseConfigFiles_Python_Builtin() " {{{2
|
||||
" Use built-in python to run the python EditorConfig core
|
||||
|
||||
let l:config = {}
|
||||
let l:ret = 0
|
||||
|
||||
" ignore buffers that do not have a file path associated
|
||||
if empty(expand('%:p'))
|
||||
return 0
|
||||
endif
|
||||
|
||||
python << EEOOFF
|
||||
|
||||
ec_data['filename'] = vim.eval("expand('%:p')")
|
||||
ec_data['conf_file'] = ".editorconfig"
|
||||
|
||||
try:
|
||||
ec_data['options'] = editorconfig.get_properties(ec_data['filename'])
|
||||
except editorconfig_except.EditorConfigError, e:
|
||||
if int(vim.eval('g:EditorConfig_verbose')) != 0:
|
||||
print >> sys.stderr, str(e)
|
||||
vim.command('let l:ret = 1')
|
||||
|
||||
EEOOFF
|
||||
if l:ret != 0
|
||||
return l:ret
|
||||
endif
|
||||
|
||||
python << EEOOFF
|
||||
for key, value in ec_data['options'].items():
|
||||
vim.command("let l:config['" + key.replace("'", "''") + "'] = " +
|
||||
"'" + value.replace("'", "''") + "'")
|
||||
|
||||
EEOOFF
|
||||
|
||||
call s:ApplyConfig(l:config)
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:UseConfigFiles_Python_External() " {{{2
|
||||
" Use external python interp to run the python EditorConfig Core
|
||||
|
||||
let l:cmd = s:editorconfig_python_interp . ' ' .
|
||||
\ s:editorconfig_core_py_dir . '/main.py'
|
||||
|
||||
call s:SpawnExternalParser(l:cmd)
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:UseConfigFiles_ExternalCommand() " {{{2
|
||||
" Use external EditorConfig core (The C core, or editorconfig.py)
|
||||
call s:SpawnExternalParser(s:EditorConfig_exec_path)
|
||||
endfunction
|
||||
|
||||
function! s:SpawnExternalParser(cmd) " {{{2
|
||||
" Spawn external EditorConfig. Used by s:UseConfigFiles_Python_External() and
|
||||
" s:UseConfigFiles_ExternalCommand()
|
||||
|
||||
let l:cmd = a:cmd
|
||||
|
||||
" ignore buffers that do not have a file path associated
|
||||
if empty(expand("%:p"))
|
||||
return
|
||||
endif
|
||||
|
||||
" if editorconfig is present, we use this as our parser
|
||||
if !empty(l:cmd)
|
||||
let l:config = {}
|
||||
|
||||
" 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.
|
||||
let l:old_shellslash = &l:shellslash
|
||||
setlocal noshellslash
|
||||
let l:cmd = l:cmd . ' ' . shellescape(expand('%:p'))
|
||||
let &l:shellslash = l:old_shellslash
|
||||
let l:parsing_result = split(system(l:cmd), '\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
|
||||
|
||||
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)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:ApplyConfig(config) " {{{1
|
||||
" Set the indentation style according to the config values
|
||||
|
||||
if has_key(a:config, "indent_style")
|
||||
if a:config["indent_style"] == "tab"
|
||||
setl noexpandtab
|
||||
elseif a:config["indent_style"] == "space"
|
||||
setl expandtab
|
||||
endif
|
||||
endif
|
||||
if has_key(a:config, "tab_width")
|
||||
let &l:tabstop = str2nr(a:config["tab_width"])
|
||||
endif
|
||||
if has_key(a:config, "indent_size")
|
||||
|
||||
" 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 has_key(a:config, "end_of_line") && &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 has_key(a:config, "charset") && &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
|
||||
|
||||
if has_key(a:config, "trim_trailing_whitespace")
|
||||
augroup editorconfig_trim_trailing_whitespace
|
||||
autocmd! editorconfig_trim_trailing_whitespace
|
||||
if a:config["trim_trailing_whitespace"] == "true"
|
||||
autocmd editorconfig_trim_trailing_whitespace BufWritePre <buffer> :%s/\s\+$//e
|
||||
endif
|
||||
|
||||
augroup END " editorconfig_trim_trailing_whitespace group
|
||||
endif
|
||||
|
||||
if has_key(a:config, 'max_line_length')
|
||||
let l:max_line_length = str2nr(a:config['max_line_length'])
|
||||
|
||||
if l:max_line_length > 0
|
||||
let &l:textwidth = l:max_line_length
|
||||
|
||||
" highlight the column
|
||||
if exists('+colorcolumn')
|
||||
let &l:colorcolumn = l:max_line_length
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
call editorconfig#ApplyHooks(a:config)
|
||||
endfunction
|
||||
|
||||
" }}}
|
||||
|
||||
let &cpo = s:saved_cpo
|
||||
unlet! s:saved_cpo
|
||||
|
||||
" vim: fdm=marker fdc=3
|
@ -0,0 +1,5 @@
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rake', '~> 10.1.0'
|
||||
gem 'rspec', '~> 2.14.1'
|
||||
gem 'vimrunner', '~> 0.3.0'
|
@ -0,0 +1,22 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
diff-lcs (1.2.4)
|
||||
rake (10.1.0)
|
||||
rspec (2.14.1)
|
||||
rspec-core (~> 2.14.0)
|
||||
rspec-expectations (~> 2.14.0)
|
||||
rspec-mocks (~> 2.14.0)
|
||||
rspec-core (2.14.5)
|
||||
rspec-expectations (2.14.2)
|
||||
diff-lcs (>= 1.1.3, < 2.0)
|
||||
rspec-mocks (2.14.3)
|
||||
vimrunner (0.3.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
rake (~> 10.1.0)
|
||||
rspec (~> 2.14.1)
|
||||
vimrunner (~> 0.3.0)
|
@ -0,0 +1,8 @@
|
||||
#
|
||||
# run `rake` to run tests
|
||||
|
||||
require 'rspec/core/rake_task'
|
||||
|
||||
RSpec::Core::RakeTask.new(:spec)
|
||||
|
||||
task :default => :spec
|
@ -0,0 +1,4 @@
|
||||
[*.rb]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = LF
|
@ -0,0 +1,110 @@
|
||||
require 'vimrunner'
|
||||
|
||||
$vim = Vimrunner.start
|
||||
$vim.add_plugin(File.expand_path('../../..', __FILE__), 'plugin/editorconfig.vim')
|
||||
|
||||
# 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(file_name, expected_values)
|
||||
$vim.edit(File.join(BASE_PATH, file_name))
|
||||
|
||||
expected_values.each do |key, val|
|
||||
$vim.echo("&l:#{key}").should == val
|
||||
end
|
||||
|
||||
$vim.command 'bd!'
|
||||
end
|
||||
|
||||
describe 'plugin/editorconfig.vim' do
|
||||
after(:all) do
|
||||
$vim.kill
|
||||
end
|
||||
|
||||
describe '#all' do
|
||||
it '3_space.py' do
|
||||
test_editorconfig '3_space.txt',
|
||||
expandtab: '1',
|
||||
shiftwidth: '3',
|
||||
tabstop: '3'
|
||||
end
|
||||
end
|
||||
|
||||
it '4_space.py' do
|
||||
test_editorconfig '4_space.py',
|
||||
expandtab: '1',
|
||||
shiftwidth: '4',
|
||||
tabstop: '8'
|
||||
end
|
||||
|
||||
it 'space.txt' do
|
||||
test_editorconfig 'space.txt',
|
||||
expandtab: '1',
|
||||
shiftwidth: $vim.echo('&l:tabstop')
|
||||
end
|
||||
|
||||
it 'tab.txt' do
|
||||
test_editorconfig 'tab.txt',
|
||||
expandtab: '0'
|
||||
end
|
||||
|
||||
it '4_tab.txt' do
|
||||
test_editorconfig '4_tab.txt',
|
||||
expandtab: '0',
|
||||
shiftwidth: '4',
|
||||
tabstop: '4'
|
||||
end
|
||||
|
||||
it '4_tab_width_of_8' do
|
||||
test_editorconfig '4_tab_width_of_8.txt',
|
||||
expandtab: '0',
|
||||
shiftwidth: '4',
|
||||
tabstop: '8'
|
||||
end
|
||||
|
||||
it 'lf.txt' do
|
||||
test_editorconfig 'lf.txt',
|
||||
fileformat: 'unix'
|
||||
end
|
||||
|
||||
it 'crlf.txt' do
|
||||
test_editorconfig 'crlf.txt',
|
||||
fileformat: 'dos'
|
||||
end
|
||||
|
||||
it 'cr.txt' do
|
||||
test_editorconfig 'cr.txt',
|
||||
fileformat: 'mac'
|
||||
end
|
||||
|
||||
it 'utf-8.txt' do
|
||||
test_editorconfig 'utf-8.txt',
|
||||
fileencoding: 'utf-8',
|
||||
bomb: '0'
|
||||
end
|
||||
|
||||
it 'utf-8-bom.txt' do
|
||||
test_editorconfig 'utf-8-bom.txt',
|
||||
fileencoding: 'utf-8',
|
||||
bomb: '1'
|
||||
end
|
||||
|
||||
it 'utf-16be.txt' do
|
||||
test_editorconfig 'utf-16be.txt',
|
||||
fileencoding: 'utf-16'
|
||||
end
|
||||
|
||||
it 'utf-16le.txt' do
|
||||
test_editorconfig 'utf-16le.txt',
|
||||
fileencoding: 'utf-16le'
|
||||
end
|
||||
|
||||
it 'latin1.txt' do
|
||||
test_editorconfig 'latin1.txt',
|
||||
fileencoding: 'latin1'
|
||||
end
|
||||
|
||||
# insert_final_newline tests are omitted, since they are not supported
|
||||
end
|
@ -0,0 +1 @@
|
||||
Subproject commit 1d7dab3be211f2addeb3e71caef018d7d151e9ca
|
Loading…
Reference in New Issue