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

Factor out is_dedented_already
[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 a 'for' is followed by" do
357      before { vim.feedkeys 'i\<TAB>\<TAB>for x in y:\<CR>' }
358      it "an 'else', it lines up with the 'for'" do
359         vim.feedkeys 'else:'
360         indent.should == shiftwidth * 2
361      end
362   end
363
364   describe "when an 'else' is followed by" do
365      before { vim.feedkeys 'i\<TAB>\<TAB>else:\<CR>XXX\<CR>' }
366      it "a 'finally', it lines up with the 'else'" do
367         vim.feedkeys 'finally:'
368         indent.should == shiftwidth * 2
369      end
370   end
371
372
373   describe "when a 'try' is followed by" do
374      before { vim.feedkeys 'i\<TAB>\<TAB>try:\<CR>' }
375      it "an 'except', it lines up with the 'try'" do
376         vim.feedkeys 'except:'
377         indent.should == shiftwidth * 2
378      end
379
380      it "an 'else', it lines up with the 'try'" do
381         vim.feedkeys 'else:'
382         indent.should == shiftwidth * 2
383      end
384
385      it "a 'finally', it lines up with the 'try'" do
386         vim.feedkeys 'finally:'
387         indent.should == shiftwidth * 2
388      end
389   end
390
391   describe "when an 'except' is followed by" do
392      before { vim.feedkeys 'i\<TAB>\<TAB>except:\<CR>' }
393      it "an 'else', it lines up with the 'except'" do
394         vim.feedkeys 'else:'
395         indent.should == shiftwidth * 2
396      end
397
398      it "another 'except', it lines up with the previous 'except'" do
399         vim.feedkeys 'except:'
400         indent.should == shiftwidth * 2
401      end
402
403      it "a 'finally', it lines up with the 'except'" do
404         vim.feedkeys 'finally:'
405         indent.should == shiftwidth * 2
406      end
407   end
408
409   describe "when jedi-vim call signatures are used" do
410     before { vim.command 'syn match jediFunction "JEDI_CALL_SIGNATURE" keepend extend' }
411
412     it "ignores the call signature after a colon" do
413       vim.feedkeys 'iif True:  JEDI_CALL_SIGNATURE\<CR>'
414       indent.should == shiftwidth
415     end
416
417     it "ignores the call signature after a function" do
418       vim.feedkeys 'idef f(  JEDI_CALL_SIGNATURE\<CR>'
419       indent.should == shiftwidth * 2
420     end
421   end
422
423   def shiftwidth
424     @shiftwidth ||= vim.echo("exists('*shiftwidth') ? shiftwidth() : &sw").to_i
425   end
426   def tabstop
427     @tabstop ||= vim.echo("&tabstop").to_i
428   end
429   def indent
430     vim.echo("indent('.')").to_i
431   end
432   def previous_indent
433     pline = vim.echo("line('.')").to_i - 1
434     vim.echo("indent('#{pline}')").to_i
435   end
436   def proposed_indent
437     line = vim.echo("line('.')")
438     col = vim.echo("col('.')")
439     indent_value = vim.echo("GetPythonPEPIndent(line('.'))").to_i
440     vim.command("call cursor(#{line}, #{col})")
441     return indent_value
442   end
443 end
444
445 describe "vim when using width of 4" do
446   before {
447     vim.command("set sw=4 ts=4 sts=4 et")
448   }
449
450   it_behaves_like "vim"
451 end
452
453 describe "vim when using width of 8" do
454   before {
455     vim.command("set sw=8 ts=8 sts=8 et")
456   }
457
458   it_behaves_like "vim"
459 end
460
461 describe "vim for cython" do
462   before {
463     vim.command "enew"
464     vim.command "set ft=cython"
465     vim.command "runtime indent/python.vim"
466   }
467
468   def shiftwidth
469     @shiftwidth ||= vim.echo("exists('*shiftwidth') ? shiftwidth() : &sw").to_i
470   end
471   def tabstop
472     @tabstop ||= vim.echo("&tabstop").to_i
473   end
474   def indent
475     vim.echo("indent('.')").to_i
476   end
477
478   describe "when using a cdef function definition" do
479       it "indents shiftwidth spaces" do
480           vim.feedkeys 'icdef long_function_name(\<CR>arg'
481           indent.should == shiftwidth * 2
482       end
483   end
484
485   describe "when using a cpdef function definition" do
486       it "indents shiftwidth spaces" do
487           vim.feedkeys 'icpdef long_function_name(\<CR>arg'
488           indent.should == shiftwidth * 2
489       end
490   end
491 end