Vim Tips Wiki

Insert a single character

1,612pages on
this wiki
Revision as of 18:13, February 27, 2014 by (Talk)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Tip 270 Printable Monobook Previous Next

created 2002 · complexity basic · author Mikko Pulkkinen · version 6.0

Using insert mode to insert a single character feels clumsy (you need three keypresses for one character), so here's a slightly easier way:

:nmap <Space> i_<Esc>r

Now, when in normal mode, just press space followed by what it is you want to insert.

Bug: Repeating the insertion with . doesn't work.


I prefer <C-I> as a {lhs}. It is unused and fits better to the insert logic of Vim, although it saves fewer key strokes.

I use

:map gt i_<Esc>r
:map gb a_<Esc>r

The author was looking for a way to save a keystroke. Both solutions are 3 keystrokes long. A solution that also moves the cursor to the right would be better.

I consider this a better solution:

:nnoremap s :exec "normal i".nr2char(getchar())."\e"<CR>
:nnoremap S :exec "normal a".nr2char(getchar())."\e"<CR>

Such inserts can be repeated with '.' thus making this command worthy (it's not a big problem to make an additional keypress but imagine you need to manually put some spaces or other separators).

PS. 's' and 'S' were chosen because:

  • They remind of 'single'.
  • If they are used occasionally, one can use synonyms 'cl' and 'cc' instead.
What is the "\e" for?
It might be meant to represent <Escape> although in Vim7.2 this method does not need to force an escape from insert mode.
The built-in s command is very useful, but that's a choice for the user. JohnBeckett 22:56, 15 June 2009 (UTC)

I quite like the solution you proposed, but it doesn't allow for repetitions, I found myself wanting to do '5s '. I couldn't use the repetition inline because it would repeat the call to getchar so I added a simple proxy function, the result is:

 function! RepeatChar(char, count)
   return repeat(a:char, a:count)
 nnoremap s :<C-U>exec "normal i".RepeatChar(nr2char(getchar()), v:count1)<CR>
 nnoremap S :<C-U>exec "normal a".RepeatChar(nr2char(getchar()), v:count1)<CR>

Note that the C-U is necessary to support the ranges and as far as I could tell the '."\e"' was unnecessary, so I removed it

Interesting, thanks. Why wouldn't repeat(getchar(), v:count1) work (why the RepeatChar function)? JohnBeckett 11:20, September 28, 2010 (UTC)
Because if you use repeat(nr2char(getchar()), v:count1) it executes the "nr2char(getchar())", "v:count1" times, meaning it will try to get "v:count1" keypresses. When you pass it as a parameter to a function it is evaluated only once and the result is repeated. 12:44, September 20, 2010 (UTC)

This is what I am using for a similar purpose -the only difference is, if a character isn't provided promptly, it inserts a space:

 function! InsertSingle()
   sleep 120m|let l:a = getchar(0)
   if l:a != 0
     silent! exec "normal a" . nr2char(l:a)
     silent! exec "normal a "
 nnoremap <silent> <Space> :call InsertSingle()<CR>

Around Wikia's network

Random Wiki