3

I'm using a really clever plugin that changes the line number style (relative/normal) contextually. Basically when you enter insert mode you have normal line numbers and when you leave insert mode it switches to relative numbers. A missing feature is to have normal line numbers when your in command-line mode.

Looking at how it is implemented it uses Vim's events system to trigger the change. I've looked but Vim's documentation seems to only offer events on insert enter/leave. (Funny aside: UserGettingBored).

At first I thought of adding nnoremap : :call MyFunc()<CR>: which works on enter but not on exit. Also relying on a map seems flaky.

How do I trigger a function when the user enters command-line mode (presses :)? And how do I trigger a function when the user leaves this mode (presses enter, ctrlc or esc)?

  • 1
    Why do you want to trigger a function when entering / leaving command mode, rather than entering / leaving insert mode? – lcd047 Jun 4 '15 at 12:59
  • If relativenumbers are on in normal mode and I hit : then my range (.,+3) is more complicated then actual line numbers which I would see if norelativenumbers was set. and so the request that when switching into command mode to swap the relative numbers setting and put it back when leaving. This is how the plugin works for insert/normal mode switching but vim doesn't provide a normal/command event. – Sukima Jun 4 '15 at 15:38
  • Note that the 'command-mode' term, while not widely used, actually means 'normal mode'. What you want is 'command-line mode' (since you add the : to explain, the idea gets through, though). – VanLaser Jun 5 '15 at 8:13
  • I edited it. To be fair in my 20 some years reading the Vim docs I don't recall a reference to command-line mode. I have seen normal, insert, command (from cmap or command mapping style), and ex modes. The last (ex) is usually over loaded to mean either the command line from : or the batch mode from Q. – Sukima Jun 5 '15 at 12:29
  • Well, just run these commands in vim: :h command-mode :h command-line-mode – VanLaser Jun 5 '15 at 12:31
6

You can use mappings to override :, /, and ? to do some action first:

nnoremap : :set number<CR>:
nnoremap / :set number<CR>/
nnoremap ? :set number<CR>?

Because we use non-recursive mappings, the : at the end will call the original built-in :.

To hide the numbers again, you can use command-line mappings to override <CR>, <Esc>, and <C-c>:

cnoremap <silent> <CR> <CR>:set nonumber<CR>
cnoremap <silent> <Esc> <Esc>:set nonumber<CR>
cnoremap <silent> <C-c> <C-c>:set nonumber<CR>

This same trick should also work with the commands from your plugin.

  • Does this misfire when using the expression register in Command-line mode? – tommcdo Jun 4 '15 at 13:14
  • Unfortunately this is not perfect. It will now trigger the <Esc> map when you press the up arrow (since they use terminal ESC sequences). – Sukima Jun 5 '15 at 1:25
  • @Sukima Confirmed ... I need to meditate on a solution... – Martin Tournoij Jun 5 '15 at 8:51
5

As of version 8.0.1206, Vim supports this with CmdlineEnter and CmdlineLeave.

1

I haven't tried it for your situation, but likely you're looking for 'doautocmd'. Here's the relevant info from :h doauto

                    *:do* *:doau* *:doautocmd* *E217*
:do[autocmd] [group] {event} [fname]
            Apply the autocommands matching [fname] (default:
            current file name) for {event} to the current buffer.
            You can use this when the current file name does not
            match the right pattern, after changing settings, or
            to execute autocommands for a certain event.
            It's possible to use this inside an autocommand too,
            so you can base the autocommands for one extension on
            another extension.  Example:
                :au Bufenter *.cpp so ~/.vimrc_cpp
                :au Bufenter *.cpp doau BufEnter x.c
            Be careful to avoid endless loops.  See
            |autocmd-nested|.

            When the [group] argument is not given, Vim executes
            the autocommands for all groups.  When the [group]
            argument is included, Vim executes only the matching
            autocommands for that group.  Note: if you use an
            undefined group name, Vim gives you an error message.

            After applying the autocommands the modelines are
            processed, so that their settings overrule the
            settings from autocommands, like what happens when
            editing a file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.