A Tale of Two (Vim) Commands: "s" and "c"
Vim continues to surprise me with its wonders. Sometimes (many times, in fact) things do not make sense, and I am perplexed as to the reasoning behind them. Then, one day, I grok it. And from that day on, I can never imagine any other way of doing it.
An example of this was my confusion over the apparent redundancy of two fundamental commands.
In normal mode Vim, "s" (mnemonic: "substitute") and "c" (mnemonic: "change") are both ways to remove some existing text and then go into insert mode.
This is the equivalent of selecting some text with a mouse and beginning to type in the world of modeless editors.
For a while I was a little bit confused about the differences between the "s" and "c", mainly because in some contexts they both behave the same way.
It took a little bit of snooping around the documentation and experimentation for me to realize the difference: "s" is the approach to use in simple situations, for replacing a single character or visual selection with typed text, while "c" is a much more powerful approach for use in more complex situations, because it is combined with motion and text object commands.
So, in general, you would use "s" in essentially one of two basic situations:
- When you want to delete the character under the cursor, and replace it with text that you want to type in (which may be more than one character).
- When you have text highlighted in visual select mode, and you want to delete it and replace it with new text that you want to type in.
And that is about it. In fact, in the first of these situations, i.e., replacing a single character with new text to be typed in, "s" is the most efficient way to do things.
The "c" command, on the other hand, is usually combined with a motion or text object command to provide a much broader range of target possibilities.
It can actually be used identically to "s" in the second situation above, i.e., to delete a visually selected block and replace it with new text to be typed in, but it really distinguishes itself when carrying out more complex operations than simply replacing the current visual selection.
The use of "c" with motions is straightforward: type "c" followed by a Vim movement command (e.g., "c$" or "cw") , to delete everything from the current cursor position to the destination and enter insert mode.
The same applies with "c" and text objects: type "c" followed by a text object selection command (e.g., "ca)", or "cis") to delete the text object, and then enter insert mode and start typing.
Now, I not only understand the distinction beween "s" and "c", but I also understand why Vim provides these two ways to go about doing a similar operation.
Because you combine the "c" command with a motion or text object, you can operate text regions of a broad range of sizes and scopes.
However, this means that in the simpler and more limited cases, where you just want to replace a single character or the current visual selection, using the "c" is quite inefficient, as you will be using keystrokes to describe what is the most atomic region of text (i.e., a single character) or the most obvious region of text (i.e., the current visual selection).
The "s" command exists solely to solve this problem, reducing the command to single keystroke when the region of text is irreducibly simple or absolutely unambiguous.
feed
Comments
6 comments postedPaul and Gabe,
You guys are absolutely right about ``r``. I love ``r``. I use ``r`` all the time. It is one of those things that if Vim did not provide out of the box, I would have had to script it.
*BUT* it is only useful if you are replacing *with* a single character. Sure, you can make a visual selection and hit "r" and then the replacement character to replace all characters in the selection with the character. And then there is magic like the following:
(1) type in a line: "ohello, world"
(2) type in "yyPVr="
and presto! we have underlining.
However, when you want to replace with *more* than one character, and the text is not in any register has to be typed fresh, then ``s`` or ``c`` are the way to go.
"i.e., replacing a single character with new text to be typed in, "s" is the most efficient way to do things."
Using 'r' to (r)eplace a single character is even more efficient since you don't have to escape out of insert mode afterwards!
"* When you want to delete the character under the cursor, and replace it with text that you want to type in (which may be more than one character)."
Let's not forget `r`! Your bullet here says "which may be more than one character." Indeed, when you want to replace a single character with more than one character then `s` seems like the way to go. But if you're replacing with exactly one character, `r` is even better since you don't have to leave normal mode.
I am a VIM noob but I think if you use cw to change a word you can repeat the command like a macro on different size words. Whereas s is more of a global search and replace
You are mistaking :%s for s.
If you use "cw", you can use "." (=="repeat" command) to repeat the same action on the next word. And this repeated action will be both: (a) the deletion of the word and (b) the insertion of whatever characters you typed in its plac.
With "s", if there is no visual selection, invoking the repeat command will result in a single character being deleted. And that's it. You lose the repeatability of the full edit.
If there is a visual selection and you use "s", the behavior is the same as if you used "c".
I do not know what you mean with the "global search and replace" reference. I do not see any relationship between "s" and this.
Post new comment