Move lines matched by :g to the top of the file - vim

I have a large text file with several calls to a specific function method_name.
I've matched them using :g/method_name.
How would I move them to the top of the file (with the first match being on the top)?
I tried :g/method_name/normal ddggP but that reverses the order. Is there a better way to directly cut and paste all the matching lines, in order?
Example input file:
method_name 1
foo
method_name 2
bar
method_name 3
baz
Example output file:
method_name 1
method_name 2
method_name 3
foo
bar
baz

How about trying it the other way around: moving the un-matched lines to the bottom:
:v/method_name/normal ddGp
This seems to achieve what you want.

I think you can achieve the desired result by first creating a variable assigned
to 0:
:let i=0
And then executing this command:
:g/method_name/exec "m ".i | let i+= 1
It basically calls :m passing as address the value of i, and then increments
that value by one so it can be used in the next match. Seems to work.
Of course, you can delete the variable when you don't need it anymore:
:unlet i

If the file is really large, count of matching entries is small, and you don't want to move around the entire file with solution v/<pattern>/ m$, you may do this:
Pick any mark you don't care about, say 'k. Now the following key sequence does what you want:
ggmk:g/method_name/ m 'k-1
ggmk marks first line with 'k.
m 'k-1 moves matching line to 1 line before the 'k mark (and mark moves down with the line it is attached to).
This will only move a few matching lines, not the entire file.
Note: this somehow works even if the first line contains the pattern -- and I don't have an explanation for that.
For scripts:
normal ggmk
g/method_name/ m 'k-1

Related

Insert mode function/abbreviation/snippet in vim

In elixir we need to write a lot of maps(key-value pairs).
Syntax is:
%{one: one, two: two, three: three}
How can we write some kind of function/snippet/abbreviation so that we can achieve:
${1:one}: ${1:one} # => %{one: one_} # => where _ denotes cursor
Where we enter one and it does the following:
Enters one in key: value pair, i.e. one: one
Takes cursor to second one's end character i.e. one: one(cursor)
And if we have to use some snippet for this then how can we assign some shortcut-key to it ?
========================
Example:
========================
Say I'm anywhere in a file (mostly inside %{} for elixir)
I hit some keyboard shortcut (e.g. ) and type elephant then i want to get the following:
elephant: elephant and want my cursor at the end of second word's last letter(i.e. t).
Initially %{|} where | denotes cursor.
We press: <C-m> and get %{term|: term}. and term - first word is selected.
We write: elephant and get %{elephant: elephant|}
Done.

How to replace finding words with the different in each occurrence in VI/VIM editor ?

For example, I have a text ,
10 3 4 2 10 , 4 ,10 ....
No I want to change each 10 with different words
I know %s/10/replace-words/gc but it only let me replace interactively like yes/no but I want to change each occurrence of 10 with different words like replace1, 3, 4 , 2 , replace2, 4, replace3 ....
Replaces each occurence of 10 with replace{index_of_match}:
:let #a=1 | %s/10/\='replace'.(#a+setreg('a',#a+1))/g
Replaces each occurence of 10 with a word from a predefined array:
:let b = ['foo', 'bar', 'vim'] | %s/10/\=(remove(b, 0))/g
Replaces each occurence of 10 with a word from a predefined array, and the index of the match:
:let #a=1 | let b = ['foo', 'bar', 'vim'] | %s/10/\=(b[#a-1]).(#a+setreg('a',#a+1))/g
But since you have to type in any word anyway, the benefit of the second and third function this is minimal. See the answer from SpoonMeiser for the "manual" solution.
Update: As wished, the explanation for the regex part in the second example:
%= on every line in the document
s/<search>/<replace>/g = s means do a search & replace, g means replace every occurence.
\= interprets the following as code.
remove(b, 0) removes the element at index 0 of the list b and returns it.
so for the first occurrence. the line will be %s/10/foo/g the second time, the list is now only ['bar', 'vim'] so the line will be %s/10/bar/g and so on
Note: This is a quick draft, and unlikely the best & cleanest way to achieve it, if somebody wants to improve it, feel free to add a comment
Is there a pattern to the words you want or would you want to type each word at each occurrence of the word you're replacing?
If I were replacing each instance of "10" with a different word, I'd probably do it somewhat manually:
/10
cw
<type word>ESC
ncw
<type word>ESC
ncw
<type word>ESC
Which doesn't seem too onerous, if each word is different and has to be typed separately anyway.

How to quickly edit determinate part of code inside different similar lines

I have this problem I'm adjusting a code I've made I have a structure like this:
Apple1 = Fruit("ss","ss",[0.1,0.4],'w')
PineApple = Fruit("ss","ss",[0.315,0.4],'w')
Banana = Fruit("ss","ss",[0.315,0.280],'w')
...
...
Instead of "ss"I would like to type further information like "Golden Delicious". For the moment I'm simply deleting "ss"clicking over it and then replacing it with the information I want to insert. I'm sure there is a faster way to do it, I've tried something with VIM macros but I can't figure out how to "Raw input" my data.
I've try simply to substitute it with Spyder, but is slow because I have to click substitute every time, with VIM for what I've try is the same.
Then I wonder how insert something else after 'w'...
This is an example of an final output only to understand better the question :
Apple1 = Fruit("Golden Delicous","red",[0.1,0.4],'w')
PineApple = Fruit("Ananas comosus","green",[0.315,0.4],'w')
Banana = Fruit(" Cavendish banana","yellow",[0.315,0.280],'w')
...
...
I reformulate the question: which is the faster way to change "ss", for the moment I'm clicking over "ss" delate "ss" and write e.g "Golden Delicous" but is very slow. What I would like is that for every single ss the editor ask me to insert something to replace the single ss.
e.g. first ssin the fist line: I want to replace it typing something else e.g. "Golden Delicous" second ssin the first line I want to replace it typing somethingelse e.g. red. First ssin the second line I want to replace it with s.e. e.g. Ananas comosussecond ssin the second line I want to replace with s.e. e.g. green and so on.
I'm sure there is an answer for this somewhere but I can't find it!
Please if you down vote explain me why so I can improve it!
As far as I understand, the data that you want to substitute for "ss" does not have regular structure, so you will need to enter it by hand.
In Vim you would do it like this:
Place the cursor over the first "ss", then press * and then N.
Press ce, enter the new data (e.g. "Golden Delicious"), then leave Insert mode by pressing Escape.
Press n to jump to the next instance of "ss".
Repeat steps 2 and 3 ad libitum.
Look up :h * and :h n for more information.
I would do it like that:
:%s/ss/\=input('Replacement: ')/gc
This queries you for each occurrence. With the /c flag, the display is even updated during the loop (at the cost of having to additionally answer y for each occurrence); without the flag, you would need to keep track of where you are yourself.
You can use a function that searches the whole file substituting all "ss" strings with values from arrays populated with the replacement data:
function! ChangeSS()
let ss1 = ['Golden Delicous', 'Ananas comosus', 'Cavendish banana']
let ss2 = ['red', 'green', 'yellow']
call cursor(1, 1)
let l = "ss2"
while search('"ss"', 'W') > 0
if l == "ss1"
let l = "ss2"
else
let l = "ss1"
endif
execute 'normal ci"' . remove({l}, 0)
endwhile
endfunction
It uses a reference variable (l) that exchanges which array you want to extract data from. ss1 is for first appearance of "ss" in the line and ss2 for the second one.
Run it like:
:call ChangeSS()
That (in my test) yields:
Apple1 = Fruit("Golden Delicous","red",[0.1,0.4],'w')
PineApple = Fruit("Ananas comosus","green",[0.315,0.4],'w')
Banana = Fruit("Cavendish banana","yellow",[0.315,0.280],'w')

vim copy-paste buffers

Suppose I have the following text (I have numbered the lines for clarity) and the cursor is at the beginning of the 5th line:
1
2 var x = 1;
3 var y = 2;
4
5 if (true) {
6 print("Hey!");
7 }
Okay, now I try to cut the lines 5, 6, 7 (all that "if" thingy). For that purpose I do:
Vjjd. Now it appears I am at the beginning of the 4th line which is an empty string.
My question: is it possible at this moment to remove the 4th line without loosing previously copied lines 5, 6, 7 (that "if" thingy), so that I'll be able to paste them somewhere else, say, on the 1st line later?
You can always yank or delete into a register using "n, where n is just about any key. See a list of available registers in "help registers", some of which have special meaning. For example, you could do:
> "a3dd (to delete the last three lines into a register called a)
> dd (to delete the blank line)
> "ap (to paste the a register)
You can also use Vjj"ad, to match what you were doing in the original question.
Yes: You can use the blackhole buffer register: type "_dd
if your #4 line is empty line, it is easy, you don't have to play with register. just do:
kJ
it means:
k: move to #3
J: (shift-J) Join #3 and #4
or you prefer do it in INSERT mode.
i<BS>
or
I<c-u>
if that line is not empty:
using register to store the 3 lines or #4, like #Derek suggested
using blackhole register like #Jan suggest
or using numbered register.
say, now you just did 3dd (without named register), and cursor on a not-empty line (#4), you could directly do dd. the 3 lines are not gone. you can paste them again by:
"2p

Reordering methods using vim

I have 2 methods in a source file:
def Foo
puts "hello"
puts "bar"
end
def Bar
puts "hello"
puts "bar"
end
I would like to swap the order of the methods, so Bar is first.
Assuming the cursor is on the d in def Foo, the simple way is to:
shift v -> jjjj -> d -> jjj -> p -> O -> esc
But that feels a little long winded and does not account well for arbitrarily long methods:
What is the most efficient way to do this in Vim, keystroke wise?
EDIT
Keep in mind, I would like the solution to account for a situation where the methods are in a context of a big class, so G is probably best avoided
Assuming the cursor is somewhere in the first method, press dap}p and they should be swapped.
What dap does is simply "delete a paragraph". Try :help object-select to learn other way of deleting/selecting text objects in VIM.
EDIT: Replaced G with } in the command.
Similar to Spatz's
d}}p
delete to the next blank line (below Foo), skip to the next blank line (below Bar), paste.
Found another method ( from godlygeek on #vim ):
with:
def function():
first
first
first
def lol():
second
second
second
From line 1, count up until the 'def lol', which is 5. Then:
:1,5m$
A couple of ways off the top of my head. You could say
5dd/end[enter key]pO
Deletes five lines, searches for end, places the lines underneath, adds a space.
If you have VimRuby installed, I believe you can use % to jump between def and end. In that case, you could say
v%x5jpO
Edit: I defer to spatz on this :P
From line 1, 5ddGp , or 5dd:5p is the most concise/shortest I can think of.
personally, I would go '4dd' then down under bar and press 'p', but I'm not a vim guru

Resources