8

I want to make a mapping that does the following:

nnoremap <F1> oHello, (user inputs their name. Ex. Jason). You have a very nice name.<ESC>

This mapping should make a non-recursive map to F1 that starts a new line in insert mode. Next it types "Hello, " then waits for the user to type their name and then enter or some other signal command to say they are done. After that input the map moves forward and completes the statement with "You have a very nice name." then exits insert mode with ESC.

2 Answers 2

10

You can use a mapping with the <expr> flag to achieve this. Mappings with the <expr> flag will evaluate the right hand side of the mapping as an expression and then apply the result as key strokes. This can be combined with the input() function to achieve what you want. Here is your mapping implemented with these features:

nnoremap <expr> <F1> "oHello, " . input("Please give your name: ") . ". You have a very nice name.\<ESC>"

Here is a break down of what happens:

  • nnoremap <expr> - create a non-recursive expr mapping
  • <F1> - the key you press to activate the mapping
  • "oHello, " . input("Please give you name: ") . ". You have a very nice name.\<ESC>" - concatenates the result of the input function with the rest of the mapping. It is necessary to escape <ESC> because if you don't, it won't be interpreted as the escape key.

See :help input() and :help :map-<expr> for more.

5
  • Is there a way I could make it type out the "Hello, " before I have answered the input prompt? Commented Jan 2, 2016 at 18:45
  • @JasonBasanese As far as I know, no. (at least using this method) Commented Jan 2, 2016 at 19:04
  • @JasonBasanese I don't know if there's another way of doing it, but you could try this: paste.debian.net/plain/359252
    – saginaw
    Commented Jan 2, 2016 at 19:34
  • @saginaw I figured it would be possible, but not the way I was doing it. Also, you can use vpaste.net for vimscript syntax highlighting. Commented Jan 2, 2016 at 19:50
  • @EvergreenTree Thank you, I didn't know this service, I will use it for the syntax highlighting. Yes, the problem seems to come from the input() function because when you call it from a mapping it consumes the remaining characters from it. At the very end of :help input(), they give an example of how to solve the issue, but it involves defining a function and calling inputsave() and inputrestore() which makes the code much longer. I prefer your code as it takes only one line and is simpler to maintain.
    – saginaw
    Commented Jan 2, 2016 at 20:06
3

By calling a user-defined function, a mapping that inserts "Hello, " before prompting for the user's name can be achieved:

function s:InputName()
    call inputsave()
    let g:name = input("Your name please: ")
    call inputrestore()
endfunction
nnoremap <F1> oHello, <C-\><C-o>:call <SID>InputName()<CR><C-r>=name<CR>. You have a nice name.<ESC>

This answer (with minor differences) was first shared as a link in a comment by @saginaw to the answer by @EvergreenTree, but I had essentially reproduced that answer (with a lot of reading :help pages and Googling) before clicking the link. This seems a distinct answer, from that of @EvergreenTree

As @saginaw pointed out, :help input() essentially documents this function-based solution, but @saginaw added the script-local function syntax (s: to the definition, and <sid> to the call).

This mapping uses insert special keys, including <C-\><C-o> (see :help i_CTRL-\_CTRL-O) and and <C-R>= (see :help i_CTRL-R_=).

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.