I have this rather big if statement to test if a certain cursor position is within two other cursor positions

Altogether it looks like this:

  " a
  " thecursor
  " b
  if (a:a[l:ROW] <# a:thecursor[l:ROW] && a:thecursor[l:ROW] <# a:b[l:ROW]) ||

    " a
    " thecursor a
          \ (a:a[l:ROW] <# a:thecursor[l:ROW] && a:thecursor[l:ROW] ==# a:b[l:ROW] &&
          \ a:thecursor[l:COL] <# a:b[l:COL]) ||

    " a thecursor
    " a
          \ (a:thecursor[l:ROW] ==# a:a[l:ROW] && a:c_a[l:COL] <# a:thecursor[l:COL] &&
          \ a:thecursor[l:ROW] <# a:b[l:ROW]) ||

    " a thecursor b
          \ (a:thecursor[l:ROW] ==# a:a[l:ROW] && a:thecursor[l:ROW] ==# a:b[l:ROW] &&
          \ a:a[l:COL] <# a:thecursor[l:COL] && a:thecursor[l:COL] <# a:b[l:COL])
    return v:true

However when executed I get this error:

E15: Invalid expression: (a:a[l:ROW] <# a:thecursor[l:ROW] && a:thecursor[l:ROW] <# a:b[l:ROW]) ||

It is because you can't enter comments within a statement that is continued using \. Is there some way to still use comments in such a situation?

  • Try with < instead of <#. – Karl Yngve Lervåg Jul 14 '16 at 20:55
  • I actually realized what it is: the comments. Going to edit my question... – hgiesel Jul 14 '16 at 21:02
  • 1
    AFIK if you can't put the comment in the middle of the expression normally, you can't put them in the middle when it's split either. – Tumbler41 Jul 14 '16 at 21:10
  • Ok, I guess I discovered another VimL idiosyncrasy... – hgiesel Jul 14 '16 at 21:13
  • 1
    this is not possible – Christian Brabandt Jul 14 '16 at 21:30

You do not need to compare numbers with any string sensitivity. You are receiving this error due to lack of escaping new lines with \ and your use of comments.

Comments in expression

Vim will not understand the expression properly if you try and sandwich a comment inside of it. It would be much better to create a set of temporary variables that are well named for each portion and comment those. Example of one such variable:

" a
" thecursor
" b
let between_the_lines = a:a[l:ROW] < a:thecursor[l:ROW] && a:thecursor[l:ROW] < a:b[l:ROW])


General rule of thumb: If some portion of code is repetitive and hard to understand, then it is time to refactor.

Let's create a compare function, s:cmp, that takes in lists and compares one list another to one item at a time returning -1 (less than), 0 (equal), or 1 (greater than).

function! s:cmp(a, b)
  for i in range(len(a:a))
    if a:a[i] < a:b[i]
      return -1
    elseif a:a[i] > a:b[i]
      return 1
  return 0

By cleverly crafting our List in the form [LNUM, COL] we can use our s:cmp function to compare different positions in the file.

Example of using this code to determine if the cursor is within the visual selection:

let cursor = getpos('.')[1:2]
let v_start = getpos("'<")[1:2]
let v_end = getpos("'>")[1:2]

echo s:cmp(v_start, cursor) <= 0 && s:cmp(cursor, v_end) <= 0

I imagine this code is far simpler to understand when you come back to it at later time.

For more help

:h user-function
:h getpos()
:h List
:h range()
:h len()
| improve this answer | |
  • :h <# brings me right to the description of the <# operator. – hgiesel Jul 14 '16 at 21:48
  • @hgiesel, You are correct <# does exist. However you do not need it in this case as these values are Number's. The issue is the lack of escaping new lines and comments. Do not mix them – Peter Rincker Jul 14 '16 at 21:53

Your Answer

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

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