8

I'm returning to Vim after using Emacs for a few years. I'm trying to grok Vim by reading and watching tutorials, as well as actually using it daily.

When editing text, I find the Emacs commands of Alt-F, Alt-B, Ctrl-a, Ctrl-e, Alt-D and Alt-Backspace to be very useful and intuitive, allowing for quick and easy local edits while working with text (words/code).

What is the Vim-way of implementing similar functionality? Returning to NORMAL mode to issue a single motion, only to re-enter INSERT mode is not optimal.

Example 1: When in INSERT mode to insert a ( at the start of an expression, how should I move to the end of the expression or the line to insert the corresponding ) in Vim?

Example 2: When editing text, one may often want to delete a word forwards or backwards while writing or editing a sentence or code. It would be unusual to have a perfectly-formed sentence/code in one's mind, ready to type "once-off" ahead of time; often a sentence changes as one is working with the text. The restrictions of INSERT mode are making this kind of editing difficult for me in Vim. I feel unable to effectively manipulate the text in insert mode, always finding myself having to switch back to NORMAL mode for simple movements or deleting words.

PS: Alt-F and -B move the cursor forward or backward one word. Ctrl-a and -e move the cursor to the start or end of line. Alt-F deletes the word under the cursor. Alt-Backspace deletes the word before the cursor.

  • 1
    The Vim way might be to use a plugin like algorithm.com.au/code/vimacs. :P Can you include an explanation of what these commands do in emacs? A list of Ctrl/Alt/Meta-foo/bar is quite meaningless for anyone who doesn't use emacs. And Ctrl-W deletes the word before the cursor. Also, I have a feeling this is a bit too broad. – muru Aug 3 '15 at 18:34
  • 1
    If we're going the plugin way you should check out github.com/tpope/vim-rsi – dkns Aug 3 '15 at 19:14
  • 3
    When moving from programming language "A" to "B". It is best not to write "B" in the style of "A" but rather learn the standard idioms of "B" (its a hard lesson for most developers). Same rule applies for editors. Don't try and apply the standard workflow of editor "A" to your new editor "B". Prefer to learn the idioms of using "B" directly. Bigger learning curve but much more productive in the long run. In vim when editing you spend most of your time in normal mode not in insert mode. – Martin York Aug 4 '15 at 14:34
6

1

You can achieve those or better (pinky) command mappings very quickly. I'm not recommending this solution, but as an example, if you want to move the cursor to the beginning of line with <C-a> you can execute the following line after hitting : from normal mode (or add the line to your vimrc)

inoremap <C-a> <C-o>0

or, if start of line means first non-blank character of line

inoremap <C-a> <C-o>^

Curious thing, I just tested these mappings in the buffer in which I'm writing this answer, and I was confused for a moment because they didn't work. Then I realized I had forgotten to enter insert mode. You seem to find it a pain to leave insert mode to execute normal mode commands. You may find after using Vim for a while that it's the reverse–that you linger in normal mode while you're thinking and only make excursions to insert mode for particular occasions. Vim is probably only (or mostly) worth learning if you find that you do more editing than writing text.

So one part of an answer to your question about executing normal mode commands quickly from insert mode is <C-o>, which lets you leave insert mode temporarily to execute one normal mode command, then reenter. Read about it at :help i_Ctrl-o. This is useful for one-off conveniences. A more sustainable route is probably to try to embrace normal mode as a default for navigation and editing, and only enter insert mode when you actually want to insert new characters by hand into the buffer.

2

Your examples are very general so it's hard to give specific answers. I'm going to make up a specific example in hopes it fits or is translatable to something you encounter. For your number 1, it depends on how you know where the closing parenthesis is supposed to go. let's say I have a line like

let cchar = s:cchar["atx"]

This is meant to be a line of VimL, vim's scripting language, and it (or something like it) occurs in a Vim syntax file I am currently disagreeing with. Let's say I want to change the right hand part of this expression to a function call, perhaps because the function provides defaults when the dictionary s:cchar has not been assigned a value yet for the "atx" key. With my cursor (in normal mode) on the first character, 'l', I might type

f=wcf[MyFunction(<Esc>$r)

Briefly, this says

  • f= - forward to '=' (I could have said fs, but I probably wouldn't pause long enough to see that the 's' I want to reach is the first s on the line, so I'd go for the character that is obviously unique, and continue from there)
  • w - next word, now my cursor is on the 's' of 's:cchar'
  • cf[ - change to forward to '['

at this point the line looks like

let cchar = |"atx"]

where | is the cursor, and I am in insert mode. I then type MyFunction( and leave insert mode (<Esc>).

  • $ - move cursor to end of line. I could have used E for end-of-big-word or f] for forward-to-']' or some other motion, but $ occurred to me first.
  • r) - replace character under cursor with a ')'

Now I have changed the assignment expression from assigning from a script-local dictionary to using the return value of a function, and in doing so I introduced parentheses. I don't know how your particular need for parentheses looks, perhaps it's very different, in which case there will be a different string of commands to achieve it. If I paused to think longer about my made up example I might find more efficient ways to achieve that also, but who has time to pause and think.

(Try it, copy-paste (sorry, yank-put) the text and the command to a buffer, and with your cursor on the first character, 'f', of the command hit y$. Now the command is in your unnamed register. Move to the beginning of the first line and hit :normal <C-r>" to a) enter command line mode, b) begin executing a normal mode command from the command line, and c) to paste (atchoo put) the unnamed register into the command line as the normal mode command to be executed. The only thing you need to change in the command is to replace the phony <Esc> series of characters (because you copy-pasted atchoo from your browser) with the actual Escape key code, so delete it and hit <C-v> and then your Esc key. It will look sort of like ^[. Now hit return to run the command. Or... just type the string of keys to test the commands, I just wanted to show you that you can interact with normal mode from cmdline mode as well, and <C-v>, and <C-r>, and all the other glories of Wonderland. Also, see :help Cmdline-mode.)

3

For deleting a word backwards you can use the standard mapping <C-w> (see :help i_Ctrl-w). I don't know if there is a default mapping to delete a word forwards, but I suppose you could make one with

inoremap <C-S-w> <C-o>dw

Again, <C-o> will take you out of insert mode for a one-off command and dw will "delete" over the "word" motion. See :help d, :help w. If the forward words you delete are not actual words but class.function#names, you may want to use W (see :help W). If you're already mostly in normal mode you don't need these mappings, just do dw, db or friends.

Some help chapters to look closer at

  • :help <C-o>
  • :help Insert
  • :help f and the following sections (F,t,T,; and ,)
  • :help word-motions
  • 5
    Writing is NOT linear. Anyone who can write prose (or code) from start to finish without performing some kind of edit is either insane or has the power of a God. For the rest of us we do more editing then writing and therefore thinking about your editor as performing edit commands (NORMAL mode) first and writing (INSERT mode) second is more efficient. And this is the true crux of why editors like Emacs, MS Word, Notepad, etc. are backwards in their approach. It is unfortunate that the mode-less concept exists but there must be a lowest common denominator. – Sukima Aug 3 '15 at 20:54
12

When editing text, I find the Emacs commands of Alt-F, Alt-B, Ctrl-a, Ctrl-e, Alt-D and Alt-Backspace to be very useful and intuitive, allowing for quick and easy local edits while working with text (words/code).

To answer your question about local edits: if you're in insert mode and press ctrl-O you'll do the next command in insert mode. It can be handy if you decide to wipe the line. There are a few other commands in insert mode for small things, like pasting from the register and autocompleting words. You can read all of them with :h ins-special-keys.

Example 1: When in INSERT mode to insert a ( at the start of an expression, how should I move to the end of the expression or the line to insert the corresponding ) in Vim?

Often there's a better way to do things in normal mode. For example, let's say you want to surround an expression with parenthesis. Some things you can do are i(<end>), i(<esc>A), c$()<esc>P.* My favorite thing involves having one of the "necessary" vim plugins, vim-surround. With vim-surround, it's just ys$). What's great about all of these is that once you know how to do it in one situation, you can do it in all similar situations. What if instead of adding parenthesis to the end of the line, it's just three words? You can use c3w()<esc>P or ys3w). What about the whole line? cc()<esc>P or yss).

Example 2: When editing text, one may often want to delete a word forwards or backwards while writing or editing a sentence or code. It would be unusual to have a perfectly-formed sentence/code in one's mind, ready to type "once-off" ahead of time; often a sentence changes as one is working with the text. The restrictions of INSERT mode are making this kind of editing difficult for me in Vim. I feel unable to effectively manipulate the text in insert mode, always finding myself having to switch back to NORMAL mode for simple movements or deleting words.

One thing that helps a lot is to add inoremap jk <esc> to your vimrc. Then you can exit insert mode by pressing jk. This takes most of the overhead out of leaving insert mode so you can do jk<sequenceofcommands>i to do commands without disrupting your typing.

9

Alt-F, Alt-B, Ctrl-a, Ctrl-e, Alt-D and Alt-Backspace

The equivalent commands in normal mode are w, b, ^, $, dw, db. Note the logic: dw deletes what is covered by w and db deletes what is covered by b. What command would you use to delete what is covered by ^? Or to yank it?

That language-like logic is the whole point of modal editing; it may take some time to adjust to it but there's no u-turn.

The equivalent commands in insert mode are: <C-Right>, <C-Left>, <Home>, <End>, <C-w> and… nothing but you can create a simple mapping: inoremap <C-something> <C-o>dw.

Returning to NORMAL mode to issue a single motion, only to re-enter INSERT mode is not optimal.

Indeed. The right approach is to enter insert mode to insert as little text as possible and return to normal mode as soon as possible.

Example 1: When in INSERT mode to insert a ( at the start of an expression, how should I move to the end of the expression or the line to insert the corresponding ) in Vim?

Like in any text editor or IDE or text processor or <textarea>:

<End>)

Example 2: When editing text, one may often want to delete a word forwards or backwards while writing or editing a sentence or code. It would be unusual to have a perfectly-formed sentence/code in one's mind, ready to type "once-off" ahead of time; often a sentence changes as one is working with the text. The restrictions of INSERT mode are making this kind of editing difficult for me in Vim. I feel unable to effectively manipulate the text in insert mode, always finding myself having to switch back to NORMAL mode for simple movements or deleting words.

Again, insert mode is for inserting text. "Manipulating text" and moving around are supposed to happen in normal mode.

Please ask more precise questions.

  • Using motions (such as End or arrow keys) in INSERT mode is OK? – SabreWolfy Aug 3 '15 at 19:46
  • 4
    Of course, anything that makes your work easier. – romainl Aug 3 '15 at 19:57
3

What is the Vim-way of implementing similar functionality? Returning to NORMAL mode to issue a single motion, only to re-enter INSERT mode is not optimal.

Well, one can say the Vim-way is to not stay in INSERT mode. The enlightening moment in Vim comes when you realize how you don't need to stay in INSERT mode. There are many ways to insert text, and all of them start from NORMAL mode.

That being said, I am not a true one myself, and I remapped keys for doing the job (à la Windows):

nmap <C-BACKSPACE> dbi
nmap <C-DEL> dei
imap <C-BACKSPACE> <ESC>ldbi
imap <C-DEL> <ESC>ldei

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.