4

I regularly press q to exit the -- more -- prompt in Vim.

I often mistakenly use this same key to exit the hit-enter prompt, which then starts recording a macro after a subsequent key is typed.

I'd like to map q to <cr> when the hit-enter prompt is shown.

I unsuccessfully tried the following mapping:

noremap <expr> q mode() ==# 'r' ? "\<cr>" : 'q'

However, mode() cannot be used in this context to check for the hit-enter prompt. As mentioned in the documentation, in most uses outside of 'statusline' and remote_expr, mode() "always returns c or n."

  • 2
    From :help mode(): "This is useful in the 'statusline' option or when used with remote_expr(). In most other places it always returns c or n." – filbranden May 6 at 1:38
  • 1
    @filbranden, Thanks! I've updated the post to reflect this. – Daniel S. May 6 at 2:01
  • 1
    The issue is not due to mode(); it can be used in an <expr> mapping. The issue is that mappings are ignored. From :h pager: Note: The typed key is directly obtained from the terminal, it is not mapped and typeahead is ignored. Slightly related issue. – user938271 May 6 at 16:13
  • 1
    @user938271, for the mapping I'm interested in, mode() would ideally return r for detecting the hit-enter prompt. However, I've verified that within the <expr> mapping, at the hit-enter prompt, mode() is returning n, as opposed to r. Additionally, I've verified that mappings are not ignored at the hit-enter prompt. For example, with the mapping :noremap q :qall!<cr>, vim exits when pressing q at the hit-enter prompt. – Daniel S. May 6 at 19:35
  • 1
    @user938271, it appears that mappings are ignored for the -- more -- prompt, but the mapping I've attempted is for the hit-enter prompt. – Daniel S. May 6 at 19:42
3

It's a hack, but you could try this:

augroup hit_enter_prompt | au!
    if has('nvim')
        au CmdlineLeave : call s:hit_enter_prompt_no_recording()
    else
        au CmdlineLeave : call timer_start(0, {-> s:hit_enter_prompt_no_recording()})
    endif
augroup END
fu s:hit_enter_prompt_no_recording() abort
    if has('nvim')
        nno q <c-\><c-n>
        return timer_start(0, {-> execute('nunmap q', 'silent!')})
    endif
    if mode() isnot# 'r' | return | endif
    nno <expr> q execute('nunmap q', 'silent!')[-1]
    if exists('##SafeState')
        au SafeState * ++once sil! nunmap q
    else
        let q = {}
        let q.timer = timer_start(10, {-> mode() isnot# 'r' && q.nunmap()}, {'repeat': -1})
        fu q.nunmap() abort
            call timer_stop(self.timer)
            sil! nunmap q
        endfu
    endif
endfu
| improve this answer | |

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.