but what do these two lines do?
let c = nr2char(getchar(0))
return (c =~ a:pat) ? '' : c
The first line consumes a character from the typeahead buffer; if the latter is empty, getchar()
doesn't wait for a character to be written inside, thanks to the optional 0
argument.
The second line spits back the consumed character, but only if it's not a whitespace.
More details:
fu s:eat_space()
let c = nr2char(getchar(0))
return c =~# '\s' ? '' : c
endfu
inorea <silent> if if ()<left><c-r>=<sid>eat_space()<cr>
Here's what happens:
you type i
; it's written in the typeahead buffer, then executed (i.e. inserted in your buffer)
you type f
; same thing
you type space which should be a non-keyword character:
it's written in the typeahead buffer
Vim checks whether the text before the cursor matches an abbreviation
it finds one; as a result, it removes its lhs from your buffer, and
inserts its rhs into the typeahead; i.e. if
is removed from your buffer,
and if ()<left><c-r>=<sid>eat_space()<cr>
is inserted in the typeahead
in front of the space
the typeahead is executed; when <c-r>=<sid>eat_space()<cr>
is executed,
s:eat_space()
consumes the last remaining space from the typeahead (via getchar()
)
the typeahead buffer is now empty, and the space is not executed
(i.e. inserted in your buffer)
You may wonder why if ()...
is written in the typeahead buffer. I think it has to, because if you define a recursive abbreviation (iab
vs inorea
), mappings are applied; that can only happen in the typeahead buffer.
You could probably replace this line:
return c =~# '\s' ? '' : c
With:
return ''
However, if you were to use s:eat_space()
in another abbreviation, and for some reason you wanted to use it in a different position in the rhs, the function could wrongly consume some non-whitespace character which would be unexpected. So the current statement, while not necessary here, is a good practice.
The fact that getchar()
consumes the typeahead buffer is not really documented, but it's briefly mentioned at :h :map-<expr> /typeahead
:
You can use getchar(), it consumes typeahead if there is any.
How does getchar(0) work? Every time I try that I get 0, so what is that doing?
From :h getchar()
:
If [expr] is 0, only get a character when one is available.
Return zero otherwise.
No character is available in the typeahead buffer when you run :echo getchar(0)
, so 0 is returned.