2

Suppose I have a file:

class X(arg):
\t#blabbla
\tdef fun1(arg):
\t\tsome code
\n
\tdef fun2(arg):
\t\tsome code
\n
class A(arg):
\t#blabbla
\tdef fun0(arg):
\t\tsome code
\n
\tdef fun3(arg):
\t\tsome code

And I wish to copy all lines start with class and \tdef, and paste them to the end of file preserving the order, i.e.

class X(arg):
\tdef fun1(arg):
\tdef fun2(arg):
class A(arg):
\tdef fun0(arg):
\tdef fun3(arg):

How can I achieve that without using extra plug-ins? (\t is tab, \n is new line)

1 Answer 1

3

Depending on what you want to perform (copy and paste or cut and paste), you could try one of the 2 following commands:

:g/\v^(class|\tdef)/t$
:g/\v^(class|\tdef)/m$

To duplicate (copy and paste) the current line after the last one, you can use the :t command: :t$

Like most Ex commands :t can be prefixed with an optional range, and like most Ex commands, when you don't give one, the current line is assumed. So :t$ is the same as :.t$ or :.,.t$

The :t command must be followed by a line address which is the number of the line after which the duplicated lines must be pasted.

With these 2 informations, you can perform an arbitrary duplication, such as: :5,10t42
Copy the lines between 5 and 10 and paste them below the line 42.

When you express a line address, there are some useful symbols (called specifiers by the help) such as:

.      current line
$      last line
'x     line where the mark x has been last set
/foo/  next line where foo is found

See :help :range for a comprehensive list of specifiers.


To move (cut and paste) the current line after the last one, you can use the :move command: :m$


In your question, you want to repeat the same command :t$ or :m$ on a set of lines where the same pattern can be found. Usually, this is a job for the global command :g.

So, you could use the command: :g/pattern/t$ or :g/pattern/m$
It would execute :t$ or :m$ on every line where pattern is found.

Besides, you want to operate on all the lines which begin with the word class, or with a hard tab followed by the word def.
In a regex, it could be expressed like this: \v^(class|\tdef)

Thus, the command :g/pattern/t$ should be rewritten, like this: :g/\v^(class|\tdef)/t$
And :g/pattern/m$ like this: :g/\v^(class|\tdef)/m$

If you execute the first command on your buffer, here's the transformation you should get (assuming there's an empty line at the end):

class X(arg):               class X(arg):     
    #blabbla                    #blabbla      
    def fun1(arg):              def fun1(arg):
        some code                   some code 

    def fun2(arg):              def fun2(arg):
        some code                   some code 

class A(arg):         ==>   class A(arg):     
    #blabbla                    #blabbla      
    def fun0(arg):              def fun0(arg):
        some code                   some code 

    def fun3(arg):              def fun3(arg):
        some code                   some code 

                            class X(arg):     
                                def fun1(arg):
                                def fun2(arg):
                            class A(arg):     
                                def fun0(arg):
                                def fun3(arg):

More generally, when you want to copy or cut a set of lines and paste them at the end of your buffer, you can follow a 2-steps process:

  1. progressively build a search pattern until your search matches the desired lines
  2. type :g//t$ or :g//m$

It works because, when you don't supply a pattern to the global or substitute command, they reuse the last search (the one in the search register :reg /).


For more information, see:

:help :global
:help :t (or :copy)
:help :move

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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