Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get "usable" window width in vim script

Tags:

vim

get the width of text field in vim

How do I get the width of 3 (marked with green color in the image) in vim script?

If there is no signs column, and there are no other "special columns", I can get it with

winwidth(0) - (max([len(line('$')), &numberwidth-1]) + 1)

like image 536
Not an ID Avatar asked Oct 11 '14 14:10

Not an ID


3 Answers

I think, you should be able to get that width using:

:set virtualedit=all
:norm! g$
:echo virtcol('.')

Alternatively, you could check, whether a signcolumn is present (e.g. using redir)

:redir =>a |exe "sil sign place buffer=".bufnr('')|redir end
:let signlist=split(a, '\n')
:let width=winwidth(0) - ((&number||&relativenumber) ? &numberwidth : 0) - &foldcolumn - (len(signlist) > 1 ? 2 : 0)
like image 71
Christian Brabandt Avatar answered Nov 12 '22 00:11

Christian Brabandt


Answering because I can't comment yet:

Christian's answer gives the wrong result in the case that the actual number of lines in the file exceeds &numberwidth (because &numberwidth is just a minimum, as kshenoy pointed out). The fix is pretty simple, though, just take the max() of &numberwidth and the number of digits in the last line in the buffer (plus one to account for the padding vim adds):

redir =>a | exe "silent sign place buffer=".bufnr('') | redir end
let signlist = split(a, '\n')
let lineno_cols = max([&numberwidth, strlen(line('$')) + 1])
return winwidth(0)
            \ - &foldcolumn
            \ - ((&number || &relativenumber) ? lineno_cols : 0)
            \ - (len(signlist) > 2 ? 2 : 0)
like image 45
Kale Kundert Avatar answered Nov 12 '22 00:11

Kale Kundert


Kale's answer corrected one corner case where the number of lines is exceeding what &numberwidth can display. Here I fix another corner case where the signcolumn option is not set to auto

function! BufWidth()
  let width = winwidth(0)
  let numberwidth = max([&numberwidth, strlen(line('$'))+1])
  let numwidth = (&number || &relativenumber)? numberwidth : 0
  let foldwidth = &foldcolumn

  if &signcolumn == 'yes'
    let signwidth = 2
  elseif &signcolumn == 'auto'
    let signs = execute(printf('sign place buffer=%d', bufnr('')))
    let signs = split(signs, "\n")
    let signwidth = len(signs)>2? 2: 0
  else
    let signwidth = 0
  endif
  return width - numwidth - foldwidth - signwidth
endfunction
like image 4
doraemon Avatar answered Nov 11 '22 23:11

doraemon