VIm change bracket types (without using search and replace) [duplicate] - vim

This question already has answers here:
Quickest way to change a pair of parenthesis to brackets in vim
(6 answers)
Closed 8 years ago.
I am looking for a VIM key combo for changing something like
blahblah["hello"]
to
blahblah("hello")
My best effort so far is
0f[yi[%c%()^["0P^[
but anything better would be much appreciated.
BTW, my combo works by doing:
find the first instance of [ (you get my point),
yank the insides (which of course means to register 0 by default, and it leaves the cursor on the first "),
move the cursor back onto the first instance of [ with %,
delete the whole [...] bit and go into insert mode,
write () and <Esc> out of insert mode,
paste the contents of register 0 in between the ().

I was hoping to have a muscle-memorable key combination that I could use for things like this where you want to 'keep the contents but change the surroundings'.
My proposal, if you reduce it to the minimum (and use ca[ rather than %c% -- credit to this SO for the a motion that I had not really known about) is not too bad because it is the sort of thing you can invent again once you know it is possible:
yi[ca[()<Esc>"0P
However, it occurred to me that a search-and-replace is going to be just the right kind of solution when you need to do a few of these in a file. Here is my best effort:
select the area in visual mode (I tend to use VISUAL LINE mode as a default),
then :s/\[\(.\{-}\)\]/(\1)/g<Enter> and you're done.
That itself looks a bit mad, but it is just a simple example of so-called backreferencing so I was quite happy to have had to get that clear in my mind too.

Related

Is there a better method for find and replace in Vim?

Edit: I moved this over to the Vi and Vim site: https://vi.stackexchange.com/questions/13689/how-to-find-and-replace-in-vim-without-having-to-type-the-original-word
I'd like to optimize my "find and replace" workflow in Vim. It's something I do often, as I'm sure most of you do too. Usually something along the lines of -- copy a block and change the name of a variable in a few places. I know, I know, that probably triggers your "why are you copying and pasting code" reflex, but let's not go down that road... There are plenty of valid use cases :)
I'm well aware of the search and replace commands: :s or :%s but I don't like them. It forces me to type out both the full variable name I'm searching for and what I'm changing it to. Maybe there is a better way fix the the amount of typing with :%s? I often use long descriptive variable names, so that is really a deal breaker for me. I also don't like how typing out a variable name from scratch is typo prone and can consume time and brainpower hunting down typos. I much prefer typing it once, and then copying and pasting to just avoid this entirely if possible.
My current workflow uses some combination of movement/yank/select/search/put to move around the file and replace one by one. It is not great but has the benefit of avoiding typing out full variable names. I might just need to type the first few letters with / or use another movement command (i.e. fx) depending on what's around and then hit ve to select the whole word. I also don't mind that I have to repeat for every instance. I never do a full find replace without confirming each change. But it would be much preferable if I could repeat the replacement action with a single keystroke (which I can't do with this method). each replacement is usually something like n then ve then p (or even worse "0p)
Is there a faster way?
My own workflow is similar to yours:
To start, get the cursor on one instance, possibly with / or by navigation.
Hit * to find the next instance of that word.
Change one instance with cw and then the new variable name.
Then it's fast: n/N to get to the next/previous instance, and . to repeat the last edit.
This workflow gives me the same advantage as yours, in that I can review each case before applying the change, but it's just two keystrokes for each additional change.
Hope this helps.
I like the "visual highlight then edit" approach.
shift + v to highlight the region that you want to modify.
then :s/old/new/r where old is what word you want to replace with new.
r changes the first instance of that word old.
Note* There are options other than r which modify its behavior how you want to replace the word.

Emacs / vim quick copy paste

I'm trying to make a transition to emacs (using evil mode/vim keybindings) and I'm having a hard time feeling more efficient/productive than if I just used the mouse. Here is an example of a situation where I find myself really slow:
for i in range(self.allData.shape[0]):
self.correctSequence = self.displayNumbers(i, self.allData)
self.userSequence = self.numberEntry()
self.allData.set_value(i, 'userSequence', ''.join(self.userSequence))
if len(self.correctSequence) != len(self.userSequence):
self.allData.set_value(i, 'correct', 0)
else:
if list(reversed(self.correctSequence)) == self.userSequence:
self.allData.set_value(i, 'correct', 1)
else:
self.allData.set_value(i, 'correct', 0)
It would be very common for me to have to change the first 4 instances of self.allData to something else (self.testData, for example), leaving the last 2 untouched.
Normally this wouldnt be too bad with a mouse. For example, I could replace the first allData with testData, copy it, use the mouse to the next 3 occurences and just hit CTRL-V for each one. Or better yet, just use multiple cursors in sublime/atom and replace all 4 in one go
I use spacesmacs in emacs with vim keybindings. So, in emacs I find myself having to do something like the following:
SPC-SPC a (avy jump to words beginning with a)
cw testData
Repeat those 2 steps once for each word I want to replace
This seems really inefficient and I'm wondering: am I just using an inefficient method? Is there a faster way to do what I want?
It seems that even if I managed to complete those steps really fast (4 times), theres still A LOT more typing one would have to do, and I fail to see how this would be faster than just reaching for the mouse. Yes, one could make the argument that I'm losing time by constantly reaching for the mouse, but in my mind I'm saving typing time by reaching for the mouse because I can just hit CTRL-V a few times to achieve what I want. Where exactly are the vim speed gains in a situation like this?
If you just want to replace, you can use query-replace, and replace the word one by one.
You can use replace-string too, but remember to limit replacement to part of the buffer, activate the region around that part.
Anyway, these commands could prevent you from finding the word by your eyes, moving cursor by mouse and moving your hand back to keybaord. And they could avoid probable overlook too. At least I don't want to leave my hands from the keyboard when typing. :)
I'm not sure how "vim-like" Spacemacs is, but you could do it like this in Vim:
/all<CR>
cgntest<Esc>
.
.
.
or:
/all<CR>
cetestData<Esc>
n.
n.
n.
or:
:,$s/allD/testD/gc<CR>
Maybe one of these methods works in Spacemacs too?
In addition to the usual (and generally the best) answer, query-replace (see #songyuanyao's answer), you can use the secondary selection to advantage to selectively paste the same thing at various places. Unlike the region, the secondary selection is unrelated to the cursor position (aka point), so it is always available regardless of where the cursor is.
And unlike query-replacing, you can paste it on demand, instead of having to answer for each matching occurrence. If you use delete-selection mode then just select some text to replace and paste the secondary selection to replace it.
You can set and paste the secondary selection using the mouse - see Secondary Selection on the Emacs Wiki, and see the Emacs manual, node Secondary Selection.
If you use library second-sel.el then you can use the secondary selection from the keyboard as well, and get a lot more use out of it.

"paste inner", similar to "yank inner" [duplicate]

This question already has answers here:
Pasting inside delimiters without using visual selection
(5 answers)
Closed 8 years ago.
Is there any known, straight-forward way to perform inner <text-object>-functons in Vim similar to yank-inner and delete-inner, only with paste? I know how to do this with Visual mode but it feels a few steps too long.
Example:
delete-inner (di<text-object>):
user.name("Carl") -> di" -> user.name("") + Carl is copied to clipboard.
Now, I occasionally find myself wanting to do something like this as well:
user.name("") -> pi" -> user.name("Carl")
I don't like taking the extra step inside Visual-mode, nor performing acharacter/string-search (/,f,t). Is there any way around this? Plugin-recommendations are also welcome if necessary.
I need this so often, I wrote a plugin to simplify (i.e. without the intermediate visual mode) and allow maximum speed: ReplaceWithRegister.
This plugin offers a two-in-one gr command that replaces text covered by a {motion} / text object, entire line(s) or the current selection with the contents of a register; the old text is deleted into the black-hole register, i.e. it's gone. It transparently handles many corner cases and allows for a quick repeat via the standard . command. Should you not like it, its page has links to alternatives.
So, your example would be g r i ".
Edit: Previous plugin versions didn't handle an empty text object well; fixed in the latest version 1.41.
"_di"P
works for me, it pastes to the left instead of right which leaves it inside the quotes
assuming you want to change the value with the one on the clipboard
Alternately you can use :map to map pi" to either the command above or the Visual method keys

How to get a better column edit mode in vim (more visualizable and customizable)

Vi experts, I have two questions concerning the column editing!
First, I already know how to go to the visual mode and do a column edit. But the point is that after shift+I and type, you can only see the first row changing before esc. My question is this, is it possible to make the editing operation visible in all rows? Or is this still an impossible task with the current vim?
My second question is, I want to insert a column with increasing numbers (0...9) or some user defined increasing items such as (monday...sunday) blahblah, what is the best way to achieve this, can I define a few customized functions and then call them?
"Still an impossible task" exposes a wrong assumption: Vim never wanted to be a WYSIWYG editor; just updating the current row requires less screen updates (which can be significant over slow connections; the whole modal editing of vi was partly born out of that necessity).
There are some attempts at "multiple cursors" plugins; with those, you might achieve this, though.
second question
(Note that it is bad style to ask about two unrelated things in a single question.)
Yes, you can do almost anything in "a few customized functions" (but you'd have to clarify your exact use case to get meaningful answers).
Some of that can be done via the speeddating plugin:
{Visual}<C-A> Increment by [count] the component under the cursor on each line of the linewise visual selection. If a component is absent on a line, it is filled in as being [count] higher than on the line above it. This can be used to create sequences. For example, place a "0" on a line followed by 4 blank lines, visually select all 5 lines, and press <C-A> to get a sequence of 1 through 5. You can use letters in visual mode too: make the first entry Z if you want a list starting with A.

Display last pressed set of valid keys on Vim's statusline [duplicate]

This question already has answers here:
Vim "show my last command" command?
(5 answers)
Closed 8 years ago.
I often find that I press the wrong set of keys but I can't figure out what I went wrong with.
In other words, a fat finger. However I don't know if it's a fat finger or not just from the output, a lot of the time yes I could figure it out, but instead I prefer Vim to tell me where I went wrong.
What I would like is to have something in my statusline that outputs the last set of valid key presses.
No showcmd does not work for my needs, that only outputs what I'm currently typing, tells me what Vim knows from me currently.
What I need is to know what Vim knew from me the last time I pressed keys.
So for examples, what I pressed on the left and what I want this addition in the statusline to tell me on the right.
j j
jjjjj j
5j 5j
4jj j
Isome text I
Aoh yeah A
. (Whatever the dot key just repeated)
Etc. You get the idea. :)
What would be a simple way to achieve this? It's probably some obscure variable that Vim keeps track of and I'm just not aware of it.
Any help is appreciated. :)
No, there's no built-in way to tell you if what you just typed is wrong and only a subset of what you type is recorded with some persistence (Ex commands, searches but not normal mode commands or inserts).
Recording everything you type is "easy" or rather "doable" with a key logger. Making sense of the content of the log (supposing we are able to decide where a command starts and where it ends) is another matter entirely. jjjj, 4j, /foo<CR>, 56G, or even using the mouse are all perfectly valid ways to move the cursor to foo and AFAIK, no one has ever written a program able to tell you which one of the method above is the most "valid".
So, in the meantime, you are left with your brain and how good it is at focusing on a given task and at manipulating abstract concepts: pay attention to what you do, identify bottlenecks and look for possible improvements.
From Seven habits of effective text editing:
While you are editing, keep an eye out for actions you repeat and/or spend quite a bit of time on.
Find out if there is an editor command that will do this action quicker. Read the documentation, ask a friend, or look at how others do this.
Train using the command. Do this until your fingers type it without thinking.

Resources