]> git.madduck.net Git - etc/vim.git/blob - spec/indent/indent_spec.rb

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

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.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

fix multiline strings when breaking a string after opening parenthesis (#58)
[etc/vim.git] / spec / indent / indent_spec.rb
1 require "spec_helper"
2
3 shared_examples_for "vim" do
4
5   before(:each) {
6     # clear buffer
7     vim.normal 'gg"_dG'
8
9     # Insert two blank lines.
10     # The first line is a corner case in this plugin that would shadow the
11     # correct behaviour of other tests. Thus we explicitly jump to the first
12     # line when we require so.
13     vim.feedkeys 'i\<CR>\<CR>\<ESC>'
14   }
15
16   describe "when using the indent plugin" do
17     it "sets the indentexpr and indentkeys options" do
18       vim.command("set indentexpr?").should include "GetPythonPEPIndent("
19       vim.command("set indentkeys?").should include "=elif"
20     end
21
22     it "sets autoindent and expandtab" do
23       vim.command("set autoindent?").should match(/\s*autoindent/)
24       vim.command("set expandtab?").should match(/\s*expandtab/)
25     end
26   end
27
28   describe "when entering the first line" do
29     before { vim.feedkeys '0ggipass' }
30
31     it "does not indent" do
32       indent.should == 0
33       proposed_indent.should == 0
34     end
35
36     it "does not indent when using '=='" do
37       vim.normal "=="
38       indent.should == 0
39     end
40   end
41
42   describe "when after a '(' that is at the end of its line" do
43     before { vim.feedkeys 'itest(\<CR>' }
44
45     it "indents by one level" do
46       proposed_indent.should == shiftwidth
47       vim.feedkeys 'something'
48       indent.should == shiftwidth
49       vim.normal '=='
50       indent.should == shiftwidth
51     end
52
53     it "puts the closing parenthesis at the same level" do
54       vim.feedkeys ')'
55       indent.should == 0
56     end
57   end
58
59   describe "when after an '(' that is followed by something" do
60     before { vim.feedkeys 'itest(something,\<CR>' }
61
62     it "lines up on following lines" do
63       indent.should == 5
64       vim.feedkeys 'more,\<CR>'
65       indent.should == 5
66     end
67
68     it "lines up the closing parenthesis" do
69       vim.feedkeys ')'
70       indent.should == 5
71     end
72
73     it "does not touch the closing parenthesis if it is already indented further" do
74       vim.feedkeys '  )'
75       indent.should == 7
76     end
77   end
78
79   describe "when after an '{' that is followed by a comment" do
80     before { vim.feedkeys 'imydict = {  # comment\<CR>' }
81
82     it "indent by one level" do
83       indent.should == shiftwidth
84       vim.feedkeys '1: 1,\<CR>'
85       indent.should == shiftwidth
86     end
87
88     it "lines up the closing parenthesis" do
89       vim.feedkeys '}'
90       indent.should == 0
91     end
92   end
93
94   describe "when using gq to reindent a '(' that is" do
95     before { vim.feedkeys 'itest(' }
96     it "something and has a string without spaces at the end" do
97       vim.feedkeys 'something_very_long_blaaaaaaaaa, "some_very_long_string_blaaaaaaaaaaaaaaaaaaaa"\<esc>gqq'
98       indent.should == 5
99     end
100   end
101
102   describe "when after multiple parens of different types" do
103     it "indents by one level" do
104       vim.feedkeys 'if({\<CR>'
105       indent.should == shiftwidth
106     end
107
108     it "lines up with the last paren" do
109       vim.feedkeys 'ifff({123: 456,\<CR>'
110       indent.should == 5
111     end
112   end
113
114   describe "when '#' is contained in a string that is followed by a colon" do
115     it "indents by one level" do
116         vim.feedkeys 'iif "some#thing" == "test":#test\<CR>pass'
117         indent.should == shiftwidth
118     end
119   end
120
121   describe "when '#' is not contained in a string and is followed by a colon" do
122     it "does not indent" do
123         vim.feedkeys 'iif "some#thing" == "test"#:test\<CR>'
124         indent.should == 0
125     end
126   end
127
128   describe "when inside an unfinished string" do
129     it "does not indent" do
130       vim.feedkeys 'i"test:\<ESC>'
131       vim.echo('synIDattr(synID(line("."), col("."), 0), "name")'
132               ).downcase.should include 'string'
133       vim.feedkeys 'a\<CR>'
134       proposed_indent.should == 0
135       indent.should == 0
136     end
137
138     it "does not dedent" do
139       vim.feedkeys 'iif True:\<CR>"test:\<ESC>'
140       vim.echo('synIDattr(synID(line("."), col("."), 0), "name")'
141               ).downcase.should include 'string'
142       proposed_indent.should == shiftwidth
143       indent.should == shiftwidth
144     end
145   end
146
147   describe "when the previous line has a colon in a string" do
148     before { vim.feedkeys 'itest(":".join(["1","2"]))\<CR>' }
149     it "does not indent" do
150       vim.feedkeys 'if True:'
151       indent.should == 0
152       proposed_indent.should == 0
153     end
154   end
155
156   describe "when the previous line has a list slice" do
157     it "does not indent" do
158       vim.feedkeys 'ib = a[2:]\<CR>'
159       indent.should == 0
160       proposed_indent.should == 0
161     end
162   end
163
164   describe "when using simple control structures" do
165       it "indents shiftwidth spaces" do
166           vim.feedkeys 'iwhile True:\<CR>pass'
167           indent.should == shiftwidth
168       end
169   end
170
171   describe "when using a function definition" do
172       it "indents shiftwidth spaces" do
173           vim.feedkeys 'idef long_function_name(\<CR>arg'
174           indent.should == shiftwidth * 2
175       end
176   end
177
178   describe "when using a class definition" do
179       it "indents shiftwidth spaces" do
180           vim.feedkeys 'iclass Foo(\<CR>'
181           indent.should == shiftwidth * 2
182       end
183   end
184
185   describe "when writing an 'else' block" do
186     it "aligns to the preceeding 'for' block" do
187       vim.feedkeys 'ifor x in "abc":\<CR>pass\<CR>else:'
188       indent.should == 0
189     end
190
191     it "aligns to the preceeding 'if' block" do
192       vim.feedkeys 'ifor x in "abc":\<CR>if True:\<CR>pass\<CR>else:'
193       indent.should == shiftwidth
194     end
195   end
196
197   describe "when using parens and control statements" do
198     it "avoids ambiguity by using extra indentation" do
199       vim.feedkeys 'iif (111 and\<CR>'
200       if shiftwidth == 4
201         indent.should == shiftwidth * 2
202       else
203         indent.should == 4
204       end
205       vim.feedkeys '222):\<CR>'
206       indent.should == shiftwidth
207       vim.feedkeys 'pass\<CR>'
208       indent.should == 0
209     end
210
211     it "still aligns parens properly if not ambiguous" do
212       vim.feedkeys 'iwhile (111 and\<CR>'
213       indent.should == 7
214       vim.feedkeys '222):\<CR>'
215       indent.should == shiftwidth
216       vim.feedkeys 'pass\<CR>'
217       indent.should == 0
218     end
219
220     it "still handles multiple parens correctly" do
221       vim.feedkeys 'iif (111 and (222 and 333\<CR>'
222       indent.should == 13
223       vim.feedkeys 'and 444\<CR>'
224       indent.should == 13
225       vim.feedkeys ')\<CR>'
226       if shiftwidth == 4
227         indent.should == shiftwidth * 2
228       else
229         indent.should == 4
230       end
231       vim.feedkeys 'and 555):\<CR>'
232       indent.should == shiftwidth
233       vim.feedkeys 'pass\<CR>'
234       indent.should == 0
235     end
236   end
237
238   describe "when a line breaks with a manual '\\'" do
239     it "indents shiftwidth spaces on normal line" do
240         vim.feedkeys 'ivalue = test + \\\\\<CR>'
241         indent.should == shiftwidth
242     end
243
244     it "indents 2x shiftwidth spaces for control structures" do
245         vim.feedkeys 'iif somevalue == xyz and \\\\\<CR>'
246         indent.should == shiftwidth * 2
247     end
248
249     it "indents relative to line above" do
250         vim.feedkeys 'i\<TAB>value = test + \\\\\<CR>'
251         indent.should == shiftwidth * 2
252     end
253   end
254
255   describe "when current line is dedented compared to previous line" do
256      before { vim.feedkeys 'i\<TAB>\<TAB>if x:\<CR>y = True\<CR>\<ESC>' }
257      it "and current line has a valid indentation (Part 1)" do
258         vim.feedkeys '0i\<TAB>if y:'
259         proposed_indent.should == -1
260      end
261
262      it "and current line has a valid indentation (Part 2)" do
263         vim.feedkeys '0i\<TAB>\<TAB>if y:'
264         proposed_indent.should == -1
265      end
266
267      it "and current line has an invalid indentation" do
268         vim.feedkeys 'i    while True:\<CR>'
269         indent.should == previous_indent + shiftwidth
270      end
271   end
272
273   describe "when current line is dedented compared to the last non-empty line" do
274      before { vim.feedkeys 'i\<TAB>\<TAB>if x:\<CR>y = True\<CR>\<CR>\<ESC>' }
275      it "and current line has a valid indentation" do
276         vim.feedkeys '0i\<TAB>if y:'
277         proposed_indent.should == -1
278      end
279   end
280
281   describe "when an 'if' is followed by" do
282      before { vim.feedkeys 'i\<TAB>\<TAB>if x:\<CR>' }
283      it "an elif, it lines up with the 'if'" do
284         vim.feedkeys 'elif y:'
285         indent.should == shiftwidth * 2
286      end
287
288      it "an 'else', it lines up with the 'if'" do
289         vim.feedkeys 'else:'
290         indent.should == shiftwidth * 2
291      end
292   end
293
294   describe "when an 'if' contains a try-except" do
295      before {
296        vim.feedkeys 'iif x:\<CR>try:\<CR>pass\<CR>except:\<CR>pass\<CR>'
297        indent.should == shiftwidth
298      }
299      it "an 'else' should be indented to the try" do
300        vim.feedkeys 'else:'
301        indent.should == shiftwidth
302        proposed_indent.should == shiftwidth
303      end
304      it "an 'else' should keep the indent of the 'if'" do
305        vim.feedkeys 'else:\<ESC><<'
306        indent.should == 0
307        proposed_indent.should == 0
308      end
309   end
310
311   describe "when a 'for' is followed by" do
312      before { vim.feedkeys 'i\<TAB>\<TAB>for x in y:\<CR>' }
313      it "an 'else', it lines up with the 'for'" do
314         vim.feedkeys 'else:'
315         indent.should == shiftwidth * 2
316      end
317   end
318
319   describe "when an 'else' is followed by" do
320      before { vim.feedkeys 'i\<TAB>\<TAB>else:\<CR>XXX\<CR>' }
321      it "a 'finally', it lines up with the 'else'" do
322         vim.feedkeys 'finally:'
323         indent.should == shiftwidth * 2
324      end
325   end
326
327
328   describe "when a 'try' is followed by" do
329      before { vim.feedkeys 'i\<TAB>\<TAB>try:\<CR>' }
330      it "an 'except', it lines up with the 'try'" do
331         vim.feedkeys 'except:'
332         indent.should == shiftwidth * 2
333      end
334
335      it "an 'else', it lines up with the 'try'" do
336         vim.feedkeys 'else:'
337         indent.should == shiftwidth * 2
338      end
339
340      it "a 'finally', it lines up with the 'try'" do
341         vim.feedkeys 'finally:'
342         indent.should == shiftwidth * 2
343      end
344   end
345
346   describe "when an 'except' is followed by" do
347      before { vim.feedkeys 'i\<TAB>\<TAB>except:\<CR>' }
348      it "an 'else', it lines up with the 'except'" do
349         vim.feedkeys 'else:'
350         indent.should == shiftwidth * 2
351      end
352
353      it "another 'except', it lines up with the previous 'except'" do
354         vim.feedkeys 'except:'
355         indent.should == shiftwidth * 2
356      end
357
358      it "a 'finally', it lines up with the 'except'" do
359         vim.feedkeys 'finally:'
360         indent.should == shiftwidth * 2
361      end
362   end
363
364   describe "when an else is used inside of a nested if" do
365     before { vim.feedkeys 'iif foo:\<CR>\<TAB>if bar:\<CR>\<TAB>\<TAB>pass\<CR>' }
366     it "indents an else to the inner if" do
367       vim.feedkeys 'else:'
368       indent.should == shiftwidth * 2
369     end
370   end
371
372   describe "when jedi-vim call signatures are used" do
373     before { vim.command 'syn match jediFunction "JEDI_CALL_SIGNATURE" keepend extend' }
374
375     it "ignores the call signature after a colon" do
376       vim.feedkeys 'iif True:  JEDI_CALL_SIGNATURE\<CR>'
377       indent.should == shiftwidth
378     end
379
380     it "ignores the call signature after a function" do
381       vim.feedkeys 'idef f(  JEDI_CALL_SIGNATURE\<CR>'
382       indent.should == shiftwidth * 2
383     end
384   end
385 end
386
387 shared_examples_for "multiline strings" do
388   describe "when after an '(' that is followed by an unfinished string" do
389     before { vim.feedkeys 'itest("""' }
390
391     it "it indents the next line" do
392       vim.feedkeys '\<CR>'
393       expected_proposed, expected_indent = multiline_indent(0, shiftwidth)
394       proposed_indent.should == expected_proposed
395       indent.should == expected_indent
396     end
397
398     it "with contents it indents the second line to the parenthesis" do
399       vim.feedkeys 'second line\<CR>'
400       expected_proposed, expected_indent = multiline_indent(0, 5)
401       proposed_indent.should == expected_proposed
402       indent.should == expected_indent
403     end
404   end
405
406   describe "when after assigning an unfinished string" do
407     before { vim.feedkeys 'itest = """' }
408
409     it "it indents the next line" do
410       vim.feedkeys '\<CR>'
411       expected_proposed, expected_indent = multiline_indent(0, shiftwidth)
412       proposed_indent.should == expected_proposed
413       indent.should == expected_indent
414     end
415   end
416
417   describe "when after assigning an unfinished string" do
418     before { vim.feedkeys 'i    test = """' }
419
420     it "it indents the next line" do
421       vim.feedkeys '\<CR>'
422       expected_proposed, expected_indent = multiline_indent(4, shiftwidth + 4)
423       proposed_indent.should == expected_proposed
424       indent.should == expected_indent
425     end
426   end
427
428   describe "when after assigning a finished string" do
429     before { vim.feedkeys 'i    test = ""' }
430
431     it "it does indent the next line" do
432       vim.feedkeys '\<CR>'
433       indent.should == 4
434     end
435
436     it "and writing a new string, it does indent the next line" do
437       vim.feedkeys '\<CR>""'
438       indent.should == 4
439     end
440   end
441
442   describe "when after a docstring" do
443     before { vim.feedkeys 'i    """' }
444     it "it does indent the next line to the docstring" do
445       vim.feedkeys '\<CR>'
446       indent.should == 4
447       proposed_indent.should == 4
448     end
449   end
450
451   describe "when after a docstring with contents" do
452     before { vim.feedkeys 'i    """First line' }
453     it "it does indent the next line to the docstring" do
454       vim.feedkeys '\<CR>'
455       indent.should == 4
456       proposed_indent.should == 4
457     end
458   end
459
460   describe "when breaking a string after opening parenthesis" do
461     before { vim.feedkeys 'i    foo("""bar<Left><Left><Left>' }
462     it "it does indent the next line as after an opening multistring" do
463       vim.feedkeys '\<CR>'
464       expected_proposed, expected_indent = multiline_indent(4, 4 + shiftwidth)
465       indent.should == expected_indent
466       proposed_indent.should == expected_proposed
467     end
468   end
469 end
470
471 describe "vim when using width of 4" do
472   before {
473     vim.command("set sw=4 ts=4 sts=4 et")
474   }
475   it_behaves_like "vim"
476 end
477
478 describe "vim when using width of 3" do
479   before {
480     vim.command("set sw=3 ts=3 sts=3 et")
481   }
482   it_behaves_like "vim"
483 end
484
485 describe "vim when not using python_pep8_indent_multiline_string" do
486   before {
487     vim.command("set sw=4 ts=4 sts=4 et")
488     vim.command("unlet! g:python_pep8_indent_multiline_string")
489   }
490   it_behaves_like "multiline strings"
491 end
492
493 describe "vim when using python_pep8_indent_multiline_first=0" do
494   before {
495     vim.command("set sw=4 ts=4 sts=4 et")
496     vim.command("let g:python_pep8_indent_multiline_string=0")
497   }
498   it_behaves_like "multiline strings"
499 end
500
501 describe "vim when using python_pep8_indent_multiline_string=-1" do
502   before {
503     vim.command("set sw=4 ts=4 sts=4 et")
504     vim.command("let g:python_pep8_indent_multiline_string=-1")
505   }
506   it_behaves_like "multiline strings"
507 end
508
509 describe "vim when using python_pep8_indent_multiline_string=-2" do
510   before {
511     vim.command("set sw=4 ts=4 sts=4 et")
512     vim.command("let g:python_pep8_indent_multiline_string=-2")
513   }
514   it_behaves_like "multiline strings"
515 end
516
517 describe "vim for cython" do
518   before {
519     vim.command "enew"
520     vim.command "set ft=cython"
521     vim.command "runtime indent/python.vim"
522   }
523
524   describe "when using a cdef function definition" do
525       it "indents shiftwidth spaces" do
526           vim.feedkeys 'icdef long_function_name(\<CR>arg'
527           indent.should == shiftwidth * 2
528       end
529   end
530
531   describe "when using a cpdef function definition" do
532       it "indents shiftwidth spaces" do
533           vim.feedkeys 'icpdef long_function_name(\<CR>arg'
534           indent.should == shiftwidth * 2
535       end
536   end
537 end