'How to make an abbreviation that expands without pressing space
I am trying to replicate the behavior of beg abbreviation shown on the page https://castel.dev/post/lecture-notes-1/ with vimscript. That means I want to make it so that when I type "beg" in insert mode at the beginning of the line, it calls a function that i choose.
I tried to make it with iabbrev, but it doesn't expand until i hit space, and space is typed after my abbreviation. It also doesn't recognize if it is the beginning of a line.
Another approach I tried is with an auto command. I added to my init.vim the following
function SayHello ()
if (getline('.') =~ "\s*beg$")
s/^\(\s*\)beg/\1\\begin{}\r\r\\end{}/
endif
endfunction
autocmd TextChangedI *.tex call SayHello ()
This almost works, but for one problem. It doesn't work if the autocomplete popup is active, which is always because of a plugin I use. So the effect of this code is that as i first type beg, there is no effect, but if i backspace one letter and add it again, it works as intended. I tried to remedy it by adding the command
autocmd CompleteChanged *.tex call SayHello ()
so that it works anyway if there is autocomplete. Unfortunately it doesn't work, because it tries to edit the buffer of the popup. I tried making the function exit the popup to no effect.
How can I make it work like on the site?
Especially useful would be knowing how to use the TextChangedI command regardless of autocomplete because that would make other useful things possible.
Solution 1:[1]
Create a harmless insert mode mapping:
inoremap beg begIt inserts
begwhen you typebeg. Cool.Turn it into an equally harmless "expression mapping":
inoremap <expr> beg 'beg'In an expression mapping, the right-hand side is an expression that is evaluated when you press the left-hand side in order to produce the macro that is going to be executed for you. Here, the expression is the string
begso the mapping works just like the first one.Experiment with logic in the RHS:
inoremap <expr> beg &filetype == 'foo' ? 'beg' : 'geb'Here, you either get a
begor ageb, depending on the current filetype. Cool, it's getting interesting!Make it insert a crude snippet only when at the beginning of a line:
inoremap <expr> beg col('.') == 1 ? 'begin{}<CR>end{}<C-o>O' : 'beg'Make it possible to name the environment "dynamically":
inoremap <expr> beg col('.') == 1 ? substitute('\begin{+++}<CR>\end{+++}','+++',input('environment: '),'g').'<C-o>O' : 'beg'
OK. It works, but it feels clunky.
That's where one usually starts to wonder whether it is actually worth it to roll one's own when existing plugins already handle all that much more elegantly.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | romainl |


