1

How can I adopt side panel plugins (TagBar, TagList, NerdTree, etc) width to current screen aspect ratio?

Using Vim with many different computers makes me a bit trouble to write one portable config for all of them. The problem is aspect ratio of screen. It varies from 4:3 - 1024x768 to 16:9 - 1920x1080. What I want is stable 80 columns for "main" window and rest for panels.

+-----------+-----------------------+-----------+
| NERD Tree |  Main content window  |  Tag Bar  |
|           |  80 columns width     |           |
|           |                       |           |
|           |                       |           |
|           |                       |           |
|           |                       |           |
+-----------+-----------------------+-----------+

Now I have a local variable in .vimrc:

let s:side_panel_width = 24
let g:NERDTreeWinSize = s:side_panel_width
let g:tagbar_width = s:side_panel_width

But it's ugly solution, since I must have many special configs with different values. Another option I found is winwidth(0) Vim function. So I think it is possible to write function, that calculates side panel size for current configuration.

Have somebody already solved this problem? Or can you suggest better options? By the way, how should I call this function - autocmd on VimEnter - or something else?

2
  • 2
    While you’re free to use the setup that works best for you, my advice would actually be not to bolt the side-panels on. Open them when you need them, and leave the stuff youre editing in focus when you dont.
    – D. Ben Knoble
    Oct 4, 2020 at 13:21
  • D. Ben Knoble, thanks for advice. Side panels do one more useful thing for me - they center "main" window, so I do not need see on the left edge of monitor most of time. It is really annoying to turn head left for hours. I tried distraction free plugin Goyo, but it worked bad with my colorscheme Solarized, so I stopped on side panels.
    – Dmitry
    Oct 4, 2020 at 17:45

2 Answers 2

1

Wrote function that satisfied my needs. It checks total screen width and sets width, position and show-on-start of panels depending on result.

" Adjust side panels to screen resolution and ratio.
func AdaptToScreenRatio()
  let screen_width = &columns " full screen size
  let main_window_width = 82 + &foldcolumn " desired main window size

  if &number
    let main_window_width += &numberwidth
  endif

  let rest_width = screen_width - main_window_width " free space size
  let min_panel_width = 20 " good panel size for small screens
  let open_panel_on_startup = 1 " show panel when vim starts?

  if rest_width > 40 " wide screen, enough for 2 panels
    let panel_width = rest_width / 2
    let g:NERDTreeWinSize = panel_width
    let g:tagbar_width = panel_width
    let g:tagbar_left = 0
  else
    " Average screen, enough for 1 panel.
    let g:tagbar_left = 1
    let g:NERDTreeWinSize = min_panel_width
    let g:tagbar_width = min_panel_width
    " Small screen, do not open panel at all.
    if rest_width < 20
      let open_panel_on_startup = 0
    endif
  endif

  if open_panel_on_startup
    NERDTree
    wincmd p " move cursor to main window
  endif
endfunc

autocmd VimEnter,TabNew * call AdaptToScreenRatio()

Note: useful function to test current window (split) length is echo winwidth(0), but it shows length without numberwidth value.

P.S. there is one bug, I don't know how to fix. If you have left/right dock with applications list (like on Ubuntu 18 or 20), then GVim will get incorrect columns value on VimEnter event. It calculates total screen width in columns. But when GVim is drawn, the columns value is less to fit dock. So panels would be a bit wider then desired. The workaround here is to call AdaptToScreenRatio() manually, but still annoying...

1
  • Rather than calling it manually, you could just call it later. There's a bunch of ways you could do this: one simple one is to use a timer
    – Rich
    Jul 4, 2022 at 8:51
0

I have a similiar use case, where I create a window which should be leftmost of a certain size, scaling with the resolution.

Just after opening the window, I apply this command to the window (so I recommend to deploy this by filetype):

execute 'vertical resize ' . string(&columns * 0.13)

You could also write a function which hooks into WinNew, restricting this call to declared windows. Hope this helps!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.