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

Merge pull request #42 from blueyed/more-indent-function-def
[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 using gq to reindent a '(' that is" do
80     before { vim.feedkeys 'itest(' }
81     it "something and has a string without spaces at the end" do
82       vim.feedkeys 'something_very_long_blaaaaaaaaa, "some_very_long_string_blaaaaaaaaaaaaaaaaaaaa"\<esc>gqq'
83       indent.should == 5
84     end
85   end
86
87   describe "when after multiple parens of different types" do
88     it "indents by one level" do
89       vim.feedkeys 'if({\<CR>'
90       indent.should == shiftwidth
91     end
92
93     it "lines up with the last paren" do
94       vim.feedkeys 'ifff({123: 456,\<CR>'
95       indent.should == 5
96     end
97   end
98
99   describe "when '#' is contained in a string that is followed by a colon" do
100     it "indents by one level" do
101         vim.feedkeys 'iif "some#thing" == "test":#test\<CR>pass'
102         indent.should == shiftwidth
103     end
104   end
105
106   describe "when '#' is not contained in a string and is followed by a colon" do
107     it "does not indent" do
108         vim.feedkeys 'iif "some#thing" == "test"#:test\<CR>'
109         indent.should == 0
110     end
111   end
112
113   describe "when inside an unfinished string" do
114     it "does not indent" do
115       vim.feedkeys 'i"test:\<ESC>'
116       vim.echo('synIDattr(synID(line("."), col("."), 0), "name")'
117               ).downcase.should include 'string'
118       vim.feedkeys 'a\<CR>'
119       proposed_indent.should == 0
120       indent.should == 0
121     end
122
123     it "does not dedent" do
124       vim.feedkeys 'iif True:\<CR>"test:\<ESC>'
125       vim.echo('synIDattr(synID(line("."), col("."), 0), "name")'
126               ).downcase.should include 'string'
127       proposed_indent.should == shiftwidth
128       indent.should == shiftwidth
129     end
130   end
131
132   describe "when after an '(' that is followed by an unfinished string" do
133     before { vim.feedkeys 'itest("""' }
134
135     it "it does not indent the next line" do
136       vim.feedkeys '\<CR>'
137       proposed_indent.should == 0
138       indent.should == 0
139     end
140
141     it "with contents it does not indent the next line" do
142       vim.feedkeys 'string_contents\<CR>'
143       proposed_indent.should == 0
144       indent.should == 0
145     end
146   end
147
148   describe "when after assigning an unfinished string" do
149     before { vim.feedkeys 'itest = """' }
150
151     it "it does not indent the next line" do
152       vim.feedkeys '\<CR>'
153       proposed_indent.should == 0
154       indent.should == 0
155     end
156   end
157
158   describe "when after assigning an unfinished string" do
159     before { vim.feedkeys 'i    test = """' }
160
161     it "it does not indent the next line" do
162       vim.feedkeys '\<CR>'
163       proposed_indent.should == 0
164       indent.should == 0
165     end
166   end
167
168   describe "when after assigning a finished string" do
169     before { vim.feedkeys 'i    test = ""' }
170
171     it "it does indent the next line" do
172       vim.feedkeys '\<CR>'
173       proposed_indent.should == 4
174       indent.should == 4
175     end
176
177     it "and writing a new string, it does indent the next line" do
178       vim.feedkeys '\<CR>""'
179       proposed_indent.should == 4
180       indent.should == 4
181     end
182   end
183
184   describe "when after a docstring" do
185     before { vim.feedkeys 'i    """' }
186
187     it "it does indent the next line" do
188       vim.feedkeys '\<CR>'
189       proposed_indent.should == 4
190       indent.should == 4
191     end
192   end
193
194   describe "when using simple control structures" do
195       it "indents shiftwidth spaces" do
196           vim.feedkeys 'iwhile True:\<CR>pass'
197           indent.should == shiftwidth
198       end
199   end
200
201   describe "when using a function definition" do
202       it "indents shiftwidth spaces" do
203           vim.feedkeys 'idef long_function_name(\<CR>arg'
204           indent.should == shiftwidth * 2
205       end
206   end
207
208   describe "when using a class definition" do
209       it "indents shiftwidth spaces" do
210           vim.feedkeys 'iclass Foo(\<CR>'
211           indent.should == shiftwidth * 2
212       end
213   end
214
215   describe "when writing an 'else' block" do
216     it "aligns to the preceeding 'for' block" do
217       vim.feedkeys 'ifor x in "abc":\<CR>pass\<CR>else:'
218       indent.should == 0
219     end
220
221     it "aligns to the preceeding 'if' block" do
222       vim.feedkeys 'ifor x in "abc":\<CR>if True:\<CR>pass\<CR>else:'
223       indent.should == shiftwidth
224     end
225   end
226
227   describe "when using parens and control statements" do
228     it "avoids ambiguity by using extra indentation" do
229       vim.feedkeys 'iif (111 and\<CR>'
230       if shiftwidth == 4
231         indent.should == shiftwidth * 2
232       else
233         indent.should == 4
234       end
235       vim.feedkeys '222):\<CR>'
236       indent.should == shiftwidth
237       vim.feedkeys 'pass\<CR>'
238       indent.should == 0
239     end
240
241     it "still aligns parens properly if not ambiguous" do
242       vim.feedkeys 'iwhile (111 and\<CR>'
243       indent.should == 7
244       vim.feedkeys '222):\<CR>'
245       indent.should == shiftwidth
246       vim.feedkeys 'pass\<CR>'
247       indent.should == 0
248     end
249
250     it "still handles multiple parens correctly" do
251       vim.feedkeys 'iif (111 and (222 and 333\<CR>'
252       indent.should == 13
253       vim.feedkeys 'and 444\<CR>'
254       indent.should == 13
255       vim.feedkeys ')\<CR>'
256       if shiftwidth == 4
257         indent.should == shiftwidth * 2
258       else
259         indent.should == 4
260       end
261       vim.feedkeys 'and 555):\<CR>'
262       indent.should == shiftwidth
263       vim.feedkeys 'pass\<CR>'
264       indent.should == 0
265     end
266   end
267
268   describe "when a line breaks with a manual '\\'" do
269     it "indents shiftwidth spaces on normal line" do
270         vim.feedkeys 'ivalue = test + \\\\\<CR>'
271         indent.should == shiftwidth
272     end
273
274     it "indents 2x shiftwidth spaces for control structures" do
275         vim.feedkeys 'iif somevalue == xyz and \\\\\<CR>'
276         indent.should == shiftwidth * 2
277     end
278
279     it "indents relative to line above" do
280         vim.feedkeys 'i\<TAB>value = test + \\\\\<CR>'
281         indent.should == shiftwidth * 2
282     end
283   end
284
285   describe "when current line is dedented compared to previous line" do
286      before { vim.feedkeys 'i\<TAB>\<TAB>if x:\<CR>y = True\<CR>\<ESC>' }
287      it "and current line has a valid indentation (Part 1)" do
288         vim.feedkeys '0i\<TAB>if y:'
289         proposed_indent.should == -1
290      end
291
292      it "and current line has a valid indentation (Part 2)" do
293         vim.feedkeys '0i\<TAB>\<TAB>if y:'
294         proposed_indent.should == -1
295      end
296
297      it "and current line has an invalid indentation" do
298         vim.feedkeys 'i    while True:\<CR>'
299         indent.should == previous_indent + shiftwidth
300      end
301   end
302
303   describe "when current line is dedented compared to the last non-empty line" do
304      before { vim.feedkeys 'i\<TAB>\<TAB>if x:\<CR>y = True\<CR>\<CR>\<ESC>' }
305      it "and current line has a valid indentation" do
306         vim.feedkeys '0i\<TAB>if y:'
307         proposed_indent.should == -1
308      end
309   end
310
311   describe "when an 'if' is followed by" do
312      before { vim.feedkeys 'i\<TAB>\<TAB>if x:\<CR>' }
313      it "an elif, it lines up with the 'if'" do
314         vim.feedkeys 'elif y:'
315         indent.should == shiftwidth * 2
316      end
317
318      it "an 'else', it lines up with the 'if'" do
319         vim.feedkeys 'else:'
320         indent.should == shiftwidth * 2
321      end
322   end
323
324   describe "when a 'for' is followed by" do
325      before { vim.feedkeys 'i\<TAB>\<TAB>for x in y:\<CR>' }
326      it "an 'else', it lines up with the 'for'" do
327         vim.feedkeys 'else:'
328         indent.should == shiftwidth * 2
329      end
330   end
331
332   describe "when an 'else' is followed by" do
333      before { vim.feedkeys 'i\<TAB>\<TAB>else:\<CR>XXX\<CR>' }
334      it "a 'finally', it lines up with the 'else'" do
335         vim.feedkeys 'finally:'
336         indent.should == shiftwidth * 2
337      end
338   end
339
340
341   describe "when a 'try' is followed by" do
342      before { vim.feedkeys 'i\<TAB>\<TAB>try:\<CR>' }
343      it "an 'except', it lines up with the 'try'" do
344         vim.feedkeys 'except:'
345         indent.should == shiftwidth * 2
346      end
347
348      it "an 'else', it lines up with the 'try'" do
349         vim.feedkeys 'else:'
350         indent.should == shiftwidth * 2
351      end
352
353      it "a 'finally', it lines up with the 'try'" do
354         vim.feedkeys 'finally:'
355         indent.should == shiftwidth * 2
356      end
357   end
358
359   describe "when an 'except' is followed by" do
360      before { vim.feedkeys 'i\<TAB>\<TAB>except:\<CR>' }
361      it "an 'else', it lines up with the 'except'" do
362         vim.feedkeys 'else:'
363         indent.should == shiftwidth * 2
364      end
365
366      it "another 'except', it lines up with the previous 'except'" do
367         vim.feedkeys 'except:'
368         indent.should == shiftwidth * 2
369      end
370
371      it "a 'finally', it lines up with the 'except'" do
372         vim.feedkeys 'finally:'
373         indent.should == shiftwidth * 2
374      end
375   end
376
377   def shiftwidth
378     @shiftwidth ||= vim.echo("exists('*shiftwidth') ? shiftwidth() : &sw").to_i
379   end
380   def tabstop
381     @tabstop ||= vim.echo("&tabstop").to_i
382   end
383   def indent
384     vim.echo("indent('.')").to_i
385   end
386   def previous_indent
387     pline = vim.echo("line('.')").to_i - 1
388     vim.echo("indent('#{pline}')").to_i
389   end
390   def proposed_indent
391     line = vim.echo("line('.')")
392     col = vim.echo("col('.')")
393     indent_value = vim.echo("GetPythonPEPIndent(line('.'))").to_i
394     vim.command("call cursor(#{line}, #{col})")
395     return indent_value
396   end
397 end
398
399 describe "vim when using width of 4" do
400   before {
401     vim.command("set sw=4 ts=4 sts=4 et")
402   }
403
404   it_behaves_like "vim"
405 end
406
407 describe "vim when using width of 8" do
408   before {
409     vim.command("set sw=8 ts=8 sts=8 et")
410   }
411
412   it_behaves_like "vim"
413 end