Reputation: 3172
I am getting the character under the cursor in vimscript the following way:
getline('.')[col('.')-1]
It works exactly like it should, however there is something I dislike. consider this []
the cursor. When there is a bracket next to the cursor like so:
}[]
, ][]
, )[]
or {[]
the cursor actually returns the bracket. What do I have to set so it will always return the character exactly under the cursor or atleast ignore if there is a bracket to it's left?
Note: I suspect that it might have to do with the brackets highlight, though I am not sure.
Note2: for the situation to occur there has to be a matching bracket.
Upvotes: 20
Views: 11057
Reputation: 1551
Try this one, it works for both ascii and multi-byte characters.
echo strpart(getline('.'), col('.')-1, 1, 1)
Brief explanation: with strpart(s, idx, 1, 1)
With the last 1, it says, given me 1 character (instead of 1 byte) starting
at byte idx.
This is probably fastest version, no regex, no copy. (Vimscript string is not reference counted, thus slicing will create a copy.)
Upvotes: 0
Reputation: 28369
Another way to get the character index under cursor that deal with both ASCII and non-ASCII characters is the like the following:
function! CharAtIdx(str, idx) abort
" Get char at idx from str. Note that this is based on character index
" instead of the byte index.
return strcharpart(a:str, a:idx, 1)
endfunction
function! CursorCharIdx() abort
" A more concise way to get character index under cursor.
let cursor_byte_idx = col('.')
if cursor_byte_idx == 1
return 0
endif
let pre_cursor_text = getline('.')[:col('.')-2]
return strchars(pre_cursor_text)
endfunction
Then if you want to get char under cursor, use the following command:
let cur_char_idx = CursorCharIdx()
let cur_char = CharAtIdx(getline('.'), cur_char_idx)
See also this post on how to get pre-cursor char.
Upvotes: 0
Reputation: 181
nr2char(strgetchar(getline('.')[col('.') - 1:], 0))
or
strcharpart(getline('.')[col('.') - 1:], 0, 1)
Upvotes: 6
Reputation: 172590
Though I cannot reproduce the problem you're describing, there's another problem with your code: Because of the string indexing (and this is one of the uglier sides of Vimscript), it only works with single-byte characters, but will fail to capture chars like Ä
or 𠔻
(depending on the encoding used). This is a better way of capturing the character under the cursor:
:echo matchstr(getline('.'), '\%' . col('.') . 'c.')
Edit: Since about Vim 7.4.1742, Vim has new strgetchar()
and strcharpart()
functions that work with character indexes, not byte addressing. This is helpful in many circumstances, but not here, because you still can only get the byte-index position of the cursor (or the screen column with virtcol()
, but that's not the same as character index).
Upvotes: 35