In one of my vim scripts I require the column of the last non-whitespace character of the current line and the column of the last character of the current line (when the current line is wrapped into two or more lines) I would like to get the column of the last character on the same visual line.

How could I acquire these columns?



Cursor marked as: [ ]
Whitespace marked as: X

Expected result:

  • Column of last e in first line
  • Column of last X in first line

Here's something I cooked up. It uses g$ to find the end of the visual line.

function! GetLastVisualColumn(nonBlankFlag)
   " Save the original spot
   let originalPos = getpos('.')

   " Put cursor at last character on visual line
   normal! g$

   " If caller specified nonBank and the cursor is on whitespace then jump to the
   "   most recent end of word
   if (a:nonBlankFlag)
      if matchstr(getline('.'), '\%' . col('.') . 'c.') =~ '\s'
         " This black magic just finds out if the character under the cursor is whitespace.
         normal! ge

   " Save column
   let column = getpos('.')[2]

   " Go back to original position
   call setpos('.', originalPos)

   return column

It moves the cursor around (and then puts it back), but as longs as that's not an issue it should work for you. Pass it 0 for end of visual line, or 1 for last non-blank character on the visual line.

For more info see: :h normal, :h g$, :h matchstr, :h getpos(), and :h setpos().

  • You could also use getpos() and setpos() instead of m' and `` so the mark is not changed without the user knowing why. – statox Sep 22 '16 at 8:06
  • 1
    Good point. I'll update it. – Tumbler41 Sep 22 '16 at 13:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy