1" Tests for window cmd (:wincmd, :split, :vsplit, :resize and etc...)
2
3so check.vim
4
5func Test_window_cmd_ls0_with_split()
6  set ls=0
7  set splitbelow
8  split
9  quit
10  call assert_equal(0, &lines - &cmdheight - winheight(0))
11  new | only!
12  "
13  set splitbelow&vim
14  botright split
15  quit
16  call assert_equal(0, &lines - &cmdheight - winheight(0))
17  new | only!
18  set ls&vim
19endfunc
20
21func Test_window_cmd_cmdwin_with_vsp()
22  let efmt = 'Expected 0 but got %d (in ls=%d, %s window)'
23  for v in range(0, 2)
24    exec "set ls=" . v
25    vsplit
26    call feedkeys("q:\<CR>")
27    let ac = &lines - (&cmdheight + winheight(0) + !!v)
28    let emsg = printf(efmt, ac, v, 'left')
29    call assert_equal(0, ac, emsg)
30    wincmd w
31    let ac = &lines - (&cmdheight + winheight(0) + !!v)
32    let emsg = printf(efmt, ac, v, 'right')
33    call assert_equal(0, ac, emsg)
34    new | only!
35  endfor
36  set ls&vim
37endfunc
38
39function Test_window_cmd_wincmd_gf()
40  let fname = 'test_gf.txt'
41  let swp_fname = '.' . fname . '.swp'
42  call writefile([], fname)
43  call writefile([], swp_fname)
44  function s:swap_exists()
45    let v:swapchoice = s:swap_choice
46  endfunc
47  " Remove the catch-all that runtest.vim adds
48  au! SwapExists
49  augroup test_window_cmd_wincmd_gf
50    autocmd!
51    exec "autocmd SwapExists " . fname . " call s:swap_exists()"
52  augroup END
53
54  call setline(1, fname)
55  " (E)dit anyway
56  let s:swap_choice = 'e'
57  wincmd gf
58  call assert_equal(2, tabpagenr())
59  call assert_equal(fname, bufname("%"))
60  quit!
61
62  " (Q)uit
63  let s:swap_choice = 'q'
64  wincmd gf
65  call assert_equal(1, tabpagenr())
66  call assert_notequal(fname, bufname("%"))
67  new | only!
68
69  call delete(fname)
70  call delete(swp_fname)
71  augroup! test_window_cmd_wincmd_gf
72endfunc
73
74func Test_window_quit()
75  e Xa
76  split Xb
77  call assert_equal(2, '$'->winnr())
78  call assert_equal('Xb', bufname(winbufnr(1)))
79  call assert_equal('Xa', bufname(winbufnr(2)))
80
81  wincmd q
82  call assert_equal(1, winnr('$'))
83  call assert_equal('Xa', bufname(winbufnr(1)))
84
85  bw Xa Xb
86endfunc
87
88func Test_window_horizontal_split()
89  call assert_equal(1, winnr('$'))
90  3wincmd s
91  call assert_equal(2, winnr('$'))
92  call assert_equal(3, winheight(0))
93  call assert_equal(winwidth(1), 2->winwidth())
94
95  call assert_fails('botright topleft wincmd s', 'E442:')
96  bw
97endfunc
98
99func Test_window_vertical_split()
100  call assert_equal(1, winnr('$'))
101  3wincmd v
102  call assert_equal(2, winnr('$'))
103  call assert_equal(3, winwidth(0))
104  call assert_equal(winheight(1), winheight(2))
105
106  call assert_fails('botright topleft wincmd v', 'E442:')
107  bw
108endfunc
109
110" Test the ":wincmd ^" and "<C-W>^" commands.
111func Test_window_split_edit_alternate()
112
113  " Test for failure when the alternate buffer/file no longer exists.
114  edit Xfoo | %bw
115  call assert_fails(':wincmd ^', 'E23')
116
117  " Test for the expected behavior when we have two named buffers.
118  edit Xfoo | edit Xbar
119  wincmd ^
120  call assert_equal('Xfoo', bufname(winbufnr(1)))
121  call assert_equal('Xbar', bufname(winbufnr(2)))
122  only
123
124  " Test for the expected behavior when the alternate buffer is not named.
125  enew | let l:nr1 = bufnr('%')
126  edit Xfoo | let l:nr2 = bufnr('%')
127  wincmd ^
128  call assert_equal(l:nr1, winbufnr(1))
129  call assert_equal(l:nr2, winbufnr(2))
130  only
131
132  " FIXME: this currently fails on AppVeyor, but passes locally
133  if !has('win32')
134    " Test the Normal mode command.
135    call feedkeys("\<C-W>\<C-^>", 'tx')
136    call assert_equal(l:nr2, winbufnr(1))
137    call assert_equal(l:nr1, winbufnr(2))
138  endif
139
140  %bw!
141endfunc
142
143" Test the ":[count]wincmd ^" and "[count]<C-W>^" commands.
144func Test_window_split_edit_bufnr()
145
146  %bwipeout
147  let l:nr = bufnr('%') + 1
148  call assert_fails(':execute "normal! ' . l:nr . '\<C-W>\<C-^>"', 'E92')
149  call assert_fails(':' . l:nr . 'wincmd ^', 'E16')
150  call assert_fails(':0wincmd ^', 'E16')
151
152  edit Xfoo | edit Xbar | edit Xbaz
153  let l:foo_nr = bufnr('Xfoo')
154  let l:bar_nr = bufnr('Xbar')
155  let l:baz_nr = bufnr('Xbaz')
156
157  " FIXME: this currently fails on AppVeyor, but passes locally
158  if !has('win32')
159    call feedkeys(l:foo_nr . "\<C-W>\<C-^>", 'tx')
160    call assert_equal('Xfoo', bufname(winbufnr(1)))
161    call assert_equal('Xbaz', bufname(winbufnr(2)))
162    only
163
164    call feedkeys(l:bar_nr . "\<C-W>\<C-^>", 'tx')
165    call assert_equal('Xbar', bufname(winbufnr(1)))
166    call assert_equal('Xfoo', bufname(winbufnr(2)))
167    only
168
169    execute l:baz_nr . 'wincmd ^'
170    call assert_equal('Xbaz', bufname(winbufnr(1)))
171    call assert_equal('Xbar', bufname(winbufnr(2)))
172  endif
173
174  %bw!
175endfunc
176
177func Test_window_split_no_room()
178  " N horizontal windows need >= 2*N + 1 lines:
179  " - 1 line + 1 status line in each window
180  " - 1 Ex command line
181  "
182  " 2*N + 1 <= &lines
183  " N <= (lines - 1)/2
184  "
185  " Beyond that number of windows, E36: Not enough room is expected.
186  let hor_win_count = (&lines - 1)/2
187  let hor_split_count = hor_win_count - 1
188  for s in range(1, hor_split_count) | split | endfor
189  call assert_fails('split', 'E36:')
190
191  " N vertical windows need >= 2*(N - 1) + 1 columns:
192  " - 1 column + 1 separator for each window (except last window)
193  " - 1 column for the last window which does not have separator
194  "
195  " 2*(N - 1) + 1 <= &columns
196  " 2*N - 1 <= &columns
197  " N <= (&columns + 1)/2
198  let ver_win_count = (&columns + 1)/2
199  let ver_split_count = ver_win_count - 1
200  for s in range(1, ver_split_count) | vsplit | endfor
201  call assert_fails('vsplit', 'E36:')
202
203  %bw!
204endfunc
205
206func Test_window_exchange()
207  e Xa
208
209  " Nothing happens with window exchange when there is 1 window
210  wincmd x
211  call assert_equal(1, winnr('$'))
212
213  split Xb
214  split Xc
215
216  call assert_equal('Xc', bufname(winbufnr(1)))
217  call assert_equal('Xb', bufname(winbufnr(2)))
218  call assert_equal('Xa', bufname(winbufnr(3)))
219
220  " Exchange current window 1 with window 3
221  3wincmd x
222  call assert_equal('Xa', bufname(winbufnr(1)))
223  call assert_equal('Xb', bufname(winbufnr(2)))
224  call assert_equal('Xc', bufname(winbufnr(3)))
225
226  " Exchange window with next when at the top window
227  wincmd x
228  call assert_equal('Xb', bufname(winbufnr(1)))
229  call assert_equal('Xa', bufname(winbufnr(2)))
230  call assert_equal('Xc', bufname(winbufnr(3)))
231
232  " Exchange window with next when at the middle window
233  wincmd j
234  wincmd x
235  call assert_equal('Xb', bufname(winbufnr(1)))
236  call assert_equal('Xc', bufname(winbufnr(2)))
237  call assert_equal('Xa', bufname(winbufnr(3)))
238
239  " Exchange window with next when at the bottom window.
240  " When there is no next window, it exchanges with the previous window.
241  wincmd j
242  wincmd x
243  call assert_equal('Xb', bufname(winbufnr(1)))
244  call assert_equal('Xa', bufname(winbufnr(2)))
245  call assert_equal('Xc', bufname(winbufnr(3)))
246
247  bw Xa Xb Xc
248endfunc
249
250func Test_window_rotate()
251  e Xa
252  split Xb
253  split Xc
254  call assert_equal('Xc', bufname(winbufnr(1)))
255  call assert_equal('Xb', bufname(winbufnr(2)))
256  call assert_equal('Xa', bufname(winbufnr(3)))
257
258  " Rotate downwards
259  wincmd r
260  call assert_equal('Xa', bufname(winbufnr(1)))
261  call assert_equal('Xc', bufname(winbufnr(2)))
262  call assert_equal('Xb', bufname(winbufnr(3)))
263
264  2wincmd r
265  call assert_equal('Xc', bufname(winbufnr(1)))
266  call assert_equal('Xb', bufname(winbufnr(2)))
267  call assert_equal('Xa', bufname(winbufnr(3)))
268
269  " Rotate upwards
270  wincmd R
271  call assert_equal('Xb', bufname(winbufnr(1)))
272  call assert_equal('Xa', bufname(winbufnr(2)))
273  call assert_equal('Xc', bufname(winbufnr(3)))
274
275  2wincmd R
276  call assert_equal('Xc', bufname(winbufnr(1)))
277  call assert_equal('Xb', bufname(winbufnr(2)))
278  call assert_equal('Xa', bufname(winbufnr(3)))
279
280  bot vsplit
281  call assert_fails('wincmd R', 'E443:')
282
283  bw Xa Xb Xc
284endfunc
285
286func Test_window_height()
287  e Xa
288  split Xb
289
290  let [wh1, wh2] = [winheight(1), winheight(2)]
291  " Active window (1) should have the same height or 1 more
292  " than the other window.
293  call assert_inrange(wh2, wh2 + 1, wh1)
294
295  wincmd -
296  call assert_equal(wh1 - 1, winheight(1))
297  call assert_equal(wh2 + 1, winheight(2))
298
299  wincmd +
300  call assert_equal(wh1, winheight(1))
301  call assert_equal(wh2, 2->winheight())
302
303  2wincmd _
304  call assert_equal(2, winheight(1))
305  call assert_equal(wh1 + wh2 - 2, winheight(2))
306
307  wincmd =
308  call assert_equal(wh1, winheight(1))
309  call assert_equal(wh2, winheight(2))
310
311  2wincmd _
312  set winfixheight
313  split Xc
314  let [wh1, wh2, wh3] = [winheight(1), winheight(2), winheight(3)]
315  call assert_equal(2, winheight(2))
316  call assert_inrange(wh3, wh3 + 1, wh1)
317  3wincmd +
318  call assert_equal(2,       winheight(2))
319  call assert_equal(wh1 + 3, winheight(1))
320  call assert_equal(wh3 - 3, winheight(3))
321  wincmd =
322  call assert_equal(2,   winheight(2))
323  call assert_equal(wh1, winheight(1))
324  call assert_equal(wh3, winheight(3))
325
326  wincmd j
327  set winfixheight&
328
329  wincmd =
330  let [wh1, wh2, wh3] = [winheight(1), winheight(2), winheight(3)]
331  " Current window (2) should have the same height or 1 more
332  " than the other windows.
333  call assert_inrange(wh1, wh1 + 1, wh2)
334  call assert_inrange(wh3, wh3 + 1, wh2)
335
336  bw Xa Xb Xc
337endfunc
338
339func Test_window_width()
340  e Xa
341  vsplit Xb
342
343  let [ww1, ww2] = [winwidth(1), winwidth(2)]
344  " Active window (1) should have the same width or 1 more
345  " than the other window.
346  call assert_inrange(ww2, ww2 + 1, ww1)
347
348  wincmd <
349  call assert_equal(ww1 - 1, winwidth(1))
350  call assert_equal(ww2 + 1, winwidth(2))
351
352  wincmd >
353  call assert_equal(ww1, winwidth(1))
354  call assert_equal(ww2, winwidth(2))
355
356  2wincmd |
357  call assert_equal(2, winwidth(1))
358  call assert_equal(ww1 + ww2 - 2, winwidth(2))
359
360  wincmd =
361  call assert_equal(ww1, winwidth(1))
362  call assert_equal(ww2, winwidth(2))
363
364  2wincmd |
365  set winfixwidth
366  vsplit Xc
367  let [ww1, ww2, ww3] = [winwidth(1), winwidth(2), winwidth(3)]
368  call assert_equal(2, winwidth(2))
369  call assert_inrange(ww3, ww3 + 1, ww1)
370  3wincmd >
371  call assert_equal(2,       winwidth(2))
372  call assert_equal(ww1 + 3, winwidth(1))
373  call assert_equal(ww3 - 3, winwidth(3))
374  wincmd =
375  call assert_equal(2,   winwidth(2))
376  call assert_equal(ww1, winwidth(1))
377  call assert_equal(ww3, winwidth(3))
378
379  wincmd l
380  set winfixwidth&
381
382  wincmd =
383  let [ww1, ww2, ww3] = [winwidth(1), winwidth(2), winwidth(3)]
384  " Current window (2) should have the same width or 1 more
385  " than the other windows.
386  call assert_inrange(ww1, ww1 + 1, ww2)
387  call assert_inrange(ww3, ww3 + 1, ww2)
388
389  bw Xa Xb Xc
390endfunc
391
392func Test_equalalways_on_close()
393  set equalalways
394  vsplit
395  windo split
396  split
397  wincmd J
398  " now we have a frame top-left with two windows, a frame top-right with two
399  " windows and a frame at the bottom, full-width.
400  let height_1 = winheight(1)
401  let height_2 = winheight(2)
402  let height_3 = winheight(3)
403  let height_4 = winheight(4)
404  " closing the bottom window causes all windows to be resized.
405  close
406  call assert_notequal(height_1, winheight(1))
407  call assert_notequal(height_2, winheight(2))
408  call assert_notequal(height_3, winheight(3))
409  call assert_notequal(height_4, winheight(4))
410  call assert_equal(winheight(1), winheight(3))
411  call assert_equal(winheight(2), winheight(4))
412
413  1wincmd w
414  split
415  4wincmd w
416  resize + 5
417  " left column has three windows, equalized heights.
418  " right column has two windows, top one a bit higher
419  let height_1 = winheight(1)
420  let height_2 = winheight(2)
421  let height_4 = winheight(4)
422  let height_5 = winheight(5)
423  3wincmd w
424  " closing window in left column equalizes heights in left column but not in
425  " the right column
426  close
427  call assert_notequal(height_1, winheight(1))
428  call assert_notequal(height_2, winheight(2))
429  call assert_equal(height_4, winheight(3))
430  call assert_equal(height_5, winheight(4))
431
432  only
433  set equalalways&
434endfunc
435
436func Test_win_screenpos()
437  CheckFeature quickfix
438
439  call assert_equal(1, winnr('$'))
440  split
441  vsplit
442  10wincmd _
443  30wincmd |
444  call assert_equal([1, 1], win_screenpos(1))
445  call assert_equal([1, 32], win_screenpos(2))
446  call assert_equal([12, 1], win_screenpos(3))
447  call assert_equal([0, 0], win_screenpos(4))
448  only
449endfunc
450
451func Test_window_jump_tag()
452  CheckFeature quickfix
453
454  help
455  /iccf
456  call assert_match('^|iccf|',  getline('.'))
457  call assert_equal(2, winnr('$'))
458  2wincmd }
459  call assert_equal(3, winnr('$'))
460  call assert_match('^|iccf|',  getline('.'))
461  wincmd k
462  call assert_match('\*iccf\*',  getline('.'))
463  call assert_equal(2, winheight(0))
464
465  wincmd z
466  set previewheight=4
467  help
468  /bugs
469  wincmd }
470  wincmd k
471  call assert_match('\*bugs\*',  getline('.'))
472  call assert_equal(4, winheight(0))
473  set previewheight&
474
475  %bw!
476endfunc
477
478func Test_window_newtab()
479  e Xa
480
481  call assert_equal(1, tabpagenr('$'))
482  call assert_equal("\nAlready only one window", execute('wincmd T'))
483
484  split Xb
485  split Xc
486
487  wincmd T
488  call assert_equal(2, tabpagenr('$'))
489  call assert_equal(['Xb', 'Xa'], map(tabpagebuflist(1), 'bufname(v:val)'))
490  call assert_equal(['Xc'      ], map(2->tabpagebuflist(), 'bufname(v:val)'))
491  call assert_equal(['Xc'      ], map(tabpagebuflist(), 'bufname(v:val)'))
492
493  %bw!
494endfunc
495
496func Test_next_split_all()
497  " This was causing an illegal memory access.
498  n x
499  norm axxx
500  split
501  split
502  s/x
503  s/x
504  all
505  bwipe!
506endfunc
507
508" Tests for adjusting window and contents
509func GetScreenStr(row)
510   let str = ""
511   for c in range(1,3)
512       let str .= nr2char(screenchar(a:row, c))
513   endfor
514   return str
515endfunc
516
517func Test_window_contents()
518  enew! | only | new
519  call setline(1, range(1,256))
520
521  exe "norm! \<C-W>t\<C-W>=1Gzt\<C-W>w\<C-W>+"
522  redraw
523  let s3 = GetScreenStr(1)
524  wincmd p
525  call assert_equal(1, line("w0"))
526  call assert_equal('1  ', s3)
527
528  exe "norm! \<C-W>t\<C-W>=50Gzt\<C-W>w\<C-W>+"
529  redraw
530  let s3 = GetScreenStr(1)
531  wincmd p
532  call assert_equal(50, line("w0"))
533  call assert_equal('50 ', s3)
534
535  exe "norm! \<C-W>t\<C-W>=59Gzt\<C-W>w\<C-W>+"
536  redraw
537  let s3 = GetScreenStr(1)
538  wincmd p
539  call assert_equal(59, line("w0"))
540  call assert_equal('59 ', s3)
541
542  %d
543  call setline(1, ['one', 'two', 'three'])
544  call assert_equal(1, line('w0'))
545  call assert_equal(3, line('w$'))
546
547  bwipeout!
548  call test_garbagecollect_now()
549endfunc
550
551func Test_window_colon_command()
552  " This was reading invalid memory.
553  exe "norm! v\<C-W>:\<C-U>echo v:version"
554endfunc
555
556func Test_access_freed_mem()
557  call assert_equal(&columns, winwidth(0))
558  " This was accessing freed memory
559  au * 0 vs xxx
560  arg 0
561  argadd
562  call assert_fails("all", "E249:")
563  au!
564  bwipe xxx
565  call assert_equal(&columns, winwidth(0))
566endfunc
567
568func Test_insert_cleared_on_switch_to_term()
569  CheckFeature terminal
570
571  set showmode
572  terminal
573  wincmd p
574
575  call feedkeys("i\<C-O>", 'ntx')
576  redraw
577
578  " The "-- (insert) --" indicator should be visible.
579  let chars = map(range(1, &columns), 'nr2char(screenchar(&lines, v:val))')
580  let str = trim(join(chars, ''))
581  call assert_equal('-- (insert) --', str)
582
583  call feedkeys("\<C-W>p", 'ntx')
584  redraw
585
586  " The "-- (insert) --" indicator should have been cleared.
587  let chars = map(range(1, &columns), 'nr2char(screenchar(&lines, v:val))')
588  let str = trim(join(chars, ''))
589  call assert_equal('', str)
590
591  set showmode&
592  %bw!
593endfunc
594
595func Test_visual_cleared_after_window_split()
596  new | only!
597  let smd_save = &showmode
598  set showmode
599  let ls_save = &laststatus
600  set laststatus=1
601  call setline(1, ['a', 'b', 'c', 'd', ''])
602  norm! G
603  exe "norm! kkvk"
604  redraw
605  exe "norm! \<C-W>v"
606  redraw
607  " check if '-- VISUAL --' disappeared from command line
608  let columns = range(1, &columns)
609  let cmdlinechars = map(columns, 'nr2char(screenchar(&lines, v:val))')
610  let cmdline = join(cmdlinechars, '')
611  let cmdline_ltrim = substitute(cmdline, '^\s*', "", "")
612  let mode_shown = substitute(cmdline_ltrim, '\s*$', "", "")
613  call assert_equal('', mode_shown)
614  let &showmode = smd_save
615  let &laststatus = ls_save
616  bwipe!
617endfunc
618
619func Test_winrestcmd()
620  2split
621  3vsplit
622  let a = winrestcmd()
623  call assert_equal(2, winheight(0))
624  call assert_equal(3, winwidth(0))
625  wincmd =
626  call assert_notequal(2, winheight(0))
627  call assert_notequal(3, winwidth(0))
628  exe a
629  call assert_equal(2, winheight(0))
630  call assert_equal(3, winwidth(0))
631  only
632endfunc
633
634func Fun_RenewFile()
635  " Need to wait a bit for the timestamp to be older.
636  let old_ftime = getftime("tmp.txt")
637  while getftime("tmp.txt") == old_ftime
638    sleep 100m
639    silent execute '!echo "1" > tmp.txt'
640  endwhile
641  sp
642  wincmd p
643  edit! tmp.txt
644endfunc
645
646func Test_window_prevwin()
647  " Can we make this work on MS-Windows?
648  if !has('unix')
649    return
650  endif
651
652  set hidden autoread
653  call writefile(['2'], 'tmp.txt')
654  new tmp.txt
655  q
656  call Fun_RenewFile()
657  call assert_equal(2, winnr())
658  wincmd p
659  call assert_equal(1, winnr())
660  wincmd p
661  q
662  call Fun_RenewFile()
663  call assert_equal(2, winnr())
664  wincmd p
665  call assert_equal(1, winnr())
666  wincmd p
667  " reset
668  q
669  call delete('tmp.txt')
670  set hidden&vim autoread&vim
671  delfunc Fun_RenewFile
672endfunc
673
674func Test_relative_cursor_position_in_one_line_window()
675  new
676  only
677  call setline(1, range(1, 10000))
678  normal 50%
679  let lnum = getcurpos()[1]
680  split
681  split
682  " make third window take as many lines as possible, other windows will
683  " become one line
684  3wincmd w
685  for i in range(1, &lines - 6)
686    wincmd +
687    redraw!
688  endfor
689
690  " first and second window should show cursor line
691  let wininfo = getwininfo()
692  call assert_equal(lnum, wininfo[0].topline)
693  call assert_equal(lnum, wininfo[1].topline)
694
695  only!
696  bwipe!
697endfunc
698
699func Test_relative_cursor_position_after_move_and_resize()
700  let so_save = &so
701  set so=0
702  enew
703  call setline(1, range(1, 10000))
704  normal 50%
705  split
706  1wincmd w
707  " Move cursor to first line in window
708  normal H
709  redraw!
710  " Reduce window height to two lines
711  let height = winheight(0)
712  while winheight(0) > 2
713    wincmd -
714    redraw!
715  endwhile
716  " move cursor to second/last line in window
717  normal j
718  " restore previous height
719  while winheight(0) < height
720    wincmd +
721    redraw!
722  endwhile
723  " make window two lines again
724  while winheight(0) > 2
725    wincmd -
726    redraw!
727  endwhile
728
729  " cursor should be at bottom line
730  let info = getwininfo(win_getid())[0]
731  call assert_equal(info.topline + 1, getcurpos()[1])
732
733  only!
734  bwipe!
735  let &so = so_save
736endfunc
737
738func Test_relative_cursor_position_after_resize()
739  let so_save = &so
740  set so=0
741  enew
742  call setline(1, range(1, 10000))
743  normal 50%
744  split
745  1wincmd w
746  let winid1 = win_getid()
747  let info = getwininfo(winid1)[0]
748  " Move cursor to second line in window
749  exe "normal " . (info.topline + 1) . "G"
750  redraw!
751  let lnum = getcurpos()[1]
752
753  " Make the window only two lines high, cursor should end up in top line
754  2wincmd w
755  exe (info.height - 2) . "wincmd +"
756  redraw!
757  let info = getwininfo(winid1)[0]
758  call assert_equal(lnum, info.topline)
759
760  only!
761  bwipe!
762  let &so = so_save
763endfunc
764
765func Test_relative_cursor_second_line_after_resize()
766  let so_save = &so
767  set so=0
768  enew
769  call setline(1, range(1, 10000))
770  normal 50%
771  split
772  1wincmd w
773  let winid1 = win_getid()
774  let info = getwininfo(winid1)[0]
775
776  " Make the window only two lines high
777  2wincmd _
778
779  " Move cursor to second line in window
780  normal H
781  normal j
782
783  " Make window size bigger, then back to 2 lines
784  for i in range(1, 10)
785    wincmd +
786    redraw!
787  endfor
788  for i in range(1, 10)
789    wincmd -
790    redraw!
791  endfor
792
793  " cursor should end up in bottom line
794  let info = getwininfo(winid1)[0]
795  call assert_equal(info.topline + 1, getcurpos()[1])
796
797  only!
798  bwipe!
799  let &so = so_save
800endfunc
801
802func Test_split_noscroll()
803  let so_save = &so
804  enew
805  call setline(1, range(1, 8))
806  normal 100%
807  split
808
809  1wincmd w
810  let winid1 = win_getid()
811  let info1 = getwininfo(winid1)[0]
812
813  2wincmd w
814  let winid2 = win_getid()
815  let info2 = getwininfo(winid2)[0]
816
817  call assert_equal(1, info1.topline)
818  call assert_equal(1, info2.topline)
819
820  " window that fits all lines by itself, but not when split: closing other
821  " window should restore fraction.
822  only!
823  call setline(1, range(1, &lines - 10))
824  exe &lines / 4
825  let winid1 = win_getid()
826  let info1 = getwininfo(winid1)[0]
827  call assert_equal(1, info1.topline)
828  new
829  redraw
830  close
831  let info1 = getwininfo(winid1)[0]
832  call assert_equal(1, info1.topline)
833
834  bwipe!
835  let &so = so_save
836endfunc
837
838" Tests for the winnr() function
839func Test_winnr()
840  only | tabonly
841  call assert_equal(1, winnr('j'))
842  call assert_equal(1, winnr('k'))
843  call assert_equal(1, winnr('h'))
844  call assert_equal(1, winnr('l'))
845
846  " create a set of horizontally and vertically split windows
847  leftabove new | wincmd p
848  leftabove new | wincmd p
849  rightbelow new | wincmd p
850  rightbelow new | wincmd p
851  leftabove vnew | wincmd p
852  leftabove vnew | wincmd p
853  rightbelow vnew | wincmd p
854  rightbelow vnew | wincmd p
855
856  call assert_equal(8, winnr('j'))
857  call assert_equal(2, winnr('k'))
858  call assert_equal(4, winnr('h'))
859  call assert_equal(6, winnr('l'))
860  call assert_equal(9, winnr('2j'))
861  call assert_equal(1, winnr('2k'))
862  call assert_equal(3, winnr('2h'))
863  call assert_equal(7, winnr('2l'))
864
865  " Error cases
866  call assert_fails("echo winnr('0.2k')", 'E15:')
867  call assert_equal(2, winnr('-2k'))
868  call assert_fails("echo winnr('-2xj')", 'E15:')
869  call assert_fails("echo winnr('j2j')", 'E15:')
870  call assert_fails("echo winnr('ll')", 'E15:')
871  call assert_fails("echo winnr('5')", 'E15:')
872  call assert_equal(4, winnr('0h'))
873
874  tabnew
875  call assert_equal(8, tabpagewinnr(1, 'j'))
876  call assert_equal(2, 1->tabpagewinnr('k'))
877  call assert_equal(4, tabpagewinnr(1, 'h'))
878  call assert_equal(6, tabpagewinnr(1, 'l'))
879
880  only | tabonly
881endfunc
882
883func Test_winrestview()
884  split runtest.vim
885  normal 50%
886  let view = winsaveview()
887  close
888  split runtest.vim
889  eval view->winrestview()
890  call assert_equal(view, winsaveview())
891
892  bwipe!
893endfunc
894
895func Test_win_splitmove()
896  CheckFeature quickfix
897
898  edit a
899  leftabove split b
900  leftabove vsplit c
901  leftabove split d
902  call assert_equal(0, win_splitmove(winnr(), winnr('l')))
903  call assert_equal(bufname(winbufnr(1)), 'c')
904  call assert_equal(bufname(winbufnr(2)), 'd')
905  call assert_equal(bufname(winbufnr(3)), 'b')
906  call assert_equal(bufname(winbufnr(4)), 'a')
907  call assert_equal(0, win_splitmove(winnr(), winnr('j'), {'vertical': 1}))
908  call assert_equal(0, win_splitmove(winnr(), winnr('j'), {'vertical': 1}))
909  call assert_equal(bufname(winbufnr(1)), 'c')
910  call assert_equal(bufname(winbufnr(2)), 'b')
911  call assert_equal(bufname(winbufnr(3)), 'd')
912  call assert_equal(bufname(winbufnr(4)), 'a')
913  call assert_equal(0, win_splitmove(winnr(), winnr('k'), {'vertical': 1}))
914  call assert_equal(bufname(winbufnr(1)), 'd')
915  call assert_equal(bufname(winbufnr(2)), 'c')
916  call assert_equal(bufname(winbufnr(3)), 'b')
917  call assert_equal(bufname(winbufnr(4)), 'a')
918  call assert_equal(0, win_splitmove(winnr(), winnr('j'), {'rightbelow': v:true}))
919  call assert_equal(bufname(winbufnr(1)), 'c')
920  call assert_equal(bufname(winbufnr(2)), 'b')
921  call assert_equal(bufname(winbufnr(3)), 'a')
922  call assert_equal(bufname(winbufnr(4)), 'd')
923  only | bd
924
925  call assert_fails('call win_splitmove(winnr(), 123)', 'E957:')
926  call assert_fails('call win_splitmove(123, winnr())', 'E957:')
927  call assert_fails('call win_splitmove(winnr(), winnr())', 'E957:')
928
929  tabnew
930  call assert_fails('call win_splitmove(1, win_getid(1, 1))', 'E957:')
931  tabclose
932endfunc
933
934" Test for the :only command
935func Test_window_only()
936  new
937  set modified
938  new
939  call assert_fails('only', 'E445:')
940  only!
941  " Test for :only with a count
942  let wid = win_getid()
943  new
944  new
945  3only
946  call assert_equal(1, winnr('$'))
947  call assert_equal(wid, win_getid())
948  call assert_fails('close', 'E444:')
949  call assert_fails('%close', 'E16:')
950endfunc
951
952" Test for errors with :wincmd
953func Test_wincmd_errors()
954  call assert_fails('wincmd g', 'E474:')
955  call assert_fails('wincmd ab', 'E474:')
956endfunc
957
958" Test for errors with :winpos
959func Test_winpos_errors()
960  if !has("gui_running") && !has('win32')
961    call assert_fails('winpos', 'E188:')
962  endif
963  call assert_fails('winpos 10', 'E466:')
964endfunc
965
966" Test for +cmd in a :split command
967func Test_split_cmd()
968  split +set\ readonly
969  call assert_equal(1, &readonly)
970  call assert_equal(2, winnr('$'))
971  close
972endfunc
973
974" Create maximum number of horizontally or vertically split windows and then
975" run commands that create a new horizontally/vertically split window
976func Run_noroom_for_newwindow_test(dir_arg)
977  let dir = (a:dir_arg == 'v') ? 'vert ' : ''
978
979  " Open as many windows as possible
980  while v:true
981    try
982      exe dir . 'new'
983    catch /E36:/
984      break
985    endtry
986  endwhile
987
988  call writefile(['first', 'second', 'third'], 'Xfile1')
989  call writefile([], 'Xfile2')
990  call writefile([], 'Xfile3')
991
992  " Argument list related commands
993  args Xfile1 Xfile2 Xfile3
994  next
995  for cmd in ['sargument 2', 'snext', 'sprevious', 'sNext', 'srewind',
996			\ 'sfirst', 'slast']
997    call assert_fails(dir .. cmd, 'E36:')
998  endfor
999  %argdelete
1000
1001  " Buffer related commands
1002  set modified
1003  hide enew
1004  for cmd in ['sbuffer Xfile1', 'sbnext', 'sbprevious', 'sbNext', 'sbrewind',
1005		\ 'sbfirst', 'sblast', 'sball', 'sbmodified', 'sunhide']
1006    call assert_fails(dir .. cmd, 'E36:')
1007  endfor
1008
1009  " Window related commands
1010  for cmd in ['split', 'split Xfile2', 'new', 'new Xfile3', 'sview Xfile1',
1011		\ 'sfind runtest.vim']
1012    call assert_fails(dir .. cmd, 'E36:')
1013  endfor
1014
1015  " Help
1016  call assert_fails(dir .. 'help', 'E36:')
1017  call assert_fails(dir .. 'helpgrep window', 'E36:')
1018
1019  " Command-line window
1020  if a:dir_arg == 'h'
1021    " Cmd-line window is always a horizontally split window
1022    call assert_beeps('call feedkeys("q:\<CR>", "xt")')
1023  endif
1024
1025  " Quickfix and location list window
1026  if has('quickfix')
1027    cexpr ''
1028    call assert_fails(dir .. 'copen', 'E36:')
1029    lexpr ''
1030    call assert_fails(dir .. 'lopen', 'E36:')
1031
1032    " Preview window
1033    call assert_fails(dir .. 'pedit Xfile2', 'E36:')
1034    call setline(1, 'abc')
1035    call assert_fails(dir .. 'psearch abc', 'E36:')
1036  endif
1037
1038  " Window commands (CTRL-W ^ and CTRL-W f)
1039  if a:dir_arg == 'h'
1040    call assert_fails('call feedkeys("\<C-W>^", "xt")', 'E36:')
1041    call setline(1, 'Xfile1')
1042    call assert_fails('call feedkeys("gg\<C-W>f", "xt")', 'E36:')
1043  endif
1044  enew!
1045
1046  " Tag commands (:stag, :stselect and :stjump)
1047  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
1048        \ "second\tXfile1\t2",
1049        \ "third\tXfile1\t3",],
1050        \ 'Xtags')
1051  set tags=Xtags
1052  call assert_fails(dir .. 'stag second', 'E36:')
1053  call assert_fails('call feedkeys(":" .. dir .. "stselect second\n1\n", "xt")', 'E36:')
1054  call assert_fails(dir .. 'stjump second', 'E36:')
1055  call assert_fails(dir .. 'ptag second', 'E36:')
1056  set tags&
1057  call delete('Xtags')
1058
1059  " :isplit and :dsplit
1060  call setline(1, ['#define FOO 1', 'FOO'])
1061  normal 2G
1062  call assert_fails(dir .. 'isplit FOO', 'E36:')
1063  call assert_fails(dir .. 'dsplit FOO', 'E36:')
1064
1065  " terminal
1066  if has('terminal')
1067    call assert_fails(dir .. 'terminal', 'E36:')
1068  endif
1069
1070  %bwipe!
1071  call delete('Xfile1')
1072  call delete('Xfile2')
1073  call delete('Xfile3')
1074  only
1075endfunc
1076
1077func Test_split_cmds_with_no_room()
1078  call Run_noroom_for_newwindow_test('h')
1079  call Run_noroom_for_newwindow_test('v')
1080endfunc
1081
1082" Test for various wincmd failures
1083func Test_wincmd_fails()
1084  only!
1085  call assert_beeps("normal \<C-W>w")
1086  call assert_beeps("normal \<C-W>p")
1087  call assert_beeps("normal \<C-W>gk")
1088  call assert_beeps("normal \<C-W>r")
1089  call assert_beeps("normal \<C-W>K")
1090  call assert_beeps("normal \<C-W>H")
1091  call assert_beeps("normal \<C-W>2gt")
1092endfunc
1093
1094" vim: shiftwidth=2 sts=2 expandtab
1095