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