0

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
  endif      

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?

5
  • Try with < instead of <#. Commented Jul 14, 2016 at 20:55
  • I actually realized what it is: the comments. Going to edit my question...
    – hgiesel
    Commented Jul 14, 2016 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
    Commented Jul 14, 2016 at 21:10
  • Ok, I guess I discovered another VimL idiosyncrasy...
    – hgiesel
    Commented Jul 14, 2016 at 21:13
  • 1
    this is not possible Commented Jul 14, 2016 at 21:30

1 Answer 1

2

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])

Refactor

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
    endif
  endfor
  return 0
endfunction

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()
2
  • :h <# brings me right to the description of the <# operator.
    – hgiesel
    Commented Jul 14, 2016 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 Commented Jul 14, 2016 at 21:53

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.