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

Improve handling of lookup in previous lines
[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 after an '(' that is followed by an unfinished string" do
157     before { vim.feedkeys 'itest("""' }
158
159     it "it does not indent the next line" do
160       vim.feedkeys '\<CR>'
161       proposed_indent.should == 0
162       indent.should == 0
163     end
164
165     it "with contents it does not indent the next line" do
166       vim.feedkeys 'string_contents\<CR>'
167       proposed_indent.should == 0
168       indent.should == 0
169     end
170   end
171
172   describe "when after assigning an unfinished string" do
173     before { vim.feedkeys 'itest = """' }
174
175     it "it does not indent the next line" do
176       vim.feedkeys '\<CR>'
177       proposed_indent.should == 0
178       indent.should == 0
179     end
180   end
181
182   describe "when after assigning an unfinished string" do
183     before { vim.feedkeys 'i    test = """' }
184
185     it "it does not indent the next line" do
186       vim.feedkeys '\<CR>'
187       proposed_indent.should == 0
188       indent.should == 0
189     end
190   end
191
192   describe "when after assigning a finished string" do
193     before { vim.feedkeys 'i    test = ""' }
194
195     it "it does indent the next line" do
196       vim.feedkeys '\<CR>'
197       proposed_indent.should == 4
198       indent.should == 4
199     end
200
201     it "and writing a new string, it does indent the next line" do
202       vim.feedkeys '\<CR>""'
203       proposed_indent.should == 4
204       indent.should == 4
205     end
206   end
207
208   describe "when after a docstring" do
209     before { vim.feedkeys 'i    """' }
210
211     it "it does indent the next line" do
212       vim.feedkeys '\<CR>'
213       proposed_indent.should == 4
214       indent.should == 4
215     end
216   end
217
218   describe "when using simple control structures" do
219       it "indents shiftwidth spaces" do
220           vim.feedkeys 'iwhile True:\<CR>pass'
221           indent.should == shiftwidth
222       end
223   end
224
225   describe "when using a function definition" do
226       it "indents shiftwidth spaces" do
227           vim.feedkeys 'idef long_function_name(\<CR>arg'
228           indent.should == shiftwidth * 2
229       end
230   end
231
232   describe "when using a class definition" do
233       it "indents shiftwidth spaces" do
234           vim.feedkeys 'iclass Foo(\<CR>'
235           indent.should == shiftwidth * 2
236       end
237   end
238
239   describe "when writing an 'else' block" do
240     it "aligns to the preceeding 'for' block" do
241       vim.feedkeys 'ifor x in "abc":\<CR>pass\<CR>else:'
242       indent.should == 0
243     end
244
245     it "aligns to the preceeding 'if' block" do
246       vim.feedkeys 'ifor x in "abc":\<CR>if True:\<CR>pass\<CR>else:'
247       indent.should == shiftwidth
248     end
249   end
250
251   describe "when using parens and control statements" do
252     it "avoids ambiguity by using extra indentation" do
253       vim.feedkeys 'iif (111 and\<CR>'
254       if shiftwidth == 4
255         indent.should == shiftwidth * 2
256       else
257         indent.should == 4
258       end
259       vim.feedkeys '222):\<CR>'
260       indent.should == shiftwidth
261       vim.feedkeys 'pass\<CR>'
262       indent.should == 0
263     end
264
265     it "still aligns parens properly if not ambiguous" do
266       vim.feedkeys 'iwhile (111 and\<CR>'
267       indent.should == 7
268       vim.feedkeys '222):\<CR>'
269       indent.should == shiftwidth
270       vim.feedkeys 'pass\<CR>'
271       indent.should == 0
272     end
273
274     it "still handles multiple parens correctly" do
275       vim.feedkeys 'iif (111 and (222 and 333\<CR>'
276       indent.should == 13
277       vim.feedkeys 'and 444\<CR>'
278       indent.should == 13
279       vim.feedkeys ')\<CR>'
280       if shiftwidth == 4
281         indent.should == shiftwidth * 2
282       else
283         indent.should == 4
284       end
285       vim.feedkeys 'and 555):\<CR>'
286       indent.should == shiftwidth
287       vim.feedkeys 'pass\<CR>'
288       indent.should == 0
289     end
290   end
291
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
296     end
297
298     it "indents 2x shiftwidth spaces for control structures" do
299         vim.feedkeys 'iif somevalue == xyz and \\\\\<CR>'
300         indent.should == shiftwidth * 2
301     end
302
303     it "indents relative to line above" do
304         vim.feedkeys 'i\<TAB>value = test + \\\\\<CR>'
305         indent.should == shiftwidth * 2
306     end
307   end
308
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
314      end
315
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
319      end
320
321      it "and current line has an invalid indentation" do
322         vim.feedkeys 'i    while True:\<CR>'
323         indent.should == previous_indent + shiftwidth
324      end
325   end
326
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
332      end
333   end
334
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
340      end
341
342      it "an 'else', it lines up with the 'if'" do
343         vim.feedkeys 'else:'
344         indent.should == shiftwidth * 2
345      end
346   end
347
348   describe "when a 'for' is followed by" do
349      before { vim.feedkeys 'i\<TAB>\<TAB>for x in y:\<CR>' }
350      it "an 'else', it lines up with the 'for'" do
351         vim.feedkeys 'else:'
352         indent.should == shiftwidth * 2
353      end
354   end
355
356   describe "when an 'else' is followed by" do
357      before { vim.feedkeys 'i\<TAB>\<TAB>else:\<CR>XXX\<CR>' }
358      it "a 'finally', it lines up with the 'else'" do
359         vim.feedkeys 'finally:'
360         indent.should == shiftwidth * 2
361      end
362   end
363
364
365   describe "when a 'try' is followed by" do
366      before { vim.feedkeys 'i\<TAB>\<TAB>try:\<CR>' }
367      it "an 'except', it lines up with the 'try'" do
368         vim.feedkeys 'except:'
369         indent.should == shiftwidth * 2
370      end
371
372      it "an 'else', it lines up with the 'try'" do
373         vim.feedkeys 'else:'
374         indent.should == shiftwidth * 2
375      end
376
377      it "a 'finally', it lines up with the 'try'" do
378         vim.feedkeys 'finally:'
379         indent.should == shiftwidth * 2
380      end
381   end
382
383   describe "when an 'except' is followed by" do
384      before { vim.feedkeys 'i\<TAB>\<TAB>except:\<CR>' }
385      it "an 'else', it lines up with the 'except'" do
386         vim.feedkeys 'else:'
387         indent.should == shiftwidth * 2
388      end
389
390      it "another 'except', it lines up with the previous 'except'" do
391         vim.feedkeys 'except:'
392         indent.should == shiftwidth * 2
393      end
394
395      it "a 'finally', it lines up with the 'except'" do
396         vim.feedkeys 'finally:'
397         indent.should == shiftwidth * 2
398      end
399   end
400
401   describe "when jedi-vim call signatures are used" do
402     before { vim.command 'syn match jediFunction "JEDI_CALL_SIGNATURE" keepend extend' }
403
404     it "ignores the call signature after a colon" do
405       vim.feedkeys 'iif True:  JEDI_CALL_SIGNATURE\<CR>'
406       indent.should == shiftwidth
407     end
408
409     it "ignores the call signature after a function" do
410       vim.feedkeys 'idef f(  JEDI_CALL_SIGNATURE\<CR>'
411       indent.should == shiftwidth * 2
412     end
413   end
414
415   def shiftwidth
416     @shiftwidth ||= vim.echo("exists('*shiftwidth') ? shiftwidth() : &sw").to_i
417   end
418   def tabstop
419     @tabstop ||= vim.echo("&tabstop").to_i
420   end
421   def indent
422     vim.echo("indent('.')").to_i
423   end
424   def previous_indent
425     pline = vim.echo("line('.')").to_i - 1
426     vim.echo("indent('#{pline}')").to_i
427   end
428   def proposed_indent
429     line = vim.echo("line('.')")
430     col = vim.echo("col('.')")
431     indent_value = vim.echo("GetPythonPEPIndent(line('.'))").to_i
432     vim.command("call cursor(#{line}, #{col})")
433     return indent_value
434   end
435 end
436
437 describe "vim when using width of 4" do
438   before {
439     vim.command("set sw=4 ts=4 sts=4 et")
440   }
441
442   it_behaves_like "vim"
443 end
444
445 describe "vim when using width of 8" do
446   before {
447     vim.command("set sw=8 ts=8 sts=8 et")
448   }
449
450   it_behaves_like "vim"
451 end