vimautomationmacros

Automation - Execute VIM macro a dynamic number of times


Is it possible to set up a macro in vim such that it executes a number of times equal to the number of results it finds earlier in execution?

I am trying to take a list of names, find all blocks in a document which contain those names in the header, then copy them to a new document. For example, the original data set may look like:

Bob's expenses {
1. food
2. water
}

Linda's expenses {
1. travel
2. food
}

George's expenses {
1. hats
}

Bob's needs {
1. raise
2. desk
3. chair
}

The name source document would look like:

Bob
George

And the final document after executing the macro would be:

Bob's expenses {
1. food
2. water
}

 George's expenses {
1. hats
}

 Bob's needs {
1. raise
2. desk
3. chair
}

Obviously, this is a condensed version of the data sets, and the real ones have hundreds of names with thousands of records. The way that I am currently executing this is by splitting the files in the order filtered data, full data, and names, starting the cursor at the top of the names file, and running these three macros:

@l - y$^W<80>kl:%s/^R"//n^M

Or, yank to the end of the line (name), move one document to the left (full data), and count the number of lines containing the yanked line. This will produce the number "n", so I then do

n@k - nzcyy^W<80>klp^W<80>kr<80>kd

Repeat the following n times: Go to next instance, fold line on brace, yank, move one document to the left, paste, move one document to the right, move cursor down one line. This grabs all blocks whose name includes the name found by the first macro, and puts them into the filtered document one at a time. Finally,

@j - ^W<80>kr<80>kd

Move one document to the right and move down one line.

So the process is manually run @l, manually check the result "n", manually run n@k, manually run @j, and manually repeat until I reach the end of the names document. What I really want to do is just n@l, where "n" is the number of lines in the names document, and have VIM be able to read the results of the search from step one, and run step two the appropriate number of times. Is this possible?


Edit: The solution does not actually need to be in VIM, come to think of it. If there is a way of accomplishing this effect through the linux terminal, that would be good too.


Edit 2: I found the solution here and answered my own question. I'll be accepting that as the correct answer.


Solution

  • Ah, of course as soon as I started talking through it and reframing the challenge, I found the right question to ask google, and found the solution here. The answer is to use the normal command. I can replace the n@k step by simplifying @k to just yank, move, paste, move and instead of running n@k, I can run

    :g/^R"/norm! @k^M
    

    This allows me to fully string together all macros, and bind them to a single register.