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  bw Xa Xb Xc
401endfunc
402
403func Test_equalalways_on_close()
404  set equalalways
405  vsplit
406  windo split
407  split
408  wincmd J
409  " now we have a frame top-left with two windows, a frame top-right with two
410  " windows and a frame at the bottom, full-width.
411  let height_1 = winheight(1)
412  let height_2 = winheight(2)
413  let height_3 = winheight(3)
414  let height_4 = winheight(4)
415  " closing the bottom window causes all windows to be resized.
416  close
417  call assert_notequal(height_1, winheight(1))
418  call assert_notequal(height_2, winheight(2))
419  call assert_notequal(height_3, winheight(3))
420  call assert_notequal(height_4, winheight(4))
421  call assert_equal(winheight(1), winheight(3))
422  call assert_equal(winheight(2), winheight(4))
423
424  1wincmd w
425  split
426  4wincmd w
427  resize + 5
428  " left column has three windows, equalized heights.
429  " right column has two windows, top one a bit higher
430  let height_1 = winheight(1)
431  let height_2 = winheight(2)
432  let height_4 = winheight(4)
433  let height_5 = winheight(5)
434  3wincmd w
435  " closing window in left column equalizes heights in left column but not in
436  " the right column
437  close
438  call assert_notequal(height_1, winheight(1))
439  call assert_notequal(height_2, winheight(2))
440  call assert_equal(height_4, winheight(3))
441  call assert_equal(height_5, winheight(4))
442
443  only
444  set equalalways&
445endfunc
446
447func Test_win_screenpos()
448  CheckFeature quickfix
449
450  call assert_equal(1, winnr('$'))
451  split
452  vsplit
453  10wincmd _
454  30wincmd |
455  call assert_equal([1, 1], win_screenpos(1))
456  call assert_equal([1, 32], win_screenpos(2))
457  call assert_equal([12, 1], win_screenpos(3))
458  call assert_equal([0, 0], win_screenpos(4))
459  call assert_fails('let l = win_screenpos([])', 'E745:')
460  only
461endfunc
462
463func Test_window_jump_tag()
464  CheckFeature quickfix
465
466  help
467  /iccf
468  call assert_match('^|iccf|',  getline('.'))
469  call assert_equal(2, winnr('$'))
470  2wincmd }
471  call assert_equal(3, winnr('$'))
472  call assert_match('^|iccf|',  getline('.'))
473  wincmd k
474  call assert_match('\*iccf\*',  getline('.'))
475  call assert_equal(2, winheight(0))
476
477  wincmd z
478  set previewheight=4
479  help
480  /bugs
481  wincmd }
482  wincmd k
483  call assert_match('\*bugs\*',  getline('.'))
484  call assert_equal(4, winheight(0))
485  set previewheight&
486
487  %bw!
488endfunc
489
490func Test_window_newtab()
491  e Xa
492
493  call assert_equal(1, tabpagenr('$'))
494  call assert_equal("\nAlready only one window", execute('wincmd T'))
495
496  split Xb
497  split Xc
498
499  wincmd T
500  call assert_equal(2, tabpagenr('$'))
501  call assert_equal(['Xb', 'Xa'], map(tabpagebuflist(1), 'bufname(v:val)'))
502  call assert_equal(['Xc'      ], map(2->tabpagebuflist(), 'bufname(v:val)'))
503  call assert_equal(['Xc'      ], map(tabpagebuflist(), 'bufname(v:val)'))
504
505  %bw!
506endfunc
507
508func Test_next_split_all()
509  " This was causing an illegal memory access.
510  n x
511  norm axxx
512  split
513  split
514  s/x
515  s/x
516  all
517  bwipe!
518endfunc
519
520" Tests for adjusting window and contents
521func GetScreenStr(row)
522   let str = ""
523   for c in range(1,3)
524       let str .= nr2char(screenchar(a:row, c))
525   endfor
526   return str
527endfunc
528
529func Test_window_contents()
530  enew! | only | new
531  call setline(1, range(1,256))
532
533  exe "norm! \<C-W>t\<C-W>=1Gzt\<C-W>w\<C-W>+"
534  redraw
535  let s3 = GetScreenStr(1)
536  wincmd p
537  call assert_equal(1, line("w0"))
538  call assert_equal('1  ', s3)
539
540  exe "norm! \<C-W>t\<C-W>=50Gzt\<C-W>w\<C-W>+"
541  redraw
542  let s3 = GetScreenStr(1)
543  wincmd p
544  call assert_equal(50, line("w0"))
545  call assert_equal('50 ', s3)
546
547  exe "norm! \<C-W>t\<C-W>=59Gzt\<C-W>w\<C-W>+"
548  redraw
549  let s3 = GetScreenStr(1)
550  wincmd p
551  call assert_equal(59, line("w0"))
552  call assert_equal('59 ', s3)
553
554  %d
555  call setline(1, ['one', 'two', 'three'])
556  call assert_equal(1, line('w0'))
557  call assert_equal(3, line('w$'))
558
559  bwipeout!
560  call test_garbagecollect_now()
561endfunc
562
563func Test_window_colon_command()
564  " This was reading invalid memory.
565  exe "norm! v\<C-W>:\<C-U>echo v:version"
566endfunc
567
568func Test_access_freed_mem()
569  call assert_equal(&columns, winwidth(0))
570  " This was accessing freed memory (but with what events?)
571  au BufEnter,BufLeave,WinEnter,WinLeave 0 vs xxx
572  arg 0
573  argadd
574  call assert_fails("all", "E242:")
575  au!
576  bwipe xxx
577  call assert_equal(&columns, winwidth(0))
578endfunc
579
580func Test_insert_cleared_on_switch_to_term()
581  CheckFeature terminal
582
583  set showmode
584  terminal
585  wincmd p
586
587  call feedkeys("i\<C-O>", 'ntx')
588  redraw
589
590  " The "-- (insert) --" indicator should be visible.
591  let chars = map(range(1, &columns), 'nr2char(screenchar(&lines, v:val))')
592  let str = trim(join(chars, ''))
593  call assert_equal('-- (insert) --', str)
594
595  call feedkeys("\<C-W>p", 'ntx')
596  redraw
597
598  " The "-- (insert) --" indicator should have been cleared.
599  let chars = map(range(1, &columns), 'nr2char(screenchar(&lines, v:val))')
600  let str = trim(join(chars, ''))
601  call assert_equal('', str)
602
603  set showmode&
604  %bw!
605endfunc
606
607func Test_visual_cleared_after_window_split()
608  new | only!
609  let smd_save = &showmode
610  set showmode
611  let ls_save = &laststatus
612  set laststatus=1
613  call setline(1, ['a', 'b', 'c', 'd', ''])
614  norm! G
615  exe "norm! kkvk"
616  redraw
617  exe "norm! \<C-W>v"
618  redraw
619  " check if '-- VISUAL --' disappeared from command line
620  let columns = range(1, &columns)
621  let cmdlinechars = map(columns, 'nr2char(screenchar(&lines, v:val))')
622  let cmdline = join(cmdlinechars, '')
623  let cmdline_ltrim = substitute(cmdline, '^\s*', "", "")
624  let mode_shown = substitute(cmdline_ltrim, '\s*$', "", "")
625  call assert_equal('', mode_shown)
626  let &showmode = smd_save
627  let &laststatus = ls_save
628  bwipe!
629endfunc
630
631func Test_winrestcmd()
632  2split
633  3vsplit
634  let a = winrestcmd()
635  call assert_equal(2, winheight(0))
636  call assert_equal(3, winwidth(0))
637  wincmd =
638  call assert_notequal(2, winheight(0))
639  call assert_notequal(3, winwidth(0))
640  exe a
641  call assert_equal(2, winheight(0))
642  call assert_equal(3, winwidth(0))
643  only
644endfunc
645
646func Fun_RenewFile()
647  " Need to wait a bit for the timestamp to be older.
648  let old_ftime = getftime("tmp.txt")
649  while getftime("tmp.txt") == old_ftime
650    sleep 100m
651    silent execute '!echo "1" > tmp.txt'
652  endwhile
653  sp
654  wincmd p
655  edit! tmp.txt
656endfunc
657
658func Test_window_prevwin()
659  " Can we make this work on MS-Windows?
660  CheckUnix
661
662  set hidden autoread
663  call writefile(['2'], 'tmp.txt')
664  new tmp.txt
665  q
666  call Fun_RenewFile()
667  call assert_equal(2, winnr())
668  wincmd p
669  call assert_equal(1, winnr())
670  wincmd p
671  q
672  call Fun_RenewFile()
673  call assert_equal(2, winnr())
674  wincmd p
675  call assert_equal(1, winnr())
676  wincmd p
677  " reset
678  q
679  call delete('tmp.txt')
680  set hidden&vim autoread&vim
681  delfunc Fun_RenewFile
682endfunc
683
684func Test_relative_cursor_position_in_one_line_window()
685  new
686  only
687  call setline(1, range(1, 10000))
688  normal 50%
689  let lnum = getcurpos()[1]
690  split
691  split
692  " make third window take as many lines as possible, other windows will
693  " become one line
694  3wincmd w
695  for i in range(1, &lines - 6)
696    wincmd +
697    redraw!
698  endfor
699
700  " first and second window should show cursor line
701  let wininfo = getwininfo()
702  call assert_equal(lnum, wininfo[0].topline)
703  call assert_equal(lnum, wininfo[1].topline)
704
705  only!
706  bwipe!
707  call assert_fails('call winrestview(test_null_dict())', 'E474:')
708endfunc
709
710func Test_relative_cursor_position_after_move_and_resize()
711  let so_save = &so
712  set so=0
713  enew
714  call setline(1, range(1, 10000))
715  normal 50%
716  split
717  1wincmd w
718  " Move cursor to first line in window
719  normal H
720  redraw!
721  " Reduce window height to two lines
722  let height = winheight(0)
723  while winheight(0) > 2
724    wincmd -
725    redraw!
726  endwhile
727  " move cursor to second/last line in window
728  normal j
729  " restore previous height
730  while winheight(0) < height
731    wincmd +
732    redraw!
733  endwhile
734  " make window two lines again
735  while winheight(0) > 2
736    wincmd -
737    redraw!
738  endwhile
739
740  " cursor should be at bottom line
741  let info = getwininfo(win_getid())[0]
742  call assert_equal(info.topline + 1, getcurpos()[1])
743
744  only!
745  bwipe!
746  let &so = so_save
747endfunc
748
749func Test_relative_cursor_position_after_resize()
750  let so_save = &so
751  set so=0
752  enew
753  call setline(1, range(1, 10000))
754  normal 50%
755  split
756  1wincmd w
757  let winid1 = win_getid()
758  let info = getwininfo(winid1)[0]
759  " Move cursor to second line in window
760  exe "normal " . (info.topline + 1) . "G"
761  redraw!
762  let lnum = getcurpos()[1]
763
764  " Make the window only two lines high, cursor should end up in top line
765  2wincmd w
766  exe (info.height - 2) . "wincmd +"
767  redraw!
768  let info = getwininfo(winid1)[0]
769  call assert_equal(lnum, info.topline)
770
771  only!
772  bwipe!
773  let &so = so_save
774endfunc
775
776func Test_relative_cursor_second_line_after_resize()
777  let so_save = &so
778  set so=0
779  enew
780  call setline(1, range(1, 10000))
781  normal 50%
782  split
783  1wincmd w
784  let winid1 = win_getid()
785  let info = getwininfo(winid1)[0]
786
787  " Make the window only two lines high
788  2wincmd _
789
790  " Move cursor to second line in window
791  normal H
792  normal j
793
794  " Make window size bigger, then back to 2 lines
795  for i in range(1, 10)
796    wincmd +
797    redraw!
798  endfor
799  for i in range(1, 10)
800    wincmd -
801    redraw!
802  endfor
803
804  " cursor should end up in bottom line
805  let info = getwininfo(winid1)[0]
806  call assert_equal(info.topline + 1, getcurpos()[1])
807
808  only!
809  bwipe!
810  let &so = so_save
811endfunc
812
813func Test_split_noscroll()
814  let so_save = &so
815  enew
816  call setline(1, range(1, 8))
817  normal 100%
818  split
819
820  1wincmd w
821  let winid1 = win_getid()
822  let info1 = getwininfo(winid1)[0]
823
824  2wincmd w
825  let winid2 = win_getid()
826  let info2 = getwininfo(winid2)[0]
827
828  call assert_equal(1, info1.topline)
829  call assert_equal(1, info2.topline)
830
831  " window that fits all lines by itself, but not when split: closing other
832  " window should restore fraction.
833  only!
834  call setline(1, range(1, &lines - 10))
835  exe &lines / 4
836  let winid1 = win_getid()
837  let info1 = getwininfo(winid1)[0]
838  call assert_equal(1, info1.topline)
839  new
840  redraw
841  close
842  let info1 = getwininfo(winid1)[0]
843  call assert_equal(1, info1.topline)
844
845  bwipe!
846  let &so = so_save
847endfunc
848
849" Tests for the winnr() function
850func Test_winnr()
851  only | tabonly
852  call assert_equal(1, winnr('j'))
853  call assert_equal(1, winnr('k'))
854  call assert_equal(1, winnr('h'))
855  call assert_equal(1, winnr('l'))
856
857  " create a set of horizontally and vertically split windows
858  leftabove new | wincmd p
859  leftabove new | wincmd p
860  rightbelow new | wincmd p
861  rightbelow new | wincmd p
862  leftabove vnew | wincmd p
863  leftabove vnew | wincmd p
864  rightbelow vnew | wincmd p
865  rightbelow vnew | wincmd p
866
867  call assert_equal(8, winnr('j'))
868  call assert_equal(2, winnr('k'))
869  call assert_equal(4, winnr('h'))
870  call assert_equal(6, winnr('l'))
871  call assert_equal(9, winnr('2j'))
872  call assert_equal(1, winnr('2k'))
873  call assert_equal(3, winnr('2h'))
874  call assert_equal(7, winnr('2l'))
875
876  " Error cases
877  call assert_fails("echo winnr('0.2k')", 'E15:')
878  call assert_equal(2, winnr('-2k'))
879  call assert_fails("echo winnr('-2xj')", 'E15:')
880  call assert_fails("echo winnr('j2j')", 'E15:')
881  call assert_fails("echo winnr('ll')", 'E15:')
882  call assert_fails("echo winnr('5')", 'E15:')
883  call assert_equal(4, winnr('0h'))
884  call assert_fails("let w = winnr([])", 'E730:')
885  call assert_equal('unknown', win_gettype(-1))
886  call assert_equal(-1, winheight(-1))
887  call assert_equal(-1, winwidth(-1))
888
889  tabnew
890  call assert_equal(8, tabpagewinnr(1, 'j'))
891  call assert_equal(2, 1->tabpagewinnr('k'))
892  call assert_equal(4, tabpagewinnr(1, 'h'))
893  call assert_equal(6, tabpagewinnr(1, 'l'))
894
895  only | tabonly
896endfunc
897
898func Test_winrestview()
899  split runtest.vim
900  normal 50%
901  let view = winsaveview()
902  close
903  split runtest.vim
904  eval view->winrestview()
905  call assert_equal(view, winsaveview())
906
907  bwipe!
908  call assert_fails('call winrestview(test_null_dict())', 'E474:')
909endfunc
910
911func Test_win_splitmove()
912  CheckFeature quickfix
913
914  edit a
915  leftabove split b
916  leftabove vsplit c
917  leftabove split d
918  call assert_equal(0, win_splitmove(winnr(), winnr('l')))
919  call assert_equal(bufname(winbufnr(1)), 'c')
920  call assert_equal(bufname(winbufnr(2)), 'd')
921  call assert_equal(bufname(winbufnr(3)), 'b')
922  call assert_equal(bufname(winbufnr(4)), 'a')
923  call assert_equal(0, win_splitmove(winnr(), winnr('j'), {'vertical': 1}))
924  call assert_equal(0, win_splitmove(winnr(), winnr('j'), {'vertical': 1}))
925  call assert_equal(bufname(winbufnr(1)), 'c')
926  call assert_equal(bufname(winbufnr(2)), 'b')
927  call assert_equal(bufname(winbufnr(3)), 'd')
928  call assert_equal(bufname(winbufnr(4)), 'a')
929  call assert_equal(0, win_splitmove(winnr(), winnr('k'), {'vertical': 1}))
930  call assert_equal(bufname(winbufnr(1)), 'd')
931  call assert_equal(bufname(winbufnr(2)), 'c')
932  call assert_equal(bufname(winbufnr(3)), 'b')
933  call assert_equal(bufname(winbufnr(4)), 'a')
934  call assert_equal(0, win_splitmove(winnr(), winnr('j'), {'rightbelow': v:true}))
935  call assert_equal(bufname(winbufnr(1)), 'c')
936  call assert_equal(bufname(winbufnr(2)), 'b')
937  call assert_equal(bufname(winbufnr(3)), 'a')
938  call assert_equal(bufname(winbufnr(4)), 'd')
939  call assert_fails('call win_splitmove(winnr(), winnr("k"), test_null_dict())', 'E474:')
940  only | bd
941
942  call assert_fails('call win_splitmove(winnr(), 123)', 'E957:')
943  call assert_fails('call win_splitmove(123, winnr())', 'E957:')
944  call assert_fails('call win_splitmove(winnr(), winnr())', 'E957:')
945
946  tabnew
947  call assert_fails('call win_splitmove(1, win_getid(1, 1))', 'E957:')
948  tabclose
949endfunc
950
951" Test for the :only command
952func Test_window_only()
953  new
954  set modified
955  new
956  call assert_fails('only', 'E445:')
957  only!
958  " Test for :only with a count
959  let wid = win_getid()
960  new
961  new
962  3only
963  call assert_equal(1, winnr('$'))
964  call assert_equal(wid, win_getid())
965  call assert_fails('close', 'E444:')
966  call assert_fails('%close', 'E16:')
967endfunc
968
969" Test for errors with :wincmd
970func Test_wincmd_errors()
971  call assert_fails('wincmd g', 'E474:')
972  call assert_fails('wincmd ab', 'E474:')
973endfunc
974
975" Test for errors with :winpos
976func Test_winpos_errors()
977  if !has("gui_running") && !has('win32')
978    call assert_fails('winpos', 'E188:')
979  endif
980  call assert_fails('winpos 10', 'E466:')
981endfunc
982
983" Test for +cmd in a :split command
984func Test_split_cmd()
985  split +set\ readonly
986  call assert_equal(1, &readonly)
987  call assert_equal(2, winnr('$'))
988  close
989endfunc
990
991" Create maximum number of horizontally or vertically split windows and then
992" run commands that create a new horizontally/vertically split window
993func Run_noroom_for_newwindow_test(dir_arg)
994  let dir = (a:dir_arg == 'v') ? 'vert ' : ''
995
996  " Open as many windows as possible
997  while v:true
998    try
999      exe dir . 'new'
1000    catch /E36:/
1001      break
1002    endtry
1003  endwhile
1004
1005  call writefile(['first', 'second', 'third'], 'Xfile1')
1006  call writefile([], 'Xfile2')
1007  call writefile([], 'Xfile3')
1008
1009  " Argument list related commands
1010  args Xfile1 Xfile2 Xfile3
1011  next
1012  for cmd in ['sargument 2', 'snext', 'sprevious', 'sNext', 'srewind',
1013			\ 'sfirst', 'slast']
1014    call assert_fails(dir .. cmd, 'E36:')
1015  endfor
1016  %argdelete
1017
1018  " Buffer related commands
1019  set modified
1020  hide enew
1021  for cmd in ['sbuffer Xfile1', 'sbnext', 'sbprevious', 'sbNext', 'sbrewind',
1022		\ 'sbfirst', 'sblast', 'sball', 'sbmodified', 'sunhide']
1023    call assert_fails(dir .. cmd, 'E36:')
1024  endfor
1025
1026  " Window related commands
1027  for cmd in ['split', 'split Xfile2', 'new', 'new Xfile3', 'sview Xfile1',
1028		\ 'sfind runtest.vim']
1029    call assert_fails(dir .. cmd, 'E36:')
1030  endfor
1031
1032  " Help
1033  call assert_fails(dir .. 'help', 'E36:')
1034  call assert_fails(dir .. 'helpgrep window', 'E36:')
1035
1036  " Command-line window
1037  if a:dir_arg == 'h'
1038    " Cmd-line window is always a horizontally split window
1039    call assert_beeps('call feedkeys("q:\<CR>", "xt")')
1040  endif
1041
1042  " Quickfix and location list window
1043  if has('quickfix')
1044    cexpr ''
1045    call assert_fails(dir .. 'copen', 'E36:')
1046    lexpr ''
1047    call assert_fails(dir .. 'lopen', 'E36:')
1048
1049    " Preview window
1050    call assert_fails(dir .. 'pedit Xfile2', 'E36:')
1051    call setline(1, 'abc')
1052    call assert_fails(dir .. 'psearch abc', 'E36:')
1053  endif
1054
1055  " Window commands (CTRL-W ^ and CTRL-W f)
1056  if a:dir_arg == 'h'
1057    call assert_fails('call feedkeys("\<C-W>^", "xt")', 'E36:')
1058    call setline(1, 'Xfile1')
1059    call assert_fails('call feedkeys("gg\<C-W>f", "xt")', 'E36:')
1060  endif
1061  enew!
1062
1063  " Tag commands (:stag, :stselect and :stjump)
1064  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
1065        \ "second\tXfile1\t2",
1066        \ "third\tXfile1\t3",],
1067        \ 'Xtags')
1068  set tags=Xtags
1069  call assert_fails(dir .. 'stag second', 'E36:')
1070  call assert_fails('call feedkeys(":" .. dir .. "stselect second\n1\n", "xt")', 'E36:')
1071  call assert_fails(dir .. 'stjump second', 'E36:')
1072  call assert_fails(dir .. 'ptag second', 'E36:')
1073  set tags&
1074  call delete('Xtags')
1075
1076  " :isplit and :dsplit
1077  call setline(1, ['#define FOO 1', 'FOO'])
1078  normal 2G
1079  call assert_fails(dir .. 'isplit FOO', 'E36:')
1080  call assert_fails(dir .. 'dsplit FOO', 'E36:')
1081
1082  " terminal
1083  if has('terminal')
1084    call assert_fails(dir .. 'terminal', 'E36:')
1085  endif
1086
1087  %bwipe!
1088  call delete('Xfile1')
1089  call delete('Xfile2')
1090  call delete('Xfile3')
1091  only
1092endfunc
1093
1094func Test_split_cmds_with_no_room()
1095  call Run_noroom_for_newwindow_test('h')
1096  call Run_noroom_for_newwindow_test('v')
1097endfunc
1098
1099" Test for various wincmd failures
1100func Test_wincmd_fails()
1101  only!
1102  call assert_beeps("normal \<C-W>w")
1103  call assert_beeps("normal \<C-W>p")
1104  call assert_beeps("normal \<C-W>gk")
1105  call assert_beeps("normal \<C-W>r")
1106  call assert_beeps("normal \<C-W>K")
1107  call assert_beeps("normal \<C-W>H")
1108  call assert_beeps("normal \<C-W>2gt")
1109endfunc
1110
1111func Test_window_resize()
1112  " Vertical :resize (absolute, relative, min and max size).
1113  vsplit
1114  vert resize 8
1115  call assert_equal(8, winwidth(0))
1116  vert resize +2
1117  call assert_equal(10, winwidth(0))
1118  vert resize -2
1119  call assert_equal(8, winwidth(0))
1120  vert resize
1121  call assert_equal(&columns - 2, winwidth(0))
1122  vert resize 0
1123  call assert_equal(1, winwidth(0))
1124  vert resize 99999
1125  call assert_equal(&columns - 2, winwidth(0))
1126
1127  %bwipe!
1128
1129  " Horizontal :resize (with absolute, relative size, min and max size).
1130  split
1131  resize 8
1132  call assert_equal(8, winheight(0))
1133  resize +2
1134  call assert_equal(10, winheight(0))
1135  resize -2
1136  call assert_equal(8, winheight(0))
1137  resize
1138  call assert_equal(&lines - 4, winheight(0))
1139  resize 0
1140  call assert_equal(1, winheight(0))
1141  resize 99999
1142  call assert_equal(&lines - 4, winheight(0))
1143
1144  " :resize with explicit window number.
1145  let other_winnr = winnr('j')
1146  exe other_winnr .. 'resize 10'
1147  call assert_equal(10, winheight(other_winnr))
1148  call assert_equal(&lines - 10 - 3, winheight(0))
1149  exe other_winnr .. 'resize +1'
1150  exe other_winnr .. 'resize +1'
1151  call assert_equal(12, winheight(other_winnr))
1152  call assert_equal(&lines - 10 - 3 -2, winheight(0))
1153  close
1154
1155  vsplit
1156  wincmd l
1157  let other_winnr = winnr('h')
1158  call assert_notequal(winnr(), other_winnr)
1159  exe 'vert ' .. other_winnr .. 'resize -' .. &columns
1160  call assert_equal(0, winwidth(other_winnr))
1161
1162  %bwipe!
1163endfunc
1164
1165" Test for adjusting the window width when a window is closed with some
1166" windows using 'winfixwidth'
1167func Test_window_width_adjust()
1168  only
1169  " Three vertical windows. Windows 1 and 2 have 'winfixwidth' set and close
1170  " window 2.
1171  wincmd v
1172  vert resize 10
1173  set winfixwidth
1174  wincmd v
1175  set winfixwidth
1176  wincmd c
1177  call assert_inrange(10, 12, winwidth(1))
1178  " Three vertical windows. Windows 2 and 3 have 'winfixwidth' set and close
1179  " window 3.
1180  only
1181  set winfixwidth
1182  wincmd v
1183  vert resize 10
1184  set winfixwidth
1185  wincmd v
1186  set nowinfixwidth
1187  wincmd b
1188  wincmd c
1189  call assert_inrange(10, 12, winwidth(2))
1190
1191  new | only
1192endfunc
1193
1194" Test for jumping to a vertical/horizontal neighbor window based on the
1195" current cursor position
1196func Test_window_goto_neightbor()
1197  %bw!
1198
1199  " Vertical window movement
1200
1201  " create the following window layout:
1202  "     +--+--+
1203  "     |w1|w3|
1204  "     +--+  |
1205  "     |w2|  |
1206  "     +--+--+
1207  "     |w4   |
1208  "     +-----+
1209  new
1210  vsplit
1211  split
1212  " vertically jump from w4
1213  wincmd b
1214  call setline(1, repeat(' ', &columns))
1215  call cursor(1, 1)
1216  wincmd k
1217  call assert_equal(2, winnr())
1218  wincmd b
1219  call cursor(1, &columns)
1220  redraw!
1221  wincmd k
1222  call assert_equal(3, winnr())
1223  %bw!
1224
1225  " create the following window layout:
1226  "     +--+--+--+
1227  "     |w1|w2|w3|
1228  "     +--+--+--+
1229  "     |w4      |
1230  "     +--------+
1231  new
1232  vsplit
1233  vsplit
1234  wincmd b
1235  call setline(1, repeat(' ', &columns))
1236  call cursor(1, 1)
1237  wincmd k
1238  call assert_equal(1, winnr())
1239  wincmd b
1240  call cursor(1, &columns / 2)
1241  redraw!
1242  wincmd k
1243  call assert_equal(2, winnr())
1244  wincmd b
1245  call cursor(1, &columns)
1246  redraw!
1247  wincmd k
1248  call assert_equal(3, winnr())
1249  %bw!
1250
1251  " Horizontal window movement
1252
1253  " create the following window layout:
1254  "     +--+--+--+
1255  "     |w1|w2|w4|
1256  "     +--+--+  |
1257  "     |w3   |  |
1258  "     +-----+--+
1259  vsplit
1260  split
1261  vsplit
1262  4wincmd l
1263  call setline(1, repeat([' '], &lines))
1264  call cursor(1, 1)
1265  redraw!
1266  wincmd h
1267  call assert_equal(2, winnr())
1268  4wincmd l
1269  call cursor(&lines, 1)
1270  redraw!
1271  wincmd h
1272  call assert_equal(3, winnr())
1273  %bw!
1274
1275  " create the following window layout:
1276  "     +--+--+
1277  "     |w1|w4|
1278  "     +--+  +
1279  "     |w2|  |
1280  "     +--+  +
1281  "     |w3|  |
1282  "     +--+--+
1283  vsplit
1284  split
1285  split
1286  wincmd l
1287  call setline(1, repeat([' '], &lines))
1288  call cursor(1, 1)
1289  redraw!
1290  wincmd h
1291  call assert_equal(1, winnr())
1292  wincmd l
1293  call cursor(&lines / 2, 1)
1294  redraw!
1295  wincmd h
1296  call assert_equal(2, winnr())
1297  wincmd l
1298  call cursor(&lines, 1)
1299  redraw!
1300  wincmd h
1301  call assert_equal(3, winnr())
1302  %bw!
1303endfunc
1304
1305" Test for an autocmd closing the destination window when jumping from one
1306" window to another.
1307func Test_close_dest_window()
1308  split
1309  edit Xfile
1310
1311  " Test for BufLeave
1312  augroup T1
1313    au!
1314    au BufLeave Xfile $wincmd c
1315  augroup END
1316  wincmd b
1317  call assert_equal(1, winnr('$'))
1318  call assert_equal('Xfile', @%)
1319  augroup T1
1320    au!
1321  augroup END
1322
1323  " Test for WinLeave
1324  new
1325  wincmd p
1326  augroup T1
1327    au!
1328    au WinLeave * 1wincmd c
1329  augroup END
1330  wincmd t
1331  call assert_equal(1, winnr('$'))
1332  call assert_equal('Xfile', @%)
1333  augroup T1
1334    au!
1335  augroup END
1336  augroup! T1
1337  %bw!
1338endfunc
1339
1340" vim: shiftwidth=2 sts=2 expandtab
1341