Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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
share|improve this question
add comment

3 Answers 3

up vote 2 down vote accepted

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 _
share|improve this answer
    
This is very ugly, but hey, it seems to do in one step exactly what I asked for (I tried). +1, and accepted. I was looking for a native way to do this quickly but since there does not seem to be one, yours will do just fine. Thanks! –  greg0ire Jan 23 '13 at 15:27
    
Beauty is in the eye of the beholder. I find this pretty elegant; you only need to type it once (into your .vimrc). –  Ingo Karkat Jan 23 '13 at 16:15
    
You're right, "very ugly" shoud have been "very unfamiliar". Your command is very handy, and I think I definitely going to carve it in my .vimrc –  greg0ire Jan 23 '13 at 16:21
add comment

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 mark a to mark b
    • 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 mark a to mark b

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.
share|improve this answer
    
Your assumption is right. This looks good, I'm going to test. Could you explain 2. a bit more? I'm not very familiar with ranges. EDIT: If I try this on the second line, it writes the first line to the other file, not the second line. –  greg0ire Jan 23 '13 at 14:09
    
@greg0ire I got that a bit backward, I'll edit to better explain –  embedded.kyle Jan 23 '13 at 14:16
    
I added an example to make my question clearer. –  greg0ire Jan 23 '13 at 14:18
    
@greg0ire I corrected my answer. It's still two steps. The first copies and writes. The second deletes. –  embedded.kyle Jan 23 '13 at 14:22
    
Ok, if I understand well, the trick is to use ranges to select and write in the same command. That's very similar to what I did. +1 for the detailed explanation, but I don't think this is more efficient, since the trick with hitting ':' is what I do for the moment. –  greg0ire Jan 23 '13 at 14:41
show 2 more comments

Select the text in visual mode, then press y to "yank" it into the buffer (copy) or d to "delete" it into the buffer (cut).

Then you can :split <new file name> to split your vim window up, and press p to paste in the yanked text. Write the file as normal.

To close the split again, pass the split you want to close :q.

share|improve this answer
    
I have 4 steps for the moment: select, write, select, delete. With your method, I have 6 steps: select, delete, split, paste, write, close. I asked for something more efficient :P –  greg0ire Jan 23 '13 at 13:42
    
Well, if you pass the split :x instead, you can combine writing and closing into one and make it five steps. :P –  Xyon Jan 23 '13 at 13:44
    
That's better, but 5 still > 4 :P –  greg0ire Jan 23 '13 at 13:46
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.