move selection to a separate file
With vim, how can I move a piece of text to a new file? For the moment, I do this:
- select the text
- use
:w new_file
- select the text again
- delete the text
Is there a more efficient way to do this?
Before
a.txt
sometext
some other text
some other other text
end
After
a.txt
sometext
end
b.txt
some other text
some other other text
How about these custom commands:
:command! -bang -range -nargs=1 -complete=file MoveWrite <line1>,<line2>write<bang> <args> | <line1>,<line2>delete _
:command! -bang -range -nargs=1 -complete=file MoveAppend <line1>,<line2>write<bang> >> <args> | <line1>,<line2>delete _
By "move a piece of text to a new file" I assume you mean cut that piece of text from the current file and create a new file containing only that text.
Various examples:
-
:1,1 w new_file
to create a new file containing only the text from line number 1 -
:5,50 w newfile
to create a new file containing the text from line 5 to line 50 -
:'a,'b w newfile
to create a new file containing the text from marka
to markb
- set your marks by using ma and mb where ever you like
The above only copies the text and creates a new file containing that text. You will then need to delete afterward.
This can be done using the same range and the d
command:
-
:5,50 d
to delete the text from line 5 to line 50 -
:'a,'b d
to delete the text from marka
to markb
Or by using dd for the single line case.
If you instead select the text using visual mode, and then hit :
while the text is selected, you will see the following on the command line:
:'<,'>
Which indicates the selected text. You can then expand the command to:
:'<,'>w >> old_file
Which will append the text to an existing file. Then delete as above.
One liner:
:2,3 d | new +put! "
The breakdown:
-
:2,3 d
- delete lines 2 through 3 -
|
- technically this redirects the output of the first command to the second command but since the first command doesn't output anything, we're just chaining the commands together -
new
- opens a new buffer -
+put! "
- put the contents of the unnamed register ("
) into the buffer- The bang (
!
) is there so that the contents are put before the current line. This causes and empty line at the end of the file. Without it, there is an empty line at the top of the file.
- The bang (
Based on @embedded.kyle's answer and this Q&A, I ended up with this one liner to append a selection to a file and delete from current file. After selecting some lines with Shift+V
, hit :
and run:
'<,'>w >> test | normal gvd
The first part appends selected lines. The second command enters normal mode and runs gvd
to select the last selection and then deletes.