3

Suppose i've got two different positions in a buffer returned by getpos() function:

p1 = getpos("v")
p2 = getpos(".")

Is there a simple or elegant way to find out which one is before the other in the buffer? Doing

if p1[1] < p2[1] || (p1[1] == p2[1] && p1[2] < p2[2])
  ...

each time looks ugly.

Alternatively, can i get the absolute positions -- the number of characters from the start of the file?

6
  • 2
    What are you trying to do? (XY Problem)
    – mMontu
    Commented Apr 7, 2016 at 11:02
  • 2
    Currently i want to find out if the cursor is at the beginning or at the end of the visual selection. But this is also a question about working with cursor positions in Vim script. Since there is apparently no separate site about programming Vim in Vim script, i am asking it here.
    – Alexey
    Commented Apr 7, 2016 at 11:22
  • 4
    Your comparison doesn't look that ugly, but to avoid rewriting it you could wrap it in a function.
    – statox
    Commented Apr 7, 2016 at 11:34
  • 1
    The X problem is that i want to live happily, to have my Vim finely configured, and to master Vim script and all other programming languages.
    – Alexey
    Commented Apr 7, 2016 at 13:31
  • 1
    On a smaller scale, i want my word-based motions in Visual mode to behave differently based on whether the cursor is at the beginning or at the end of the selection.
    – Alexey
    Commented Apr 7, 2016 at 13:33

2 Answers 2

1

Alternatively, can i get the absolute positions -- the number of characters from the start of the file?

Yes, you can get that from the wordcount() function (see :h wordcount).

In your case, you would want wordcount().cursor_bytes.

For the problem you are having, simply call this function when visual mode is entered, then call it again when the cursor is moved and compare the two to see if the current position is before or after the initial position.

0

That's also what I've been doing so far in my library plugin

" Function: lh#position#is_before                 {{{3
" @param[in] positions as those returned from |getpos()|
" @return whether lhs_pos is before rhs_pos
function! lh#position#is_before(lhs_pos, rhs_pos) abort
  if a:lhs_pos[0] != a:rhs_pos[0]
    throw "Positions from incompatible buffers can't be ordered"
  endif
  "1 test lines
  "2 test cols
  let before
        \ = (a:lhs_pos[1] == a:rhs_pos[1])
        \ ? (a:lhs_pos[2] < a:rhs_pos[2])
        \ : (a:lhs_pos[1] < a:rhs_pos[1])
  return before
endfunction

" Function: lh#position#compare(lhs_pos, rhs_pos) {{{3
function! lh#position#compare(lhs_pos, rhs_pos) abort
  if a:lhs_pos[0] != a:rhs_pos[0]
    throw "Positions from incompatible buffers can't be ordered"
  endif
  "1 test lines
  "2 test cols
  let res
        \ = (a:lhs_pos[1] == a:rhs_pos[1])
        \ ? (a:lhs_pos[2] - a:rhs_pos[2])
        \ : (a:lhs_pos[1] - a:rhs_pos[1])
  return res
endfunction

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.