8

I have a custom save function, and bound it to :w by using an abbreviation:

cabbrev w call SaveBuffer()

This works, but I ran into issues when I wanted to reference window local variables because w: triggers the abbreviation. How can I get abbreviations to only trigger at the beginning of the command-line?

1 Answer 1

8

First and foremost, for most cases like this you'll want to use a command! instead of an abbreviation. This allows you to create a custom command-line command that will not mess up other inputs.

However, you can't override default vim commands with command!. So an abbreviation is probably acceptable here.

Abbreviations can use the special <expr> argument which allows an expression to be used in the right hand side. Using this we can construct an abbreviation that only triggers at the beginning of the line:

cnoreabbrev <expr> w (getcmdtype() == ':' && getcmdline() =~ '^w$')? 'call SaveBuffer()' : 'w'
  • getcmdtype() == ':' Ensures that you are in command-line mode and not search mode (or others).
  • getcmdline() Gets the text that is currently in the command line.
  • =~ '^w$' A regex that only matches if there is a "w" and nothing else.
  • ()? '' : '' A turnary statement that will use the first '' if the expression in the parentheses is true, or the second '' if it is false.

This abbreviation will technically trigger all the time, but in the other cases it simply replaces w with w so no harm done.

For more info see :help E174 (for help on how to use command!) and :help :map-<expr>.

3
  • 5
    This abbreviation would trigger if you searched via /w as well. It would be best to also check getcmdtype() == ':'. e.g. cnoreabbrev <expr> w getcmdtype() == ":" && getcmdline() == 'w' ? 'call SaveBuffer()' : 'w'. There is also cmdalias.vim if you like plugins better. Commented Jul 10, 2017 at 19:04
  • Ah, I hadn't run into that one, but that's a good point! Thanks, I'll update.
    – Tumbler41
    Commented Jul 10, 2017 at 19:06
  • @PeterRincker Many thanks for introducing cmdalias.vim. Simply put au VimEnter * Alias w call SaveBuffer() in .vimrc and it works decently.
    – Arnie97
    Commented May 19, 2020 at 3:52

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.