From: martin f. krafft Date: Thu, 14 Oct 2021 02:01:27 +0000 (+1300) Subject: Add '.vim/bundle/vim-python-pep8-indent/' from commit '60ba5e11a61618c0344e2db1902101... X-Git-Url: https://git.madduck.net/etc/vim.git/commitdiff_plain/3f68af9813542a5e277b7a51b316644241c372d7?hp=2de20d9c659d6350a6408dc1ec4aa6e0b1dea6ac Add '.vim/bundle/vim-python-pep8-indent/' from commit '60ba5e11a61618c0344e2db190210145083c91f8' git-subtree-dir: .vim/bundle/vim-python-pep8-indent git-subtree-mainline: 2de20d9c659d6350a6408dc1ec4aa6e0b1dea6ac git-subtree-split: 60ba5e11a61618c0344e2db190210145083c91f8 --- diff --git a/.vim/bundle/vim-python-pep8-indent/.circleci/config.yml b/.vim/bundle/vim-python-pep8-indent/.circleci/config.yml new file mode 100644 index 0000000..8d54439 --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/.circleci/config.yml @@ -0,0 +1,37 @@ +version: 2 + +common: &common + working_directory: ~/repo + docker: + - image: blueyed/vim-python-pep8-indent-vims-for-test:3@sha256:e7e3c4f4b021954a40f2f1d88dc470f119dc65603c63724d1c58cbe437fdc2d4 + +jobs: + test: + <<: *common + steps: + - checkout + - run: + name: Run tests + command: | + spec/make-coverage + - run: + name: Report coverage + command: | + covimerage xml + codecov -X search gcov pycov -f coverage.xml + + checkqa: + <<: *common + steps: + - checkout + - run: + name: Lint + command: | + vint **/*.vim + +workflows: + version: 2 + test: + jobs: + - test + - checkqa diff --git a/.vim/bundle/vim-python-pep8-indent/.coveragerc b/.vim/bundle/vim-python-pep8-indent/.coveragerc new file mode 100644 index 0000000..74cc24e --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/.coveragerc @@ -0,0 +1,7 @@ +[run] +plugins = covimerage +data_file = .coverage_covimerage +source = indent/python.vim + +[report] +include = indent/python.vim diff --git a/.vim/bundle/vim-python-pep8-indent/.dockerignore b/.vim/bundle/vim-python-pep8-indent/.dockerignore new file mode 100644 index 0000000..1a99a79 --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/.dockerignore @@ -0,0 +1,2 @@ +* +!Gemfile diff --git a/.vim/bundle/vim-python-pep8-indent/.gitignore b/.vim/bundle/vim-python-pep8-indent/.gitignore new file mode 100644 index 0000000..e8035f6 --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/.gitignore @@ -0,0 +1,3 @@ +.*.swp +.coverage_covimerage +Gemfile.lock diff --git a/.vim/bundle/vim-python-pep8-indent/CONTRIBUTING.rst b/.vim/bundle/vim-python-pep8-indent/CONTRIBUTING.rst new file mode 100644 index 0000000..094f20a --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/CONTRIBUTING.rst @@ -0,0 +1,37 @@ +How To Contribute +================= + +``vim-python-pep8-indent`` is always open for suggestions and contributions by generous developers. +I’ve collected a few tips to get you started. + +Please: + +- *Always* add tests for your code. +- Write `good commit messages`_. + + +Running Tests +------------- + +- They are written in Ruby_ (sorry :() using vimrunner_ which requires rspec_. +- The tests go into ``spec/indent/indent_spec.rb``. + Look at the ``describe`` blocks to get the hang of it. +- Run the tests with the command:: + + $ rspec spec +- Alternatively you can use Docker:: + + $ make test_docker + +- You can select tests based on line numbers, e.g.:: + + $ rspec ./spec/indent/indent_spec.rb:385 + $ make test_docker RSPEC_ARGS=./spec/indent/indent_spec.rb:385 + +Thank you for considering to contribute! + + +.. _Ruby: https://www.ruby-lang.org/ +.. _`good commit messages`: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html +.. _vimrunner: https://github.com/AndrewRadev/vimrunner +.. _rspec: https://github.com/rspec/rspec diff --git a/.vim/bundle/vim-python-pep8-indent/COPYING.txt b/.vim/bundle/vim-python-pep8-indent/COPYING.txt new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/COPYING.txt @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/.vim/bundle/vim-python-pep8-indent/Dockerfile b/.vim/bundle/vim-python-pep8-indent/Dockerfile new file mode 100644 index 0000000..14e39ea --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/Dockerfile @@ -0,0 +1,24 @@ +FROM testbed/vim:latest + +RUN apk --no-cache add gtk+2.0-dev libx11-dev libxt-dev mcookie xauth xvfb +# NOTE: +profile needs huge features. +RUN install_vim -tag v8.1.0129 -name vim --with-features=huge \ + --disable-channel --disable-netbeans --disable-xim \ + --enable-gui=gtk2 --with-x -build +RUN ln -s /vim-build/bin/vim /usr/bin/gvim +RUN gvim --version + +# Install covimerage and vint. +# NOTE: we have py2 already via gtk+2.0-dev. +# NOTE: enum34+pathlib+typing gets installed as workaround for broken vim-vint wheel. +RUN apk --no-cache add py2-pip \ + && pip install --no-cache-dir codecov covimerage==0.0.9 vim-vint enum34 pathlib typing \ + && rm -rf /usr/include /usr/lib/python*/turtle* /usr/lib/python*/tkinter + +WORKDIR /vim-python-pep8-indent + +ADD Gemfile . +RUN apk --no-cache add coreutils ruby-bundler +RUN bundle install + +ENTRYPOINT ["rspec", "spec"] diff --git a/.vim/bundle/vim-python-pep8-indent/Gemfile b/.vim/bundle/vim-python-pep8-indent/Gemfile new file mode 100644 index 0000000..9bbf596 --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/Gemfile @@ -0,0 +1,3 @@ +source 'https://rubygems.org' +gem "vimrunner", "0.3.4" +gem "rspec" diff --git a/.vim/bundle/vim-python-pep8-indent/Makefile b/.vim/bundle/vim-python-pep8-indent/Makefile new file mode 100644 index 0000000..2566d41 --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/Makefile @@ -0,0 +1,25 @@ +test: + VIMRUNNER_REUSE_SERVER=1 xvfb-run bundle exec rspec + +# Run tests in dockerized Vims. +DOCKER_REPO:=blueyed/vim-python-pep8-indent-vims-for-test +DOCKER_TAG:=3 +DOCKER_IMAGE:=$(DOCKER_REPO):$(DOCKER_TAG) + +docker_image: + docker build -t $(DOCKER_REPO):$(DOCKER_TAG) . +docker_push: + docker push $(DOCKER_REPO):$(DOCKER_TAG) +docker_update_latest: + docker tag $(DOCKER_REPO):$(DOCKER_TAG) $(DOCKER_REPO):latest + docker push $(DOCKER_REPO):latest + +test_docker: XVFB_ERRORFILE:=/dev/null +test_docker: + @set -x; export DISPLAY=$(if $(VIMRUNNER_TEST_DISPLAY),$(VIMRUNNER_TEST_DISPLAY),172.17.0.1:99; Xvfb -ac -listen tcp :99 >$(XVFB_ERRORFILE) 2>&1 & XVFB_PID=$$!); \ + docker run --rm -ti -e DISPLAY -e VIMRUNNER_REUSE_SERVER=1 \ + -v $(CURDIR):/vim-python-pep8-indent $(DOCKER_IMAGE) $(RSPEC_ARGS) \ + $(if $(VIMRUNNER_TEST_DISPLAY),,; ret=$$?; kill $$XVFB_PID; exit $$ret) + +test_coverage: + spec/make-coverage diff --git a/.vim/bundle/vim-python-pep8-indent/README.rst b/.vim/bundle/vim-python-pep8-indent/README.rst new file mode 100644 index 0000000..77be58c --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/README.rst @@ -0,0 +1,169 @@ +vim-python-pep8-indent +====================== + +.. image:: https://circleci.com/gh/Vimjas/vim-python-pep8-indent.svg?style=svg + :target: https://circleci.com/gh/Vimjas/vim-python-pep8-indent +.. image:: https://codecov.io/gh/Vimjas/vim-python-pep8-indent/branch/master/graph/badge.svg + :target: https://codecov.io/gh/Vimjas/vim-python-pep8-indent + +This small script modifies Vim_’s indentation behavior to comply with PEP8_ and my aesthetic preferences. +Most importantly:: + + foobar(foo, + bar) + +and:: + + foobar( + foo, + bar + ) + + +Installation +------------ + +Install the plugin using your favorite plugin manager / method, a few examples +follow: + +Pathogen +^^^^^^^^ + +Follow the instructions on installing Pathogen_ and then: + +.. code-block:: shell-session + + $ cd ~/.vim/bundle + $ git clone https://github.com/Vimjas/vim-python-pep8-indent.git + + +Vundle +^^^^^^ + +Follow the instructions on installing Vundle_ and add the appropriate plugin line into your ``.vimrc``: + +.. code-block:: vim + + Plugin 'Vimjas/vim-python-pep8-indent' + + +NeoBundle +^^^^^^^^^ + +Follow the instructions on installing NeoBundle_ and add the appropriate NeoBundle line into your ``.vimrc``: + +.. code-block:: vim + + NeoBundle 'Vimjas/vim-python-pep8-indent' + + +Configuration +------------- + +g:python_pep8_indent_multiline_string +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can configure the initial indentation of multiline strings using ``g:python_pep8_indent_multiline_string`` (which can also be set per buffer). +This defaults to ``0``, which means that multiline strings are not indented. +``-1`` and positive values will be used as-is, where ``-1`` is a special value for Vim's ``indentexpr``, and will keep the existing indent (using Vim's ``autoindent`` setting). +``-2`` is meant to be used for strings that are wrapped with ``textwrap.dedent`` etc. It will add a level of indentation if the multiline string started in the previous line, without any content in it already:: + + testdir.makeconftest(""" + _ + +With content already, it will be aligned to the opening parenthesis:: + + testdir.makeconftest("""def pytest_addoption(parser): + _ + +Existing indentation (including ``0``) in multiline strings will be kept, so this setting only applies to the indentation of new/empty lines. + +g:python_pep8_indent_hang_closing +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Control closing bracket indentation with ``python_pep8_indent_hang_closing``, set globally or per buffer. + +By default (set to ``0``), closing brackets line up with the opening line:: + + my_list = [ + 1, 2, 3, + 4, 5, 6, + ] + result = some_function_that_takes_arguments( + 'a', 'b', 'c', + 'd', 'e', 'f', + ) + +With ``python_pep8_indent_hang_closing = 1``, closing brackets line up with the items:: + + my_list = [ + 1, 2, 3, + 4, 5, 6, + ] + result = some_function_that_takes_arguments( + 'a', 'b', 'c', + 'd', 'e', 'f', + ) + + +Troubleshooting +--------------- + +In case it is not working, please make sure your Vim is configured to load +indent files (``filetype indent on``). +This is typically the case when using a plugin manager, but check its docs. + +Check ``:verbose set indentexpr?`` in a Python file, which should show +something like the following: + + indentexpr=GetPythonPEPIndent(v:lnum) + Last set from ~/…/plugged/vim-python-pep8-indent/indent/python.vim + + +Notes +----- + +Please note that Kirill Klenov’s python-mode_ ships its own version of this bundle. +Therefore, if you want to use this version specifically, you’ll have to disable python-mode’s using: + +.. code-block:: vim + + let g:pymode_indent = 0 + + +License and Authorship +---------------------- + +This script is based on one from Vim’s official `script repo`_ that was *not* originally written by me. +Unfortunately the indentation was off by one character in one case and the script hasn’t been updated since 2005. + +Even more unfortunately, I wasn’t able to reach any of the original authors/maintainers: +**David Bustos** and **Eric Mc Sween**. + +So I fixed the annoyance with the help of `Steve Losh`_ and am putting it out here so you don’t have to patch the original yourself. +The original patch is still available here_. + +Over the time a lot more improvements have been contributed_ by `generous people`_. + +I’d like to thank the original authors here for their work and release it hereby to the *Public Domain* (using the CC0_ licence) since I hope that would be in their spirit. +If anyone with a say in this objects, please let me_ know immediately. +Also, if someone is in contact with one of them, I would appreciate being introduced. + +While my Vimscript_ skills are still feeble, I intend to maintain it for now. +This mainly means that I’ll triage through bugs and pull requests but won’t be fixing much myself. + + +.. _Vim: http://www.vim.org/ +.. _PEP8: http://www.python.org/dev/peps/pep-0008/ +.. _`script repo`: http://www.vim.org/scripts/script.php?script_id=974 +.. _`Steve Losh`: http://stevelosh.com/ +.. _here: https://gist.github.com/2965846 +.. _Neobundle: https://github.com/Shougo/neobundle.vim +.. _Pathogen: https://github.com/tpope/vim-pathogen +.. _python-mode: https://github.com/klen/python-mode +.. _`Vimscript`: http://learnvimscriptthehardway.stevelosh.com/ +.. _vundle: https://github.com/gmarik/Vundle.vim +.. _me: https://hynek.me/ +.. _CC0: http://creativecommons.org/publicdomain/zero/1.0/ +.. _contributed: https://github.com/hynek/vim-python-pep8-indent/blob/master/CONTRIBUTING.rst +.. _`generous people`: https://github.com/hynek/vim-python-pep8-indent/graphs/contributors diff --git a/.vim/bundle/vim-python-pep8-indent/docker-compose.yml b/.vim/bundle/vim-python-pep8-indent/docker-compose.yml new file mode 100644 index 0000000..71760c2 --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/docker-compose.yml @@ -0,0 +1,6 @@ +version: '2' +services: + rspec: + build: . + volumes: + - .:/vim-python-pep8-indent diff --git a/.vim/bundle/vim-python-pep8-indent/indent/cython.vim b/.vim/bundle/vim-python-pep8-indent/indent/cython.vim new file mode 120000 index 0000000..4407bc1 --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/indent/cython.vim @@ -0,0 +1 @@ +python.vim \ No newline at end of file diff --git a/.vim/bundle/vim-python-pep8-indent/indent/python.vim b/.vim/bundle/vim-python-pep8-indent/indent/python.vim new file mode 100644 index 0000000..047ae3d --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/indent/python.vim @@ -0,0 +1,454 @@ +" PEP8 compatible Python indent file +" Language: Python +" Maintainer: Daniel Hahler +" Prev Maintainer: Hynek Schlawack +" Prev Maintainer: Eric Mc Sween (address invalid) +" Original Author: David Bustos (address invalid) +" License: CC0 +" +" vim-python-pep8-indent - A nicer Python indentation style for vim. +" Written in 2004 by David Bustos +" Maintained from 2004-2005 by Eric Mc Sween +" Maintained from 2013 by Hynek Schlawack +" Maintained from 2017 by Daniel Hahler +" +" To the extent possible under law, the author(s) have dedicated all copyright +" and related and neighboring rights to this software to the public domain +" worldwide. This software is distributed without any warranty. +" You should have received a copy of the CC0 Public Domain Dedication along +" with this software. If not, see +" . + +" Only load this indent file when no other was loaded. +if exists('b:did_indent') + finish +endif +let b:did_indent = 1 + +setlocal nolisp +setlocal autoindent +setlocal indentexpr=GetPythonPEPIndent(v:lnum) +setlocal indentkeys=!^F,o,O,<:>,0),0],0},=elif,=except + +if !exists('g:python_pep8_indent_multiline_string') + let g:python_pep8_indent_multiline_string = 0 +endif + +if !exists('g:python_pep8_indent_hang_closing') + let g:python_pep8_indent_hang_closing = 0 +endif + +" TODO: check required patch for timeout argument, likely lower than 7.3.429 though. +if !exists('g:python_pep8_indent_searchpair_timeout') + if has('patch-8.0.1483') + let g:python_pep8_indent_searchpair_timeout = 150 + else + let g:python_pep8_indent_searchpair_timeout = 0 + endif +endif + +let s:block_rules = { + \ '^\s*elif\>': [['if', 'elif'], ['else']], + \ '^\s*except\>': [['try', 'except'], []], + \ '^\s*finally\>': [['try', 'except', 'else'], []] + \ } +let s:block_rules_multiple = { + \ '^\s*else\>': [['if', 'elif', 'for', 'try', 'except'], []] + \ } +" Pairs to look for when searching for opening parenthesis. +" The value is the maximum offset in lines. +let s:paren_pairs = {'()': 50, '[]': 100, '{}': 1000} + +if &filetype ==# 'pyrex' || &filetype ==# 'cython' + let b:control_statement = '\v^\s*(class|def|if|while|with|for|except|cdef|cpdef)>' +else + let b:control_statement = '\v^\s*(class|def|if|while|with|for|except)>' +endif +let s:stop_statement = '^\s*\(break\|continue\|raise\|return\|pass\)\>' + +let s:skip_after_opening_paren = 'synIDattr(synID(line("."), col("."), 0), "name") ' . + \ '=~? "\\vcomment|jedi\\S"' + +let s:special_chars_syn_pattern = "\\vstring|comment|^pythonbytes%(contents)=$|pythonTodo|jedi\\S" + +if !get(g:, 'python_pep8_indent_skip_concealed', 0) || !has('conceal') + " Skip strings and comments. Return 1 for chars to skip. + " jedi* refers to syntax definitions from jedi-vim for call signatures, which + " are inserted temporarily into the buffer. + function! s:_skip_special_chars(line, col) + return synIDattr(synID(a:line, a:col, 0), 'name') + \ =~? s:special_chars_syn_pattern + endfunction +else + " Also ignore anything concealed. + " TODO: doc; likely only necessary with jedi-vim, where a better version is + " planned (https://github.com/Vimjas/vim-python-pep8-indent/pull/98). + + " Wrapper around synconcealed for older Vim (7.3.429, used on Travis CI). + function! s:is_concealed(line, col) + let concealed = synconcealed(a:line, a:col) + return len(concealed) && concealed[0] + endfunction + + function! s:_skip_special_chars(line, col) + return synIDattr(synID(a:line, a:col, 0), 'name') + \ =~? s:special_chars_syn_pattern + \ || s:is_concealed(a:line, a:col) + endfunction +endif + +" Use 'shiftwidth()' instead of '&sw'. +" (Since Vim patch 7.3.629, 'shiftwidth' can be set to 0 to follow 'tabstop'). +if exists('*shiftwidth') + function! s:sw() + return shiftwidth() + endfunction +else + function! s:sw() + return &shiftwidth + endfunction +endif + +" Find backwards the closest open parenthesis/bracket/brace. +function! s:find_opening_paren(lnum, col) + " Return if cursor is in a comment. + if synIDattr(synID(a:lnum, a:col, 0), 'name') =~? 'comment' + return [0, 0] + endif + + call cursor(a:lnum, a:col) + + let nearest = [0, 0] + let timeout = g:python_pep8_indent_searchpair_timeout + let skip_special_chars = 's:_skip_special_chars(line("."), col("."))' + for [p, maxoff] in items(s:paren_pairs) + let stopline = max([0, line('.') - maxoff, nearest[0]]) + let next = searchpairpos( + \ '\V'.p[0], '', '\V'.p[1], 'bnW', skip_special_chars, stopline, timeout) + if next[0] && (next[0] > nearest[0] || (next[0] == nearest[0] && next[1] > nearest[1])) + let nearest = next + endif + endfor + return nearest +endfunction + +" Find the start of a multi-line statement +function! s:find_start_of_multiline_statement(lnum) + let lnum = a:lnum + while lnum > 0 + if getline(lnum - 1) =~# '\\$' + let lnum = prevnonblank(lnum - 1) + else + let [paren_lnum, _] = s:find_opening_paren(lnum, 1) + if paren_lnum < 1 + return lnum + else + let lnum = paren_lnum + endif + endif + endwhile +endfunction + +" Find possible indent(s) of the block starter that matches the current line. +function! s:find_start_of_block(lnum, types, skip, multiple) abort + let r = [] + let re = '\V\^\s\*\('.join(a:types, '\|').'\)\>' + if !empty(a:skip) + let re_skip = '\V\^\s\*\('.join(a:skip, '\|').'\)\>' + else + let re_skip = '' + endif + let last_indent = indent(a:lnum) + 1 + let lnum = a:lnum - 1 + while lnum > 0 && last_indent > 0 + let indent = indent(lnum) + if indent < last_indent + let line = getline(lnum) + if !empty(re_skip) && line =~# re_skip + let last_indent = indent + elseif line =~# re + if !a:multiple + return [indent] + endif + if index(r, indent) == -1 + let r += [indent] + endif + let last_indent = indent + endif + endif + let lnum = prevnonblank(lnum - 1) + endwhile + return r +endfunction + +" Is "expr" true for every position in "lnum", beginning at "start"? +" (optionally up to a:1 / 4th argument) +function! s:match_expr_on_line(expr, lnum, start, ...) + let text = getline(a:lnum) + let end = a:0 ? a:1 : len(text) + if a:start > end + return 1 + endif + let save_pos = getpos('.') + let r = 1 + for i in range(a:start, end) + call cursor(a:lnum, i) + if !(eval(a:expr) || text[i-1] =~# '\s') + let r = 0 + break + endif + endfor + call setpos('.', save_pos) + return r +endfunction + +" Line up with open parenthesis/bracket/brace. +function! s:indent_like_opening_paren(lnum) + let [paren_lnum, paren_col] = s:find_opening_paren(a:lnum, 1) + if paren_lnum <= 0 + return -2 + endif + let text = getline(paren_lnum) + let base = indent(paren_lnum) + + let nothing_after_opening_paren = s:match_expr_on_line( + \ s:skip_after_opening_paren, paren_lnum, paren_col+1) + let starts_with_closing_paren = getline(a:lnum) =~# '^\s*[])}]' + + let hang_closing = get(b:, 'python_pep8_indent_hang_closing', + \ get(g:, 'python_pep8_indent_hang_closing', 0)) + + if nothing_after_opening_paren + if starts_with_closing_paren && !hang_closing + let res = base + else + let res = base + s:sw() + + " Special case for parenthesis. + if text[paren_col-1] ==# '(' && getline(a:lnum) !~# '\v\)\s*:?\s*$' + return res + endif + endif + else + " Indent to match position of opening paren. + let res = paren_col + endif + + " If this line is the continuation of a control statement + " indent further to distinguish the continuation line + " from the next logical line. + if text =~# b:control_statement && res == base + s:sw() + " But only if not inside parens itself (Flake's E127). + let [paren_lnum, _] = s:find_opening_paren(paren_lnum, 1) + if paren_lnum <= 0 + return res + s:sw() + endif + endif + return res +endfunction + +" Match indent of first block of this type. +function! s:indent_like_block(lnum) + let text = getline(a:lnum) + for [multiple, block_rules] in [ + \ [0, s:block_rules], + \ [1, s:block_rules_multiple], + \ ] + for [line_re, blocks_ignore] in items(block_rules) + if text !~# line_re + continue + endif + + let [blocks, skip] = blocks_ignore + let indents = s:find_start_of_block(a:lnum, blocks, skip, multiple) + if empty(indents) + return -1 + endif + if len(indents) == 1 + return indents[0] + endif + + " Multiple valid indents, e.g. for 'else' with both try and if. + let indent = indent(a:lnum) + if index(indents, indent) != -1 + " The indent is valid, keep it. + return indent + endif + " Fallback to the first/nearest one. + return indents[0] + endfor + endfor + return -2 +endfunction + +function! s:indent_like_previous_line(lnum) + let lnum = prevnonblank(a:lnum - 1) + + " No previous line, keep current indent. + if lnum < 1 + return -1 + endif + + let text = getline(lnum) + let start = s:find_start_of_multiline_statement(lnum) + let base = indent(start) + let current = indent(a:lnum) + + " Ignore last character in previous line? + let lastcol = len(text) + let col = lastcol + + " Search for final colon that is not inside something to be ignored. + while 1 + if col == 1 | break | endif + if text[col-1] =~# '\s' || s:_skip_special_chars(lnum, col) + let col = col - 1 + continue + elseif text[col-1] ==# ':' + return base + s:sw() + endif + break + endwhile + + if text =~# '\\$' && !s:_skip_special_chars(lnum, lastcol) + " If this line is the continuation of a control statement + " indent further to distinguish the continuation line + " from the next logical line. + if getline(start) =~# b:control_statement + return base + s:sw() * 2 + endif + + " Nest (other) explicit continuations only one level deeper. + return base + s:sw() + endif + + let empty = getline(a:lnum) =~# '^\s*$' + + " Current and prev line are empty, next is not -> indent like next. + if empty && a:lnum > 1 && + \ (getline(a:lnum - 1) =~# '^\s*$') && + \ !(getline(a:lnum + 1) =~# '^\s*$') + return indent(a:lnum + 1) + endif + + " If the previous statement was a stop-execution statement or a pass + if getline(start) =~# s:stop_statement + " Remove one level of indentation if the user hasn't already dedented + if empty || current > base - s:sw() + return base - s:sw() + endif + " Otherwise, trust the user + return -1 + endif + + if (current || !empty) && s:is_dedented_already(current, base) + return -1 + endif + + " In all other cases, line up with the start of the previous statement. + return base +endfunction + +" If this line is dedented and the number of indent spaces is valid +" (multiple of the indentation size), trust the user. +function! s:is_dedented_already(current, base) + let dedent_size = a:current - a:base + return (dedent_size < 0 && a:current % s:sw() == 0) ? 1 : 0 +endfunction + +" Is the syntax at lnum (and optionally cnum) a python string? +function! s:is_python_string(lnum, ...) + let line = getline(a:lnum) + if a:0 + let cols = type(a:1) != type([]) ? [a:1] : a:1 + else + let cols = range(1, max([1, len(line)])) + endif + for cnum in cols + if match(map(synstack(a:lnum, cnum), + \ "synIDattr(v:val, 'name')"), 'python\S*String') == -1 + return 0 + end + endfor + return 1 +endfunction + +function! GetPythonPEPIndent(lnum) + " First line has indent 0 + if a:lnum == 1 + return 0 + endif + + let line = getline(a:lnum) + let prevline = getline(a:lnum-1) + + " Multilinestrings: continous, docstring or starting. + if s:is_python_string(a:lnum-1, max([1, len(prevline)])) + \ && (s:is_python_string(a:lnum, 1) + \ || match(line, '^\%("""\|''''''\)') != -1) + + " Indent closing quotes as the line with the opening ones. + let match_quotes = match(line, '^\s*\zs\%("""\|''''''\)') + if match_quotes != -1 + " closing multiline string + let quotes = line[match_quotes:(match_quotes+2)] + call cursor(a:lnum, 1) + let pairpos = searchpairpos(quotes, '', quotes, 'bW', '', 0, g:python_pep8_indent_searchpair_timeout) + if pairpos[0] != 0 + return indent(pairpos[0]) + else + return -1 + endif + endif + + if s:is_python_string(a:lnum-1) + " Previous line is (completely) a string: keep current indent. + return -1 + endif + + if match(prevline, '^\s*\%("""\|''''''\)') != -1 + " docstring. + return indent(a:lnum-1) + endif + + let indent_multi = get(b:, 'python_pep8_indent_multiline_string', + \ get(g:, 'python_pep8_indent_multiline_string', 0)) + if match(prevline, '\v%("""|'''''')$') != -1 + " Opening multiline string, started in previous line. + if (&autoindent && indent(a:lnum) == indent(a:lnum-1)) + \ || match(line, '\v^\s+$') != -1 + " with empty line or to split up 'foo("""bar' into + " 'foo("""' and 'bar'. + if indent_multi == -2 + return indent(a:lnum-1) + s:sw() + endif + return indent_multi + endif + endif + + " Keep existing indent. + if match(line, '\v^\s*\S') != -1 + return -1 + endif + + if indent_multi != -2 + return indent_multi + endif + + return s:indent_like_opening_paren(a:lnum) + endif + + " Parens: If we can find an open parenthesis/bracket/brace, line up with it. + let indent = s:indent_like_opening_paren(a:lnum) + if indent >= -1 + return indent + endif + + " Blocks: Match indent of first block of this type. + let indent = s:indent_like_block(a:lnum) + if indent >= -1 + return indent + endif + + return s:indent_like_previous_line(a:lnum) +endfunction diff --git a/.vim/bundle/vim-python-pep8-indent/spec/indent/bytes_spec.rb b/.vim/bundle/vim-python-pep8-indent/spec/indent/bytes_spec.rb new file mode 100644 index 0000000..3d6744e --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/spec/indent/bytes_spec.rb @@ -0,0 +1,36 @@ +require "spec_helper" + +describe "handles byte strings" do + before(:all) { + vim.command 'syn region pythonBytes start=+[bB]"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonBytesError,pythonBytesContent,@Spell' + vim.command "syn match pythonBytesEscape '\\\\$'" + } + + before(:each) { + # clear buffer + vim.normal 'gg"_dG' + + # Insert two blank lines. + # The first line is a corner case in this plugin that would shadow the + # correct behaviour of other tests. Thus we explicitly jump to the first + # line when we require so. + vim.feedkeys 'i\\\' + } + + it "it does not indent to bracket in byte string" do + vim.feedkeys 'ireg = b"["\' + vim.echo('map(synstack(line("."), col(".")), "synIDattr(v:val, \"name\")")' + ).should == "['pythonBytes']" + vim.feedkeys 'o' + indent.should == 0 + end + + it "it indents backslash continuation correctly" do + vim.feedkeys 'iwith foo, \\' + vim.echo('getline(".")').should == "with foo, \\" + vim.echo('map(synstack(line("."), col(".")), "synIDattr(v:val, \"name\")")' + ).should == "['pythonBytesEscape']" + vim.feedkeys 'o' + indent.should == 8 + end +end diff --git a/.vim/bundle/vim-python-pep8-indent/spec/indent/cython_spec.rb b/.vim/bundle/vim-python-pep8-indent/spec/indent/cython_spec.rb new file mode 100644 index 0000000..03dcbb2 --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/spec/indent/cython_spec.rb @@ -0,0 +1,36 @@ +require "spec_helper" + +describe "vim for cython" do + before(:all) { + vim.command "new" + vim.command "set ft=cython" + vim.command("set indentexpr?").should include "GetPythonPEPIndent(" + } + before(:each) { + # clear buffer + vim.normal 'gg"_dG' + + # Insert two blank lines. + # The first line is a corner case in this plugin that would shadow the + # correct behaviour of other tests. Thus we explicitly jump to the first + # line when we require so. + vim.feedkeys 'i\\\' + } + after(:all) { + vim.command "bwipe!" + } + + describe "when using a cdef function definition" do + it "indents shiftwidth spaces" do + vim.feedkeys 'icdef long_function_name(\arg' + indent.should == shiftwidth + end + end + + describe "when using a cpdef function definition" do + it "indents shiftwidth spaces" do + vim.feedkeys 'icpdef long_function_name(\arg' + indent.should == shiftwidth + end + end +end diff --git a/.vim/bundle/vim-python-pep8-indent/spec/indent/indent_spec.rb b/.vim/bundle/vim-python-pep8-indent/spec/indent/indent_spec.rb new file mode 100644 index 0000000..745e939 --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/spec/indent/indent_spec.rb @@ -0,0 +1,796 @@ +require "spec_helper" + +shared_examples_for "vim" do + before(:each) { + # clear buffer + vim.normal 'gg"_dG' + + # Insert two blank lines. + # The first line is a corner case in this plugin that would shadow the + # correct behaviour of other tests. Thus we explicitly jump to the first + # line when we require so. + vim.feedkeys 'i\\\' + } + + describe "when using the indent plugin" do + it "sets the indentexpr and indentkeys options" do + vim.command("set indentexpr?").should include "GetPythonPEPIndent(" + vim.command("set indentkeys?").should include "=elif" + end + + it "sets autoindent and expandtab" do + vim.command("set autoindent?").should match(/\s*autoindent/) + vim.command("set expandtab?").should match(/\s*expandtab/) + end + end + + describe "when entering the first line" do + before { vim.feedkeys '0ggipass' } + + it "does not indent" do + indent.should == 0 + proposed_indent.should == 0 + end + + it "does not indent when using '=='" do + vim.normal "==" + indent.should == 0 + end + end + + describe "when after a '(' that is at the end of its line" do + before { vim.feedkeys 'itest(\' } + + it "indents by one level" do + proposed_indent.should == shiftwidth + vim.feedkeys 'something' + indent.should == shiftwidth + vim.normal '==' + indent.should == shiftwidth + end + + it "puts the closing parenthesis at the same level" do + vim.feedkeys ')' + indent.should == (hang_closing ? shiftwidth : 0) + end + end + + describe "when after an '(' that is followed by something" do + before { vim.feedkeys 'itest(something,\' } + + it "lines up on following lines" do + indent.should == 5 + vim.feedkeys 'more,\' + indent.should == 5 + end + + it "lines up the closing parenthesis" do + vim.feedkeys ')' + indent.should == 5 + end + + it "does not touch the closing parenthesis if it is already indented further" do + vim.feedkeys ' )' + indent.should == 7 + end + end + + describe "when after an '{' that is followed by a comment" do + before { vim.feedkeys 'imydict = { # comment\' } + + it "indent by one level" do + indent.should == shiftwidth + vim.feedkeys '1: 1,\' + indent.should == shiftwidth + end + + it "lines up the closing parenthesis" do + vim.feedkeys '}' + indent.should == (hang_closing ? shiftwidth : 0) + end + end + + describe "when using gq to reindent a '(' that is" do + before { vim.feedkeys 'itest(' } + it "something and has a string without spaces at the end" do + vim.feedkeys 'something_very_long_blaaaaaaaaa, "some_very_long_string_blaaaaaaaaaaaaaaaaaaaa"\gqq' + indent.should == 5 + end + end + + describe "when after multiple parens of different types" do + it "indents by one level" do + vim.feedkeys 'if({\' + indent.should == shiftwidth + end + + it "lines up with the last paren" do + vim.feedkeys 'ifff({123: 456,\' + indent.should == 5 + end + end + + describe "when '#' is contained in a string that is followed by a colon" do + it "indents by one level" do + vim.feedkeys 'iif "some#thing" == "test":#test\pass' + indent.should == shiftwidth + end + end + + describe "when '#' is not contained in a string and is followed by a colon" do + it "does not indent" do + vim.feedkeys 'iif "some#thing" == "test"#:test\' + indent.should == 0 + end + end + + describe "when inside an unfinished string" do + it "does not indent" do + vim.feedkeys 'i"test:\' + vim.echo('synIDattr(synID(line("."), col("."), 0), "name")' + ).downcase.should include 'string' + vim.feedkeys 'a\' + proposed_indent.should == -1 + indent.should == 0 + end + + it "does not dedent" do + vim.feedkeys 'iif True:\"test:\' + vim.echo('synIDattr(synID(line("."), col("."), 0), "name")' + ).downcase.should include 'string' + proposed_indent.should == shiftwidth + indent.should == shiftwidth + end + end + + describe "when the previous line has a colon in a string" do + before { vim.feedkeys 'itest(":".join(["1","2"]))\' } + it "does not indent" do + vim.feedkeys 'if True:' + indent.should == 0 + proposed_indent.should == 0 + end + end + + describe "when the previous line has a list slice" do + it "does not indent" do + vim.feedkeys 'ib = a[2:]\' + indent.should == 0 + proposed_indent.should == 0 + end + end + + describe "when line is empty inside a block" do + it "is indented like the previous line" do + vim.feedkeys 'idef a():\1\\2\kcc' + indent.should == shiftwidth + end + end + + describe "when an empty line is after empty line / before non-empty" do + it "is indented like the next line" do + vim.feedkeys 'idef a():\1\\\2\<1\\\\0i\2\kcc' + indent.should == shiftwidth + end + end + + describe "when line is empty inside a block following multi-line statement" do + it "is indented like the previous line" do + vim.feedkeys 'idef a():\x = (1 +\2)\\y\kcc' + indent.should == shiftwidth + end + end + + describe "when line is empty inside a block following stop statement" do + it "is indented like the previous line minus shiftwidth" do + vim.feedkeys 'iif x:\if y:\pass\\z\kcc' + indent.should == shiftwidth + end + end + + describe "when using simple control structures" do + it "indents shiftwidth spaces" do + vim.feedkeys 'iwhile True:\pass' + indent.should == shiftwidth + end + end + + describe "when using a function definition" do + it "handles indent with closing parenthesis on same line" do + vim.feedkeys 'idef long_function_name(\arg' + indent.should == shiftwidth + vim.feedkeys '):' + indent.should == shiftwidth * 2 + end + + it "handles indent with closing parenthesis on new line" do + vim.feedkeys 'idef long_function_name(\arg' + indent.should == shiftwidth + vim.feedkeys '\' + indent.should == shiftwidth + vim.feedkeys ')' + indent.should == (hang_closing ? shiftwidth * 2 : 0) + vim.feedkeys ':' + indent.should == (hang_closing ? shiftwidth * 2 : 0) + vim.feedkeys '\k' + indent.should == shiftwidth + end + end + + describe "when using a class definition" do + it "indents shiftwidth spaces" do + vim.feedkeys 'iclass Foo(\' + indent.should == shiftwidth + end + end + + describe "when writing an 'else' block" do + it "aligns to the preceeding 'for' block" do + vim.feedkeys 'ifor x in "abc":\pass\else:' + indent.should == 0 + end + + it "aligns to the preceeding 'if' block" do + vim.feedkeys 'ifor x in "abc":\if True:\pass\else:' + indent.should == shiftwidth + end + end + + describe "when using parens and control statements" do + it "avoids ambiguity by using extra indentation" do + vim.feedkeys 'iif (111 and\' + if shiftwidth == 4 + indent.should == shiftwidth * 2 + else + indent.should == 4 + end + vim.feedkeys '222):\' + indent.should == shiftwidth + vim.feedkeys 'pass\' + indent.should == 0 + end + + it "still aligns parens properly if not ambiguous" do + vim.feedkeys 'iwhile (111 and\' + indent.should == 7 + vim.feedkeys '222):\' + indent.should == shiftwidth + vim.feedkeys 'pass\' + indent.should == 0 + end + + it "handles nested expressions (Flake8's E127)" do + vim.feedkeys 'i[\x for x in foo\if (\' + indent.should == shiftwidth * 2 + end + + it "still handles multiple parens correctly" do + vim.feedkeys 'iif (111 and (222 and 333\' + indent.should == 13 + vim.feedkeys 'and 444\' + indent.should == 13 + vim.feedkeys ')\' + if shiftwidth == 4 + indent.should == shiftwidth * 2 + else + indent.should == 4 + end + vim.feedkeys 'and 555):\' + indent.should == shiftwidth + vim.feedkeys 'pass\' + indent.should == 0 + end + end + + describe "when a line breaks with a manual '\\'" do + it "indents shiftwidth spaces on normal line" do + vim.feedkeys 'ivalue = test + \\\\\' + indent.should == shiftwidth + end + + it "indents 2x shiftwidth spaces for control structures" do + vim.feedkeys 'iif somevalue == xyz and \\\\\' + indent.should == shiftwidth * 2 + end + + it "indents relative to line above" do + vim.feedkeys 'i\value = test + \\\\\' + indent.should == shiftwidth * 2 + end + end + + describe "when current line is dedented compared to previous line" do + before { vim.feedkeys 'i\\if x:\y = True\\' } + it "and current line has a valid indentation (Part 1)" do + vim.feedkeys '0i\if y:' + proposed_indent.should == -1 + end + + it "and current line has a valid indentation (Part 2)" do + vim.feedkeys '0i\\if y:' + proposed_indent.should == -1 + end + + it "and current line has an invalid indentation" do + vim.feedkeys 'i while True:\' + indent.should == previous_indent + shiftwidth + end + end + + describe "when current line is dedented compared to the last non-empty line" do + before { vim.feedkeys 'i\\if x:\y = True\\\' } + it "and current line has a valid indentation" do + vim.feedkeys '0i\if y:' + proposed_indent.should == -1 + end + end + + describe "when an 'if' is followed by" do + before { vim.feedkeys 'i\\if x:\' } + it "an elif, it lines up with the 'if'" do + vim.feedkeys 'elif y:' + indent.should == shiftwidth * 2 + end + + it "an 'else', it lines up with the 'if'" do + vim.feedkeys 'else:' + indent.should == shiftwidth * 2 + end + end + + describe "when an 'if' contains a try-except" do + before { + vim.feedkeys 'iif x:\try:\pass\except:\pass\' + indent.should == shiftwidth + } + it "an 'else' should be indented to the try" do + vim.feedkeys 'else:' + indent.should == shiftwidth + proposed_indent.should == shiftwidth + end + it "an 'else' should keep the indent of the 'if'" do + vim.feedkeys 'else:\<<' + indent.should == 0 + proposed_indent.should == 0 + end + end + + describe "when a 'for' is followed by" do + before { vim.feedkeys 'i\\for x in y:\' } + it "an 'else', it lines up with the 'for'" do + vim.feedkeys 'else:' + indent.should == shiftwidth * 2 + end + end + + describe "when an 'else' is followed by" do + before { vim.feedkeys 'i\\else:\XXX\' } + it "a 'finally', it lines up with the 'else'" do + vim.feedkeys 'finally:' + indent.should == shiftwidth * 2 + end + end + + + describe "when a 'try' is followed by" do + before { vim.feedkeys 'i\\try:\' } + it "an 'except', it lines up with the 'try'" do + vim.feedkeys 'except:' + indent.should == shiftwidth * 2 + end + + it "an 'else', it lines up with the 'try'" do + vim.feedkeys 'else:' + indent.should == shiftwidth * 2 + end + + it "a 'finally', it lines up with the 'try'" do + vim.feedkeys 'finally:' + indent.should == shiftwidth * 2 + end + end + + describe "when an 'except' is followed by" do + before { vim.feedkeys 'i\\except:\' } + it "an 'else', it lines up with the 'except'" do + vim.feedkeys 'else:' + indent.should == shiftwidth * 2 + end + + it "another 'except', it lines up with the previous 'except'" do + vim.feedkeys 'except:' + indent.should == shiftwidth * 2 + end + + it "a 'finally', it lines up with the 'except'" do + vim.feedkeys 'finally:' + indent.should == shiftwidth * 2 + end + end + + describe "when an else is used inside of a nested if" do + before { vim.feedkeys 'iif foo:\if bar:\pass\' } + it "indents the else to the inner if" do + vim.feedkeys 'else:' + indent.should == shiftwidth + end + end + + describe "when an else is used outside of a nested if" do + before { vim.feedkeys 'iif True:\if True:\pass\\0' } + it "indents the else to the outer if" do + indent.should == 0 + proposed_indent.should == shiftwidth + + vim.feedkeys 'ielse:' + indent.should == 0 + proposed_indent.should == 0 + end + end + + describe "when jedi-vim call signatures are used" do + before { vim.command 'syn match jediFunction "JEDI_CALL_SIGNATURE" keepend extend' } + + it "ignores the call signature after a colon" do + vim.feedkeys 'iif True: JEDI_CALL_SIGNATURE\' + indent.should == shiftwidth + end + + it "ignores the call signature after a function" do + vim.feedkeys 'idef f( JEDI_CALL_SIGNATURE\' + indent.should == shiftwidth + end + end +end + +shared_examples_for "multiline strings" do + before(:each) { + # clear buffer + vim.normal 'gg"_dG' + + # Insert two blank lines. + # The first line is a corner case in this plugin that would shadow the + # correct behaviour of other tests. Thus we explicitly jump to the first + # line when we require so. + vim.feedkeys 'i\\\' + } + + describe "when after an '(' that is followed by an unfinished string" do + before { vim.feedkeys 'itest("""' } + + it "it indents the next line" do + vim.feedkeys '\' + expected_proposed, expected_indent = multiline_indent(0, shiftwidth) + proposed_indent.should == expected_proposed + indent.should == expected_indent + end + + it "with contents it indents the second line to the parenthesis" do + vim.feedkeys 'second line\' + expected_proposed, expected_indent = multiline_indent(0, 5) + proposed_indent.should == expected_proposed + indent.should == expected_indent + end + end + + describe "when after assigning an unfinished string" do + before { vim.feedkeys 'itest = """' } + + it "it indents the next line" do + vim.feedkeys '\' + expected_proposed, expected_indent = multiline_indent(0, shiftwidth) + proposed_indent.should == expected_proposed + indent.should == expected_indent + end + end + + describe "when after assigning an indented unfinished string" do + before { vim.feedkeys 'i test = """' } + + it "it indents the next line" do + vim.feedkeys '\' + expected_proposed, expected_indent = multiline_indent(4, shiftwidth + 4) + proposed_indent.should == expected_proposed + indent.should == expected_indent + end + end + + describe "when after assigning an indented finished string" do + before { vim.feedkeys 'i test = ""' } + + it "it does indent the next line" do + vim.feedkeys '\' + indent.should == 4 + end + + it "and writing a new string, it does indent the next line" do + vim.feedkeys '\""' + indent.should == 4 + end + end + + describe "when after a docstring" do + it "it does indent the next line to the docstring" do + vim.feedkeys 'i """\' + indent.should == 4 + proposed_indent.should == 4 + end + + it "indents the closing docstring quotes" do + vim.feedkeys 'i """\\"""' + indent.should == 4 + proposed_indent.should == 4 + vim.echo('getline(3)').should == ' """' + end + + it "indents non-matching docstring quotes" do + vim.feedkeys 'i """\\' + vim.feedkeys "0C'''" + vim.echo('line(".")').should == "4" + vim.echo('getline(".")').should == "'''" + indent.should == 0 + proposed_indent.should == -1 + end + end + + describe "when after a docstring with contents" do + before { vim.feedkeys 'i """First line' } + it "it does indent the next line to the docstring" do + vim.feedkeys '\' + indent.should == 4 + proposed_indent.should == 4 + end + end + + describe "when breaking a string after opening parenthesis" do + before { vim.feedkeys 'i foo("""bar\\\' } + it "it does indent the next line as after an opening multistring" do + vim.feedkeys '\' + _, expected_indent = multiline_indent(4, 4 + shiftwidth) + indent.should == expected_indent + proposed_indent.should == -1 + + # it keeps the indent after an empty line + vim.feedkeys '\' + proposed_indent, expected_indent = multiline_indent(4, 4 + shiftwidth) + indent.should == expected_indent + proposed_indent.should == proposed_indent + + # it keeps the indent of nonblank above + vim.feedkeys '\\' + proposed_indent, expected_indent = multiline_indent(4, 4 + shiftwidth) + indent.should == expected_indent + proposed_indent.should == proposed_indent + + # it keeps the indent of nonblank above before an empty line + vim.feedkeys '\' + proposed_indent, expected_indent = multiline_indent(4, 4 + shiftwidth) + indent.should == expected_indent + proposed_indent.should == proposed_indent + end + end +end + +SUITE_SHIFTWIDTHS = [4, 3] +SUITE_HANG_CLOSINGS = [false, true] + +SUITE_SHIFTWIDTHS.each do |sw| + describe "vim when using width of #{sw}" do + before { + vim.command("set sw=#{sw} ts=#{sw} sts=#{sw} et") + } + it "sets shiftwidth to #{sw}" do + shiftwidth.should == sw + end + + SUITE_HANG_CLOSINGS.each do |hc| + describe "vim when hang_closing is set to #{hc}" do + before { + set_hang_closing hc + } + it "sets hang_closing to #{hc}" do + hang_closing.should == !!hc + end + + it_behaves_like "vim" + end + end + end +end + +describe "vim when not using python_pep8_indent_multiline_string" do + before { + vim.command("set sw=4 ts=4 sts=4 et") + vim.command("unlet! g:python_pep8_indent_multiline_string") + } + it_behaves_like "multiline strings" +end + +describe "vim when using python_pep8_indent_multiline_first=0" do + before { + vim.command("set sw=4 ts=4 sts=4 et") + vim.command("let g:python_pep8_indent_multiline_string=0") + } + it_behaves_like "multiline strings" +end + +describe "vim when using python_pep8_indent_multiline_string=-1" do + before { + vim.command("set sw=4 ts=4 sts=4 et") + vim.command("let g:python_pep8_indent_multiline_string=-1") + } + it_behaves_like "multiline strings" +end + +describe "vim when using python_pep8_indent_multiline_string=-2" do + before { + vim.command("set sw=4 ts=4 sts=4 et") + vim.command("let g:python_pep8_indent_multiline_string=-2") + } + it_behaves_like "multiline strings" +end + +describe "Handles far away opening parens" do + before { vim.feedkeys '\ggdGifrom foo import (' } + + it "indents by one level" do + vim.feedkeys '\' + proposed_indent.should == shiftwidth + end + + it "indents by one level for 10 lines" do + vim.command('set paste | exe "norm 9o" | set nopaste') + vim.feedkeys '\o' + indent.should == shiftwidth + end + + it "indents by one level for 50 lines" do + vim.command('set paste | exe "norm 49o" | set nopaste') + vim.feedkeys '\o' + indent.should == shiftwidth + end +end + +describe "Handles far away opening square brackets" do + before { vim.feedkeys '\ggdGibar = [' } + + it "indents by one level" do + vim.feedkeys '\' + proposed_indent.should == shiftwidth + end + + it "indents by one level for 10 lines" do + vim.command('set paste | exe "norm 9o" | set nopaste') + vim.feedkeys '\o' + indent.should == shiftwidth + end + + it "indents by one level for 100 lines" do + vim.command('set paste | exe "norm 99o" | set nopaste') + vim.feedkeys '\o' + indent.should == shiftwidth + end +end + +describe "Handles far away opening curly brackets" do + before { vim.feedkeys '\ggdGijson = {' } + + it "indents by one level" do + vim.feedkeys '\' + vim.feedkeys '\o' + proposed_indent.should == shiftwidth + end + + it "indents by one level for 10 lines" do + vim.command('set paste | exe "norm 9o" | set nopaste') + vim.feedkeys '\o' + indent.should == shiftwidth + end + + it "indents by one level for 1000 lines" do + vim.command('set paste | exe "norm 999o" | set nopaste') + vim.feedkeys '\o' + indent.should == shiftwidth + end +end + +describe "Compact multiline dict" do + before { vim.feedkeys '\ggdGid = {"one": 1,' } + + it "gets indented correctly" do + vim.feedkeys '\' + proposed_indent.should == 5 + + vim.feedkeys '"two": 2}' + proposed_indent.should == 5 + + vim.feedkeys '\' + proposed_indent.should == 0 + end +end + +describe "Using O" do + before { + vim.feedkeys '\ggdG' + vim.feedkeys 'iif foo:\' + } + + it "respects autoindent" do + vim.feedkeys '1\\' + indent.should == shiftwidth + vim.feedkeys '\ko' + indent.should == shiftwidth + vim.feedkeys '\kO' + indent.should == shiftwidth + # Uses/keeps indent from line above + vim.feedkeys '\i2\O' + indent.should == shiftwidth + # Uses/keeps indent from line above + vim.feedkeys '\j\O' + indent.should == 0 + end +end + +describe "searchpairpos" do + before { vim.feedkeys '\ggdG' } + it "handles nested parenthesis" do + vim.feedkeys 'iif foo.startswith("("):\' + indent.should == shiftwidth + end +end + +describe "o within TODO" do + before { + vim.feedkeys '\ggdG' + vim.feedkeys 'iif 1: # TODO\' + # Assertion that we have a pythonTodo here. + vim.echo('synIDattr(synID(line("."), col("."), 0), "name")').should match 'pythonTodo' + } + + it "respects autoindent" do + vim.feedkeys 'o' + indent.should == shiftwidth + end +end + +describe "elif after else" do + before { + vim.feedkeys '\ggdG' + } + + it "is indented to the outer if" do + vim.feedkeys 'iif 1:\if 2:\pass\else:\pass\elif 3:\' + indent.should == 0 + + vim.feedkeys '\ggdG' + vim.feedkeys 'i if 1:\if 2:\pass\else:\pass\elif 3:\' + indent.should == 4 + end +end + +describe "elif after two ifs" do + before { + vim.feedkeys '\ggdG' + } + + it "keeps its indent to the outer if" do + vim.feedkeys 'iif 1:\if 2:\pass\elif 3:\pass\' + indent.should == 4 + vim.feedkeys '\' + indent.should == 0 + proposed_indent.should == shiftwidth + vim.feedkeys 'ielif 4:' + indent.should == 0 + proposed_indent.should == 0 + vim.feedkeys '\' + indent.should == 4 + proposed_indent.should == 4 + end +end diff --git a/.vim/bundle/vim-python-pep8-indent/spec/make-coverage b/.vim/bundle/vim-python-pep8-indent/spec/make-coverage new file mode 100755 index 0000000..f425496 --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/spec/make-coverage @@ -0,0 +1,24 @@ +#!/bin/sh + +set -ex + +rm -f .coverage_covimerage +export PYTHON_PEP8_INDENT_TEST_PROFILE_BASE=/tmp/vim-python-pep8-profile + +Xvfb :99 2>/dev/null >&2 & +export DISPLAY=:99 + +export VIMRUNNER_REUSE_SERVER=1 + +ret=0 +for file in ./spec/indent/*_spec.rb; do + # shellcheck disable=SC2086 + bundle exec rspec "$file" $RSPEC_OPTIONS || ret=1 + + for p in "${PYTHON_PEP8_INDENT_TEST_PROFILE_BASE}".*; do + covimerage write_coverage --append "$p" + rm "$p" + covimerage report -m + done +done +exit $ret diff --git a/.vim/bundle/vim-python-pep8-indent/spec/spec_helper.rb b/.vim/bundle/vim-python-pep8-indent/spec/spec_helper.rb new file mode 100644 index 0000000..c6cc517 --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/spec/spec_helper.rb @@ -0,0 +1,70 @@ +require 'vimrunner' +require 'vimrunner/rspec' +require 'vimrunner/server' + +# Explicitly enable usage of "should". +RSpec.configure do |config| + config.expect_with(:rspec) { |c| c.syntax = :should } +end + +Vimrunner::RSpec.configure do |config| + # Use a single Vim instance for the test suite. Set to false to use an + # instance per test (slower, but can be easier to manage). + # This requires using gvim, otherwise it hangs after a few tests. + config.reuse_server = ENV['VIMRUNNER_REUSE_SERVER'] == '1' ? true : false + + config.start_vim do + exe = config.reuse_server ? Vimrunner::Platform.gvim : Vimrunner::Platform.vim + vimrc = File.expand_path("../vimrc", __FILE__) + vim = Vimrunner::Server.new(:executable => exe, + :vimrc => vimrc).start + # More friendly killing. + # Otherwise profiling information might not be written. + def vim.kill + normal(':qall!') + + Timeout.timeout(5) do + sleep 0.1 while server.running? + end + end + + plugin_path = File.expand_path('../..', __FILE__) + vim.command "set rtp^=#{plugin_path}" + vim.command "set filetype=python" + + def shiftwidth + @shiftwidth ||= vim.echo("exists('*shiftwidth') ? shiftwidth() : &sw").to_i + end + def tabstop + @tabstop ||= vim.echo("&tabstop").to_i + end + def indent + vim.echo("indent('.')").to_i + end + def previous_indent + pline = vim.echo("line('.')").to_i - 1 + vim.echo("indent('#{pline}')").to_i + end + def proposed_indent + line = vim.echo("line('.')") + col = vim.echo("col('.')") + indent_value = vim.echo("GetPythonPEPIndent(#{line})").to_i + vim.command("call cursor(#{line}, #{col})") + return indent_value + end + def multiline_indent(prev, default) + i = vim.echo("get(g:, 'python_pep8_indent_multiline_string', 0)").to_i + return (i == -2 ? default : i), i < 0 ? (i == -1 ? prev : default) : i + end + def hang_closing + i = vim.echo("get(g:, 'python_pep8_indent_hang_closing', 0)").to_i + return (i != 0) + end + def set_hang_closing(value) + i = value ? 1 : 0 + vim.command("let g:python_pep8_indent_hang_closing=#{i}") + end + + vim + end +end diff --git a/.vim/bundle/vim-python-pep8-indent/spec/vimrc b/.vim/bundle/vim-python-pep8-indent/spec/vimrc new file mode 100644 index 0000000..e549f80 --- /dev/null +++ b/.vim/bundle/vim-python-pep8-indent/spec/vimrc @@ -0,0 +1,22 @@ +" vint: -ProhibitSetNoCompatible +set nocompatible + +filetype plugin on +filetype indent on +syntax on + +set noswapfile nobackup + +" remove default ~/.vim directories to avoid loading plugins +set runtimepath-=~/.vim +set runtimepath-=~/.vim/after + +let sfile = expand('') +let plugin_path = fnamemodify(sfile, ':p:h:h') +exe 'set runtimepath^='.plugin_path + +if !empty($PYTHON_PEP8_INDENT_TEST_PROFILE_BASE) + execute printf('profile start %s.%s', + \ $PYTHON_PEP8_INDENT_TEST_PROFILE_BASE, getpid()) + execute 'profile! file '. plugin_path . '/indent/python.vim' +endif