All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
3 shared_examples_for "vim" do
8 # Insert two blank lines.
9 # The first line is a corner case in this plugin that would shadow the
10 # correct behaviour of other tests. Thus we explicitly jump to the first
11 # line when we require so.
12 vim.feedkeys 'i\<CR>\<CR>\<ESC>'
15 describe "when using the indent plugin" do
16 it "sets the indentexpr and indentkeys options" do
17 vim.command("set indentexpr?").should include "GetPythonPEPIndent("
18 vim.command("set indentkeys?").should include "=elif"
21 it "sets autoindent and expandtab" do
22 vim.command("set autoindent?").should match(/\s*autoindent/)
23 vim.command("set expandtab?").should match(/\s*expandtab/)
27 describe "when entering the first line" do
28 before { vim.feedkeys '0ggipass' }
30 it "does not indent" do
32 proposed_indent.should == 0
35 it "does not indent when using '=='" do
41 describe "when after a '(' that is at the end of its line" do
42 before { vim.feedkeys 'itest(\<CR>' }
44 it "indents by one level" do
45 proposed_indent.should == shiftwidth
46 vim.feedkeys 'something'
47 indent.should == shiftwidth
49 indent.should == shiftwidth
52 it "puts the closing parenthesis at the same level" do
54 indent.should == (hang_closing ? shiftwidth : 0)
58 describe "when after an '(' that is followed by something" do
59 before { vim.feedkeys 'itest(something,\<CR>' }
61 it "lines up on following lines" do
63 vim.feedkeys 'more,\<CR>'
67 it "lines up the closing parenthesis" do
72 it "does not touch the closing parenthesis if it is already indented further" do
78 describe "when after an '{' that is followed by a comment" do
79 before { vim.feedkeys 'imydict = { # comment\<CR>' }
81 it "indent by one level" do
82 indent.should == shiftwidth
83 vim.feedkeys '1: 1,\<CR>'
84 indent.should == shiftwidth
87 it "lines up the closing parenthesis" do
89 indent.should == (hang_closing ? shiftwidth : 0)
93 describe "when using gq to reindent a '(' that is" do
94 before { vim.feedkeys 'itest(' }
95 it "something and has a string without spaces at the end" do
96 vim.feedkeys 'something_very_long_blaaaaaaaaa, "some_very_long_string_blaaaaaaaaaaaaaaaaaaaa"\<esc>gqq'
101 describe "when after multiple parens of different types" do
102 it "indents by one level" do
103 vim.feedkeys 'if({\<CR>'
104 indent.should == shiftwidth
107 it "lines up with the last paren" do
108 vim.feedkeys 'ifff({123: 456,\<CR>'
113 describe "when '#' is contained in a string that is followed by a colon" do
114 it "indents by one level" do
115 vim.feedkeys 'iif "some#thing" == "test":#test\<CR>pass'
116 indent.should == shiftwidth
120 describe "when '#' is not contained in a string and is followed by a colon" do
121 it "does not indent" do
122 vim.feedkeys 'iif "some#thing" == "test"#:test\<CR>'
127 describe "when inside an unfinished string" do
128 it "does not indent" do
129 vim.feedkeys 'i"test:\<ESC>'
130 vim.echo('synIDattr(synID(line("."), col("."), 0), "name")'
131 ).downcase.should include 'string'
132 vim.feedkeys 'a\<CR>'
133 proposed_indent.should == -1
137 it "does not dedent" do
138 vim.feedkeys 'iif True:\<CR>"test:\<ESC>'
139 vim.echo('synIDattr(synID(line("."), col("."), 0), "name")'
140 ).downcase.should include 'string'
141 proposed_indent.should == shiftwidth
142 indent.should == shiftwidth
146 describe "when the previous line has a colon in a string" do
147 before { vim.feedkeys 'itest(":".join(["1","2"]))\<CR>' }
148 it "does not indent" do
149 vim.feedkeys 'if True:'
151 proposed_indent.should == 0
155 describe "when the previous line has a list slice" do
156 it "does not indent" do
157 vim.feedkeys 'ib = a[2:]\<CR>'
159 proposed_indent.should == 0
163 describe "when line is empty inside a block" do
164 it "is indented like the previous line" do
165 vim.feedkeys 'idef a():\<CR>1\<CR>\<CR>2\<ESC>kcc'
166 indent.should == shiftwidth
170 describe "when an empty line is after empty line / before non-empty" do
171 it "is indented like the next line" do
172 vim.feedkeys 'idef a():\<CR>1\<CR>\<CR>\<CR>2\<ESC><<kcc'
177 describe "when an empty line is after empty line / before non-empty (nested)" do
178 it "is indented like the next line" do
179 vim.feedkeys 'idef a():\<CR>1\<CR>\<CR>\<CR>\<ESC>0i\<TAB>2\<ESC>kcc'
180 indent.should == shiftwidth
184 describe "when line is empty inside a block following multi-line statement" do
185 it "is indented like the previous line" do
186 vim.feedkeys 'idef a():\<CR>x = (1 +\<CR>2)\<CR>\<CR>y\<ESC>kcc'
187 indent.should == shiftwidth
191 describe "when line is empty inside a block following stop statement" do
192 it "is indented like the previous line minus shiftwidth" do
193 vim.feedkeys 'iif x:\<CR>if y:\<CR>pass\<CR>\<CR>z\<ESC>kcc'
194 indent.should == shiftwidth
198 describe "when using simple control structures" do
199 it "indents shiftwidth spaces" do
200 vim.feedkeys 'iwhile True:\<CR>pass'
201 indent.should == shiftwidth
205 describe "when using a function definition" do
206 it "handles indent with closing parenthesis on same line" do
207 vim.feedkeys 'idef long_function_name(\<CR>arg'
208 indent.should == shiftwidth
210 indent.should == shiftwidth * 2
213 it "handles indent with closing parenthesis on new line" do
214 vim.feedkeys 'idef long_function_name(\<CR>arg'
215 indent.should == shiftwidth
217 indent.should == shiftwidth
219 indent.should == (hang_closing ? shiftwidth * 2 : 0)
221 indent.should == (hang_closing ? shiftwidth * 2 : 0)
222 vim.feedkeys '\<Esc>k'
223 indent.should == shiftwidth
227 describe "when using a class definition" do
228 it "indents shiftwidth spaces" do
229 vim.feedkeys 'iclass Foo(\<CR>'
230 indent.should == shiftwidth
234 describe "when writing an 'else' block" do
235 it "aligns to the preceeding 'for' block" do
236 vim.feedkeys 'ifor x in "abc":\<CR>pass\<CR>else:'
240 it "aligns to the preceeding 'if' block" do
241 vim.feedkeys 'ifor x in "abc":\<CR>if True:\<CR>pass\<CR>else:'
242 indent.should == shiftwidth
246 describe "when using parens and control statements" do
247 it "avoids ambiguity by using extra indentation" do
248 vim.feedkeys 'iif (111 and\<CR>'
250 indent.should == shiftwidth * 2
254 vim.feedkeys '222):\<CR>'
255 indent.should == shiftwidth
256 vim.feedkeys 'pass\<CR>'
260 it "still aligns parens properly if not ambiguous" do
261 vim.feedkeys 'iwhile (111 and\<CR>'
263 vim.feedkeys '222):\<CR>'
264 indent.should == shiftwidth
265 vim.feedkeys 'pass\<CR>'
269 it "handles nested expressions (Flake8's E127)" do
270 vim.feedkeys 'i[\<CR>x for x in foo\<CR>if (\<CR>'
271 indent.should == shiftwidth * 2
274 it "still handles multiple parens correctly" do
275 vim.feedkeys 'iif (111 and (222 and 333\<CR>'
277 vim.feedkeys 'and 444\<CR>'
279 vim.feedkeys ')\<CR>'
281 indent.should == shiftwidth * 2
285 vim.feedkeys 'and 555):\<CR>'
286 indent.should == shiftwidth
287 vim.feedkeys 'pass\<CR>'
292 describe "when a line breaks with a manual '\\'" do
293 it "indents shiftwidth spaces on normal line" do
294 vim.feedkeys 'ivalue = test + \\\\\<CR>'
295 indent.should == shiftwidth
298 it "indents 2x shiftwidth spaces for control structures" do
299 vim.feedkeys 'iif somevalue == xyz and \\\\\<CR>'
300 indent.should == shiftwidth * 2
303 it "indents relative to line above" do
304 vim.feedkeys 'i\<TAB>value = test + \\\\\<CR>'
305 indent.should == shiftwidth * 2
309 describe "when current line is dedented compared to previous line" do
310 before { vim.feedkeys 'i\<TAB>\<TAB>if x:\<CR>y = True\<CR>\<ESC>' }
311 it "and current line has a valid indentation (Part 1)" do
312 vim.feedkeys '0i\<TAB>if y:'
313 proposed_indent.should == -1
316 it "and current line has a valid indentation (Part 2)" do
317 vim.feedkeys '0i\<TAB>\<TAB>if y:'
318 proposed_indent.should == -1
321 it "and current line has an invalid indentation" do
322 vim.feedkeys 'i while True:\<CR>'
323 indent.should == previous_indent + shiftwidth
327 describe "when current line is dedented compared to the last non-empty line" do
328 before { vim.feedkeys 'i\<TAB>\<TAB>if x:\<CR>y = True\<CR>\<CR>\<ESC>' }
329 it "and current line has a valid indentation" do
330 vim.feedkeys '0i\<TAB>if y:'
331 proposed_indent.should == -1
335 describe "when an 'if' is followed by" do
336 before { vim.feedkeys 'i\<TAB>\<TAB>if x:\<CR>' }
337 it "an elif, it lines up with the 'if'" do
338 vim.feedkeys 'elif y:'
339 indent.should == shiftwidth * 2
342 it "an 'else', it lines up with the 'if'" do
344 indent.should == shiftwidth * 2
348 describe "when an 'if' contains a try-except" do
350 vim.feedkeys 'iif x:\<CR>try:\<CR>pass\<CR>except:\<CR>pass\<CR>'
351 indent.should == shiftwidth
353 it "an 'else' should be indented to the try" do
355 indent.should == shiftwidth
356 proposed_indent.should == shiftwidth
358 it "an 'else' should keep the indent of the 'if'" do
359 vim.feedkeys 'else:\<ESC><<'
361 proposed_indent.should == 0
365 describe "when a 'for' is followed by" do
366 before { vim.feedkeys 'i\<TAB>\<TAB>for x in y:\<CR>' }
367 it "an 'else', it lines up with the 'for'" do
369 indent.should == shiftwidth * 2
373 describe "when an 'else' is followed by" do
374 before { vim.feedkeys 'i\<TAB>\<TAB>else:\<CR>XXX\<CR>' }
375 it "a 'finally', it lines up with the 'else'" do
376 vim.feedkeys 'finally:'
377 indent.should == shiftwidth * 2
382 describe "when a 'try' is followed by" do
383 before { vim.feedkeys 'i\<TAB>\<TAB>try:\<CR>' }
384 it "an 'except', it lines up with the 'try'" do
385 vim.feedkeys 'except:'
386 indent.should == shiftwidth * 2
389 it "an 'else', it lines up with the 'try'" do
391 indent.should == shiftwidth * 2
394 it "a 'finally', it lines up with the 'try'" do
395 vim.feedkeys 'finally:'
396 indent.should == shiftwidth * 2
400 describe "when an 'except' is followed by" do
401 before { vim.feedkeys 'i\<TAB>\<TAB>except:\<CR>' }
402 it "an 'else', it lines up with the 'except'" do
404 indent.should == shiftwidth * 2
407 it "another 'except', it lines up with the previous 'except'" do
408 vim.feedkeys 'except:'
409 indent.should == shiftwidth * 2
412 it "a 'finally', it lines up with the 'except'" do
413 vim.feedkeys 'finally:'
414 indent.should == shiftwidth * 2
418 describe "when an else is used inside of a nested if" do
419 before { vim.feedkeys 'iif foo:\<CR>if bar:\<CR>pass\<CR>' }
420 it "indents the else to the inner if" do
422 indent.should == shiftwidth
426 describe "when an else is used outside of a nested if" do
427 before { vim.feedkeys 'iif True:\<CR>if True:\<CR>pass\<CR>\<Esc>0' }
428 it "indents the else to the outer if" do
430 proposed_indent.should == shiftwidth
432 vim.feedkeys 'ielse:'
434 proposed_indent.should == 0
438 describe "when jedi-vim call signatures are used" do
439 before { vim.command 'syn match jediFunction "JEDI_CALL_SIGNATURE" keepend extend' }
441 it "ignores the call signature after a colon" do
442 vim.feedkeys 'iif True: JEDI_CALL_SIGNATURE\<CR>'
443 indent.should == shiftwidth
446 it "ignores the call signature after a function" do
447 vim.feedkeys 'idef f( JEDI_CALL_SIGNATURE\<CR>'
448 indent.should == shiftwidth
453 shared_examples_for "multiline strings" do
458 # Insert two blank lines.
459 # The first line is a corner case in this plugin that would shadow the
460 # correct behaviour of other tests. Thus we explicitly jump to the first
461 # line when we require so.
462 vim.feedkeys 'i\<CR>\<CR>\<ESC>'
465 describe "when after an '(' that is followed by an unfinished string" do
466 before { vim.feedkeys 'itest("""' }
468 it "it indents the next line" do
470 expected_proposed, expected_indent = multiline_indent(0, shiftwidth)
471 proposed_indent.should == expected_proposed
472 indent.should == expected_indent
475 it "with contents it indents the second line to the parenthesis" do
476 vim.feedkeys 'second line\<CR>'
477 expected_proposed, expected_indent = multiline_indent(0, 5)
478 proposed_indent.should == expected_proposed
479 indent.should == expected_indent
483 describe "when after assigning an unfinished string" do
484 before { vim.feedkeys 'itest = """' }
486 it "it indents the next line" do
488 expected_proposed, expected_indent = multiline_indent(0, shiftwidth)
489 proposed_indent.should == expected_proposed
490 indent.should == expected_indent
494 describe "when after assigning an indented unfinished string" do
495 before { vim.feedkeys 'i test = """' }
497 it "it indents the next line" do
499 expected_proposed, expected_indent = multiline_indent(4, shiftwidth + 4)
500 proposed_indent.should == expected_proposed
501 indent.should == expected_indent
505 describe "when after assigning an indented finished string" do
506 before { vim.feedkeys 'i test = ""' }
508 it "it does indent the next line" do
513 it "and writing a new string, it does indent the next line" do
514 vim.feedkeys '\<CR>""'
519 describe "when after a docstring" do
520 it "it does indent the next line to the docstring" do
521 vim.feedkeys 'i """\<CR>'
523 proposed_indent.should == 4
526 it "indents the closing docstring quotes" do
527 vim.feedkeys 'i """\<CR>\<CR>"""'
529 proposed_indent.should == 4
530 vim.echo('getline(3)').should == ' """'
533 it "indents non-matching docstring quotes" do
534 vim.feedkeys 'i """\<CR>\<Esc>'
536 vim.echo('line(".")').should == "4"
537 vim.echo('getline(".")').should == "'''"
539 proposed_indent.should == -1
543 describe "when after a docstring with contents" do
544 before { vim.feedkeys 'i """First line' }
545 it "it does indent the next line to the docstring" do
548 proposed_indent.should == 4
552 describe "when breaking a string after opening parenthesis" do
553 before { vim.feedkeys 'i foo("""bar\<Left>\<Left>\<Left>' }
554 it "it does indent the next line as after an opening multistring" do
556 _, expected_indent = multiline_indent(4, 4 + shiftwidth)
557 indent.should == expected_indent
558 proposed_indent.should == -1
560 # it keeps the indent after an empty line
562 proposed_indent, expected_indent = multiline_indent(4, 4 + shiftwidth)
563 indent.should == expected_indent
564 proposed_indent.should == proposed_indent
566 # it keeps the indent of nonblank above
567 vim.feedkeys '\<End>\<CR>'
568 proposed_indent, expected_indent = multiline_indent(4, 4 + shiftwidth)
569 indent.should == expected_indent
570 proposed_indent.should == proposed_indent
572 # it keeps the indent of nonblank above before an empty line
574 proposed_indent, expected_indent = multiline_indent(4, 4 + shiftwidth)
575 indent.should == expected_indent
576 proposed_indent.should == proposed_indent
581 SUITE_SHIFTWIDTHS = [4, 3]
582 SUITE_HANG_CLOSINGS = [false, true]
584 SUITE_SHIFTWIDTHS.each do |sw|
585 describe "vim when using width of #{sw}" do
587 vim.command("set sw=#{sw} ts=#{sw} sts=#{sw} et")
589 it "sets shiftwidth to #{sw}" do
590 shiftwidth.should == sw
593 SUITE_HANG_CLOSINGS.each do |hc|
594 describe "vim when hang_closing is set to #{hc}" do
598 it "sets hang_closing to #{hc}" do
599 hang_closing.should == !!hc
602 it_behaves_like "vim"
608 describe "vim when not using python_pep8_indent_multiline_string" do
610 vim.command("set sw=4 ts=4 sts=4 et")
611 vim.command("unlet! g:python_pep8_indent_multiline_string")
613 it_behaves_like "multiline strings"
616 describe "vim when using python_pep8_indent_multiline_first=0" do
618 vim.command("set sw=4 ts=4 sts=4 et")
619 vim.command("let g:python_pep8_indent_multiline_string=0")
621 it_behaves_like "multiline strings"
624 describe "vim when using python_pep8_indent_multiline_string=-1" do
626 vim.command("set sw=4 ts=4 sts=4 et")
627 vim.command("let g:python_pep8_indent_multiline_string=-1")
629 it_behaves_like "multiline strings"
632 describe "vim when using python_pep8_indent_multiline_string=-2" do
634 vim.command("set sw=4 ts=4 sts=4 et")
635 vim.command("let g:python_pep8_indent_multiline_string=-2")
637 it_behaves_like "multiline strings"
640 describe "Handles far away opening parens" do
641 before { vim.feedkeys '\<ESC>ggdGifrom foo import (' }
643 it "indents by one level" do
645 proposed_indent.should == shiftwidth
648 it "indents by one level for 10 lines" do
649 vim.command('set paste | exe "norm 9o" | set nopaste')
650 vim.feedkeys '\<Esc>o'
651 indent.should == shiftwidth
654 it "indents by one level for 50 lines" do
655 vim.command('set paste | exe "norm 49o" | set nopaste')
656 vim.feedkeys '\<Esc>o'
657 indent.should == shiftwidth
661 describe "Handles far away opening square brackets" do
662 before { vim.feedkeys '\<ESC>ggdGibar = [' }
664 it "indents by one level" do
666 proposed_indent.should == shiftwidth
669 it "indents by one level for 10 lines" do
670 vim.command('set paste | exe "norm 9o" | set nopaste')
671 vim.feedkeys '\<Esc>o'
672 indent.should == shiftwidth
675 it "indents by one level for 100 lines" do
676 vim.command('set paste | exe "norm 99o" | set nopaste')
677 vim.feedkeys '\<Esc>o'
678 indent.should == shiftwidth
682 describe "Handles far away opening curly brackets" do
683 before { vim.feedkeys '\<ESC>ggdGijson = {' }
685 it "indents by one level" do
687 vim.feedkeys '\<Esc>o'
688 proposed_indent.should == shiftwidth
691 it "indents by one level for 10 lines" do
692 vim.command('set paste | exe "norm 9o" | set nopaste')
693 vim.feedkeys '\<Esc>o'
694 indent.should == shiftwidth
697 it "indents by one level for 1000 lines" do
698 vim.command('set paste | exe "norm 999o" | set nopaste')
699 vim.feedkeys '\<Esc>o'
700 indent.should == shiftwidth
704 describe "Compact multiline dict" do
705 before { vim.feedkeys '\<ESC>ggdGid = {"one": 1,' }
707 it "gets indented correctly" do
709 proposed_indent.should == 5
711 vim.feedkeys '"two": 2}'
712 proposed_indent.should == 5
715 proposed_indent.should == 0
719 describe "Using O" do
721 vim.feedkeys '\<ESC>ggdG'
722 vim.feedkeys 'iif foo:\<CR>'
725 it "respects autoindent" do
726 vim.feedkeys '1\<CR>\<CR>'
727 indent.should == shiftwidth
728 vim.feedkeys '\<Esc>ko'
729 indent.should == shiftwidth
730 vim.feedkeys '\<Esc>kO'
731 indent.should == shiftwidth
732 # Uses/keeps indent from line above
733 vim.feedkeys '\<Esc>i2\<Esc>O'
734 indent.should == shiftwidth
735 # Uses/keeps indent from line above
736 vim.feedkeys '\<Esc>j\<Esc>O'
741 describe "searchpairpos" do
742 before { vim.feedkeys '\<ESC>ggdG' }
743 it "handles nested parenthesis" do
744 vim.feedkeys 'iif foo.startswith("("):\<CR>'
745 indent.should == shiftwidth
749 describe "o within TODO" do
751 vim.feedkeys '\<ESC>ggdG'
752 vim.feedkeys 'iif 1: # TODO\<Esc>'
753 # Assertion that we have a pythonTodo here.
754 vim.echo('synIDattr(synID(line("."), col("."), 0), "name")').should match 'pythonTodo'
757 it "respects autoindent" do
759 indent.should == shiftwidth
763 describe "elif after else" do
765 vim.feedkeys '\<ESC>ggdG'
768 it "is indented to the outer if" do
769 vim.feedkeys 'iif 1:\<CR>if 2:\<CR>pass\<CR>else:\<CR>pass\<CR>elif 3:\<Esc>'
772 vim.feedkeys '\<ESC>ggdG'
773 vim.feedkeys 'i if 1:\<CR>if 2:\<CR>pass\<CR>else:\<CR>pass\<CR>elif 3:\<Esc>'