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