]> 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:

Indent empty lines inside blocks (#81)
[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 line is empty inside a block" do
165     it "is indented like the previous line" do
166       vim.feedkeys 'idef a():\<CR>1\<CR>\<CR>2\<ESC>kcc'
167       indent.should == shiftwidth
168     end
169   end
170
171   describe "when line is empty inside a block following multi-line statement" do
172     it "is indented like the previous line" do
173       vim.feedkeys 'idef a():\<CR>x = (1 +\<CR>2)\<CR>\<CR>y\<ESC>kcc'
174       indent.should == shiftwidth
175     end
176   end
177
178   describe "when line is empty inside a block following stop statement" do
179     it "is indented like the previous line minus shiftwidth" do
180       vim.feedkeys 'iif x:\<CR>if y:\<CR>pass\<CR>\<CR>z\<ESC>kcc'
181       indent.should == shiftwidth
182     end
183   end
184
185   describe "when using simple control structures" do
186       it "indents shiftwidth spaces" do
187           vim.feedkeys 'iwhile True:\<CR>pass'
188           indent.should == shiftwidth
189       end
190   end
191
192   describe "when using a function definition" do
193       it "indents shiftwidth spaces" do
194           vim.feedkeys 'idef long_function_name(\<CR>arg'
195           indent.should == shiftwidth * 2
196       end
197   end
198
199   describe "when using a class definition" do
200       it "indents shiftwidth spaces" do
201           vim.feedkeys 'iclass Foo(\<CR>'
202           indent.should == shiftwidth * 2
203       end
204   end
205
206   describe "when writing an 'else' block" do
207     it "aligns to the preceeding 'for' block" do
208       vim.feedkeys 'ifor x in "abc":\<CR>pass\<CR>else:'
209       indent.should == 0
210     end
211
212     it "aligns to the preceeding 'if' block" do
213       vim.feedkeys 'ifor x in "abc":\<CR>if True:\<CR>pass\<CR>else:'
214       indent.should == shiftwidth
215     end
216   end
217
218   describe "when using parens and control statements" do
219     it "avoids ambiguity by using extra indentation" do
220       vim.feedkeys 'iif (111 and\<CR>'
221       if shiftwidth == 4
222         indent.should == shiftwidth * 2
223       else
224         indent.should == 4
225       end
226       vim.feedkeys '222):\<CR>'
227       indent.should == shiftwidth
228       vim.feedkeys 'pass\<CR>'
229       indent.should == 0
230     end
231
232     it "still aligns parens properly if not ambiguous" do
233       vim.feedkeys 'iwhile (111 and\<CR>'
234       indent.should == 7
235       vim.feedkeys '222):\<CR>'
236       indent.should == shiftwidth
237       vim.feedkeys 'pass\<CR>'
238       indent.should == 0
239     end
240
241     it "still handles multiple parens correctly" do
242       vim.feedkeys 'iif (111 and (222 and 333\<CR>'
243       indent.should == 13
244       vim.feedkeys 'and 444\<CR>'
245       indent.should == 13
246       vim.feedkeys ')\<CR>'
247       if shiftwidth == 4
248         indent.should == shiftwidth * 2
249       else
250         indent.should == 4
251       end
252       vim.feedkeys 'and 555):\<CR>'
253       indent.should == shiftwidth
254       vim.feedkeys 'pass\<CR>'
255       indent.should == 0
256     end
257   end
258
259   describe "when a line breaks with a manual '\\'" do
260     it "indents shiftwidth spaces on normal line" do
261         vim.feedkeys 'ivalue = test + \\\\\<CR>'
262         indent.should == shiftwidth
263     end
264
265     it "indents 2x shiftwidth spaces for control structures" do
266         vim.feedkeys 'iif somevalue == xyz and \\\\\<CR>'
267         indent.should == shiftwidth * 2
268     end
269
270     it "indents relative to line above" do
271         vim.feedkeys 'i\<TAB>value = test + \\\\\<CR>'
272         indent.should == shiftwidth * 2
273     end
274   end
275
276   describe "when current line is dedented compared to previous line" do
277      before { vim.feedkeys 'i\<TAB>\<TAB>if x:\<CR>y = True\<CR>\<ESC>' }
278      it "and current line has a valid indentation (Part 1)" do
279         vim.feedkeys '0i\<TAB>if y:'
280         proposed_indent.should == -1
281      end
282
283      it "and current line has a valid indentation (Part 2)" do
284         vim.feedkeys '0i\<TAB>\<TAB>if y:'
285         proposed_indent.should == -1
286      end
287
288      it "and current line has an invalid indentation" do
289         vim.feedkeys 'i    while True:\<CR>'
290         indent.should == previous_indent + shiftwidth
291      end
292   end
293
294   describe "when current line is dedented compared to the last non-empty line" do
295      before { vim.feedkeys 'i\<TAB>\<TAB>if x:\<CR>y = True\<CR>\<CR>\<ESC>' }
296      it "and current line has a valid indentation" do
297         vim.feedkeys '0i\<TAB>if y:'
298         proposed_indent.should == -1
299      end
300   end
301
302   describe "when an 'if' is followed by" do
303      before { vim.feedkeys 'i\<TAB>\<TAB>if x:\<CR>' }
304      it "an elif, it lines up with the 'if'" do
305         vim.feedkeys 'elif y:'
306         indent.should == shiftwidth * 2
307      end
308
309      it "an 'else', it lines up with the 'if'" do
310         vim.feedkeys 'else:'
311         indent.should == shiftwidth * 2
312      end
313   end
314
315   describe "when an 'if' contains a try-except" do
316      before {
317        vim.feedkeys 'iif x:\<CR>try:\<CR>pass\<CR>except:\<CR>pass\<CR>'
318        indent.should == shiftwidth
319      }
320      it "an 'else' should be indented to the try" do
321        vim.feedkeys 'else:'
322        indent.should == shiftwidth
323        proposed_indent.should == shiftwidth
324      end
325      it "an 'else' should keep the indent of the 'if'" do
326        vim.feedkeys 'else:\<ESC><<'
327        indent.should == 0
328        proposed_indent.should == 0
329      end
330   end
331
332   describe "when a 'for' is followed by" do
333      before { vim.feedkeys 'i\<TAB>\<TAB>for x in y:\<CR>' }
334      it "an 'else', it lines up with the 'for'" do
335         vim.feedkeys 'else:'
336         indent.should == shiftwidth * 2
337      end
338   end
339
340   describe "when an 'else' is followed by" do
341      before { vim.feedkeys 'i\<TAB>\<TAB>else:\<CR>XXX\<CR>' }
342      it "a 'finally', it lines up with the 'else'" do
343         vim.feedkeys 'finally:'
344         indent.should == shiftwidth * 2
345      end
346   end
347
348
349   describe "when a 'try' is followed by" do
350      before { vim.feedkeys 'i\<TAB>\<TAB>try:\<CR>' }
351      it "an 'except', it lines up with the 'try'" do
352         vim.feedkeys 'except:'
353         indent.should == shiftwidth * 2
354      end
355
356      it "an 'else', it lines up with the 'try'" do
357         vim.feedkeys 'else:'
358         indent.should == shiftwidth * 2
359      end
360
361      it "a 'finally', it lines up with the 'try'" do
362         vim.feedkeys 'finally:'
363         indent.should == shiftwidth * 2
364      end
365   end
366
367   describe "when an 'except' is followed by" do
368      before { vim.feedkeys 'i\<TAB>\<TAB>except:\<CR>' }
369      it "an 'else', it lines up with the 'except'" do
370         vim.feedkeys 'else:'
371         indent.should == shiftwidth * 2
372      end
373
374      it "another 'except', it lines up with the previous 'except'" do
375         vim.feedkeys 'except:'
376         indent.should == shiftwidth * 2
377      end
378
379      it "a 'finally', it lines up with the 'except'" do
380         vim.feedkeys 'finally:'
381         indent.should == shiftwidth * 2
382      end
383   end
384
385   describe "when an else is used inside of a nested if" do
386     before { vim.feedkeys 'iif foo:\<CR>\<TAB>if bar:\<CR>\<TAB>\<TAB>pass\<CR>' }
387     it "indents an else to the inner if" do
388       vim.feedkeys 'else:'
389       indent.should == shiftwidth * 2
390     end
391   end
392
393   describe "when jedi-vim call signatures are used" do
394     before { vim.command 'syn match jediFunction "JEDI_CALL_SIGNATURE" keepend extend' }
395
396     it "ignores the call signature after a colon" do
397       vim.feedkeys 'iif True:  JEDI_CALL_SIGNATURE\<CR>'
398       indent.should == shiftwidth
399     end
400
401     it "ignores the call signature after a function" do
402       vim.feedkeys 'idef f(  JEDI_CALL_SIGNATURE\<CR>'
403       indent.should == shiftwidth * 2
404     end
405   end
406 end
407
408 shared_examples_for "multiline strings" do
409   describe "when after an '(' that is followed by an unfinished string" do
410     before { vim.feedkeys 'itest("""' }
411
412     it "it indents the next line" do
413       vim.feedkeys '\<CR>'
414       expected_proposed, expected_indent = multiline_indent(0, shiftwidth)
415       proposed_indent.should == expected_proposed
416       indent.should == expected_indent
417     end
418
419     it "with contents it indents the second line to the parenthesis" do
420       vim.feedkeys 'second line\<CR>'
421       expected_proposed, expected_indent = multiline_indent(0, 5)
422       proposed_indent.should == expected_proposed
423       indent.should == expected_indent
424     end
425   end
426
427   describe "when after assigning an unfinished string" do
428     before { vim.feedkeys 'itest = """' }
429
430     it "it indents the next line" do
431       vim.feedkeys '\<CR>'
432       expected_proposed, expected_indent = multiline_indent(0, shiftwidth)
433       proposed_indent.should == expected_proposed
434       indent.should == expected_indent
435     end
436   end
437
438   describe "when after assigning an unfinished string" do
439     before { vim.feedkeys 'i    test = """' }
440
441     it "it indents the next line" do
442       vim.feedkeys '\<CR>'
443       expected_proposed, expected_indent = multiline_indent(4, shiftwidth + 4)
444       proposed_indent.should == expected_proposed
445       indent.should == expected_indent
446     end
447   end
448
449   describe "when after assigning a finished string" do
450     before { vim.feedkeys 'i    test = ""' }
451
452     it "it does indent the next line" do
453       vim.feedkeys '\<CR>'
454       indent.should == 4
455     end
456
457     it "and writing a new string, it does indent the next line" do
458       vim.feedkeys '\<CR>""'
459       indent.should == 4
460     end
461   end
462
463   describe "when after a docstring" do
464     before { vim.feedkeys 'i    """' }
465     it "it does indent the next line to the docstring" do
466       vim.feedkeys '\<CR>'
467       indent.should == 4
468       proposed_indent.should == 4
469     end
470   end
471
472   describe "when after a docstring with contents" do
473     before { vim.feedkeys 'i    """First line' }
474     it "it does indent the next line to the docstring" do
475       vim.feedkeys '\<CR>'
476       indent.should == 4
477       proposed_indent.should == 4
478     end
479   end
480
481   describe "when breaking a string after opening parenthesis" do
482     before { vim.feedkeys 'i    foo("""bar<Left><Left><Left>' }
483     it "it does indent the next line as after an opening multistring" do
484       vim.feedkeys '\<CR>'
485       expected_proposed, expected_indent = multiline_indent(4, 4 + shiftwidth)
486       indent.should == expected_indent
487       proposed_indent.should == expected_proposed
488     end
489   end
490 end
491
492 describe "vim when using width of 4" do
493   before {
494     vim.command("set sw=4 ts=4 sts=4 et")
495   }
496   it_behaves_like "vim"
497 end
498
499 describe "vim when using width of 3" do
500   before {
501     vim.command("set sw=3 ts=3 sts=3 et")
502   }
503   it_behaves_like "vim"
504 end
505
506 describe "vim when not using python_pep8_indent_multiline_string" do
507   before {
508     vim.command("set sw=4 ts=4 sts=4 et")
509     vim.command("unlet! g:python_pep8_indent_multiline_string")
510   }
511   it_behaves_like "multiline strings"
512 end
513
514 describe "vim when using python_pep8_indent_multiline_first=0" do
515   before {
516     vim.command("set sw=4 ts=4 sts=4 et")
517     vim.command("let g:python_pep8_indent_multiline_string=0")
518   }
519   it_behaves_like "multiline strings"
520 end
521
522 describe "vim when using python_pep8_indent_multiline_string=-1" do
523   before {
524     vim.command("set sw=4 ts=4 sts=4 et")
525     vim.command("let g:python_pep8_indent_multiline_string=-1")
526   }
527   it_behaves_like "multiline strings"
528 end
529
530 describe "vim when using python_pep8_indent_multiline_string=-2" do
531   before {
532     vim.command("set sw=4 ts=4 sts=4 et")
533     vim.command("let g:python_pep8_indent_multiline_string=-2")
534   }
535   it_behaves_like "multiline strings"
536 end
537
538 describe "vim for cython" do
539   before {
540     vim.command "enew"
541     vim.command "set ft=cython"
542     vim.command "runtime indent/python.vim"
543   }
544
545   describe "when using a cdef function definition" do
546       it "indents shiftwidth spaces" do
547           vim.feedkeys 'icdef long_function_name(\<CR>arg'
548           indent.should == shiftwidth * 2
549       end
550   end
551
552   describe "when using a cpdef function definition" do
553       it "indents shiftwidth spaces" do
554           vim.feedkeys 'icpdef long_function_name(\<CR>arg'
555           indent.should == shiftwidth * 2
556       end
557   end
558 end