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