@@ -164,20 +164,12 @@ function s:Receiver(b)
164164 return has_key (s: scratch , a: b ) && s: Jobs (a: b ) != []
165165endfunc
166166
167- function s: SplitSize ( n , rel )
167+ function s: New (cmd )
168168 let min = &winminheight > 0 ? 2 * &winminheight + 1 : 2
169169 if winheight (0 ) < min
170170 exe min .' wincmd _'
171171 endif
172- let h = winheight (0 )
173- let stat = 1 + (winnr (' $' ) == 1 && &laststatus == 1 )
174- return a: rel == ' =' ? a: n : a: rel == ' <'
175- \ ? min ([abs (a: n ), h - stat - max ([&winminheight , 1 ])])
176- \ : max ([a: n , h - s: Fit (win_getid (), (h - stat) / 2 ) - stat])
177- endfunc
178-
179- function s: New (cmd)
180- exe s: SplitSize (10 , ' >' ).a: cmd
172+ exe a: cmd
181173endfunc
182174
183175function s: Argv (cmd)
@@ -234,7 +226,7 @@ function s:InDir(path, dir)
234226endfunc
235227
236228function s: ErrorSplitPos (name)
237- let [w , match , mod , rel ] = [0 , 0 , ' ' , ' ' ]
229+ let [w , match , mod ] = [0 , 0 , ' ' ]
238230 let dir = fnamemodify (s: Path (a: name ), ' :h' )
239231 for i in reverse (range (1 , winnr (' $' )))
240232 let b = winbufnr (i )
@@ -245,11 +237,11 @@ function s:ErrorSplitPos(name)
245237 let n = max ([s: InDir (d , dir ), s: InDir (dir , d )])
246238 if n > match
247239 let [w , match ] = [i , n ]
248- let [ mod , rel] = f == ' guide' || f == ' +Errors'
249- \ ? [ ' abo' , ' > ' ] : [ ' bel' , ' = ' ]
240+ let mod = f == ' guide' || f == ' +Errors'
241+ \ ? ' abo' : ' bel'
250242 endif
251243 endfor
252- return w != 0 ? [w , mod , rel ] : [winnr (' $' ), ' bel' , ' = ' ]
244+ return w != 0 ? [w , mod ] : [winnr (' $' ), ' bel' ]
253245endfunc
254246
255247function s: ErrorLoad (name)
@@ -269,15 +261,15 @@ function s:ErrorOpen(name, ...)
269261 if w != 0
270262 exe w .' wincmd w'
271263 else
272- let [w , mod , rel ] = s: ErrorSplitPos (a: name )
264+ let [w , mod ] = s: ErrorSplitPos (a: name )
273265 exe w .' wincmd w'
274266 let b = s: ErrorLoad (a: name )
275267 for job in s: jobs
276268 if ch_getbufnr (job.h , ' out' ) == b && job.buf != b
277269 let job.buf = b
278270 endif
279271 endfor
280- exe mod s: SplitSize ( 10 , rel). ' sp | b ' .b
272+ call s: New ( mod . ' sb ' .b )
281273 endif
282274 if a: 0 == 0
283275 elseif line (' $' ) == 1 && getline (1 ) == ' '
@@ -685,23 +677,6 @@ function s:WinCol(w)
685677 return col
686678endfunc
687679
688- function s: CloseWin (w )
689- let h = winheight (a: w ) + 1
690- let col = s: WinCol (a: w )
691- let [i , j ] = [index (col , a: w ), index (col , win_getid ())]
692- let sb = &splitbelow
693- let &splitbelow = 0
694- exe win_id2win (a: w ).' close!'
695- let &splitbelow = sb
696- if j == -1
697- return
698- endif
699- let d = i - j
700- for i in d < 0 ? range (d + 1 , -1 ) : reverse (range (d ))
701- call win_move_statusline (winnr () + i , d < 0 ? - h : h )
702- endfor
703- endfunc
704-
705680function s: RestWinVars (w , vars)
706681 let vars = getwinvar (a: w , ' &' )
707682 for v in keys (a: vars )
@@ -727,23 +702,28 @@ function s:MoveWin(w, other, below)
727702 endfor
728703 noa exe win_id2win (p ).' wincmd w'
729704 noa exe win_id2win (w ).' wincmd w'
705+ call s: Layout (s: WinCol (a: w ))
730706 else
707+ let minimized = s: Minimized (a: w )
731708 let v = winsaveview ()
732709 let vars = getwinvar (0 , ' &' )
733710 noa exe win_id2win (a: other ).' wincmd w'
734- let h = s: SplitSize (1 , ' >' )
735- noa exe (a: below ? ' bel' : ' abo' ) h .' sp'
736- noa exe ' b' winbufnr (a: w )
737- call winrestview (v )
711+ noa call s: New ((a: below ? ' bel' : ' abo' ).' sb ' .winbufnr (a: w ))
738712 let nw = win_getid ()
713+ call s: RestWinVars (nw, vars)
714+ call winrestview (v )
715+ let s: minimized [nw] = minimized
739716 noa exe win_id2win (p != a: w ? p : nw).' wincmd w'
740717 noa exe win_id2win (w != a: w ? w : nw).' wincmd w'
741- noa call s: CloseWin (a: w )
742- call s: RestWinVars (nw, vars)
718+ noa exe win_id2win (a: w ).' close!'
719+ call remove (col , i )
720+ call s: Layout (col )
721+ call s: Layout (s: WinCol (nw))
743722 endif
744723endfunc
745724
746725function s: NewCol (w )
726+ let col = s: WinCol (a: w )
747727 let w = win_getid ()
748728 let p = win_getid (winnr (' #' ))
749729 noa exe win_id2win (a: w ).' wincmd w'
@@ -753,7 +733,9 @@ function s:NewCol(w)
753733 endif
754734 noa exe win_id2win (p ).' wincmd w'
755735 noa exe win_id2win (w ).' wincmd w'
756- call s: CloseWin (a: w )
736+ noa exe win_id2win (a: w ).' close!'
737+ call remove (col , index (col , a: w ))
738+ call s: Layout (col )
757739endfunc
758740
759741function s: Scroll (topline)
@@ -762,7 +744,7 @@ function s:Scroll(topline)
762744 call winrestview (v )
763745endfunc
764746
765- function s: FitHeight (w , l )
747+ function s: LineHeight (w , l )
766748 " Only works without fold, number & sign columns and just with
767749 " line wrapping, e.g. 'nobreakindent', 'nolinebreak' & 'nolist'
768750 let lw = ! getwinvar (a: w , ' &wrap' ) ? 1 :
@@ -771,42 +753,62 @@ function s:FitHeight(w, l)
771753 return (max ([lw , 1 ]) + ww - 1 ) / ww
772754endfunc
773755
774- function s: Fit (w , h , ... )
775- if fnamemodify (bufname (winbufnr (a: w )), ' :t' ) == ' guide'
776- let h = s: FitHeight (a: w , 1 )
777- if a: 0 == 0 || a: w != a: 1 || h != winheight (a: w )
778- call win_execute (a: w , ' normal! gg' )
779- return h
756+ function s: Fit (col )
757+ for w in a: col
758+ if s: Minimized (w )
759+ continue
780760 endif
781- endif
782- let h = 0
783- let top = line (' $' , a: w ) + 1
784- while top > 1
785- let h += s: FitHeight (a: w , top - 1 )
786- if h > a: h
787- break
761+ let h = 0
762+ let wh = winheight (w )
763+ let top = line (' $' , w ) + 1
764+ while top > 1
765+ let h += s: LineHeight (w , top - 1 )
766+ if h > wh
767+ break
768+ endif
769+ let top -= 1
770+ endwhile
771+ if top < getwininfo (w )[0 ].topline
772+ call win_execute (w , ' noa call s:Scroll(' .top .' )' )
788773 endif
789- let top -= 1
790- endwhile
791- call timer_start (0 , {_ - >
792- \ win_execute (a: w , ' noa call s:Scroll(' .top .' )' )})
793- return min ([h , a: h ])
774+ endfor
794775endfunc
795776
796- function s: Zoom (w )
797- let col = s: WinCol (a: w )
798- let col = slice (col , 0 , index (col , a: w ) + 1 )
799- let h = reduce (col , {s , w - > s + winheight (w )}, 0 )
800- let n = len (col )
801- for w in reverse (col )
802- let s = s: Fit (w , h / n , a: w )
777+ function s: Layout (col )
778+ let h = reduce (a: col , {s , w - > s + winheight (w )}, 0 )
779+ let n = len (a: col )
780+ for w in reverse (a: col )
803781 if n == 1
804782 break
805783 endif
784+ if s: Minimized (w )
785+ if fnamemodify (bufname (winbufnr (w )), ' :t' ) == ' guide'
786+ call win_execute (w , ' normal! gg' )
787+ endif
788+ let s = 1
789+ else
790+ let s = h / (n + n * (n > s: tops ))
791+ endif
806792 call win_move_statusline (win_id2win (w ) - 1 , winheight (w ) - s )
807793 let h -= s
808794 let n -= 1
809795 endfor
796+ call timer_start (0 , {_ - > s: Fit (a: col )})
797+ endfunc
798+
799+ function s: Minimized (w )
800+ let isguide = fnamemodify (bufname (winbufnr (a: w )), ' :t' ) == ' guide'
801+ return get (s: minimized , a: w , isguide)
802+ endfunc
803+
804+ function s: Minimize (w )
805+ let col = s: WinCol (a: w )
806+ if index (col , a: w ) == 0
807+ let s: tops = s: tops == 1 ? 2 : 1
808+ else
809+ let s: minimized [a: w ] = ! s: Minimized (a: w )
810+ endif
811+ call s: Layout (col )
810812endfunc
811813
812814function s: InSel ()
@@ -856,7 +858,7 @@ function s:MiddleRelease(click)
856858 \ p .winrow <= winheight (p .winid)
857859 " off the statusline
858860 elseif p .wincol < 3
859- call s: CloseWin (p .winid)
861+ exe win_id2win (p .winid). ' close! '
860862 endif
861863 return
862864 endif
@@ -894,7 +896,7 @@ function s:RightRelease(click)
894896 elseif p .wincol < 3
895897 call s: NewCol (p .winid)
896898 else
897- call s: Zoom (p .winid)
899+ call s: Minimize (p .winid)
898900 endif
899901 return
900902 endif
@@ -1171,6 +1173,20 @@ function s:BufWinLeave()
11711173 endif
11721174endfunc
11731175
1176+ function s: WinClosed (w )
1177+ if has_key (s: minimized , a: w )
1178+ call remove (s: minimized , a: w )
1179+ endif
1180+ let col = s: WinCol (a: w )
1181+ call remove (col , index (col , a: w ))
1182+ call timer_start (0 , {_ - > s: Layout (col )})
1183+ endfunc
1184+
1185+ function s: WinNew (w )
1186+ let col = s: WinCol (a: w )
1187+ call timer_start (0 , {_ - > s: Layout (col )})
1188+ endfunc
1189+
11741190augroup acme_vim
11751191au !
11761192au BufEnter * call s: ListDir ()
@@ -1180,6 +1196,8 @@ au TextChanged,TextChangedI guide setl nomodified
11801196au VimEnter * call s: ReloadDirs (winnr ())
11811197au VimResized * call s: ReloadDirs (0 )
11821198au WinResized * call s: ReloadDirs (0 )
1199+ au WinClosed * call s: WinClosed (str2nr (expand (" <amatch>" )))
1200+ au WinNew * call s: WinNew (win_getid ())
11831201augroup END
11841202
11851203if exists (" s:ctrlexe" )
@@ -1199,7 +1217,9 @@ let s:editbufs = {}
11991217let s: editcids = {}
12001218let s: editcmds = {}
12011219let s: jobs = []
1220+ let s: minimized = {}
12021221let s: scratch = {}
1222+ let s: tops = 1
12031223
12041224if s: ctrlexe != ' '
12051225 let s: ctrl = job_start ([s: ctrlexe ], {
0 commit comments