I don't know how to do this with macros, but there are a few options that I can see that can help:
Heavy use of "normal"
This is the closest option to your macro, but not very pleasant: make the saved file like this:
" Delete line normal dd " Delete word normal dw " Move to next line normal j
Difficult replacement
This uses regular expressions, but makes these regular expressions well-commented (this is based on your actual example).
let pattern = '^' " Start of line let pattern .= '\(\d\+\)' " One or more digits (test number) let pattern .= '\s\+' " Space or tab as delimiter let pattern .= '\(\k\+\)' " Installation name let pattern .= '\s\+' " Space or tab as delimiter let pattern .= '\(\a\+\d\+\)' " One or more alphabetic characters, then one or more spaces (isotope) let pattern .= '\s*$' " Any spaces up to the end of the line let result = 'procedure TWatchIntegrationTests.Test\1;\r' let result .= 'begin\r' let result .= ' //***** Setup\r' let result .= ' builder\r' let result .= ' .withInstallation(\2)\r' let result .= ' .withIsotope(\3)\r' let result .= ' .Build;\r' let result .= '\r' let result .= ' //***** Execute\r' let result .= ' CreateAndCollectWatches;\r' let result .= '\r' let result .= ' //***** Verify\r' let result .= ' VerifyThat\r' let result .= ' .toDo;\r' let result .= 'end;\r' exe '%s!' . pattern . '!' . result . '!'
Paste it into a function
Given that this is getting rather complicated, I will probably do it this way because it gives more options for customization. As I can see, you want to split the line into empty space and use three fields, something like this:
" A command to make it easier to call " (eg :ConvertPICTData or :'<,'>ConvertPICTData) command! -range=% ConvertPICTData <line1>,<line2>call ConvertPICTData() " Function that does the work function! ConvertPICTData() range " List of lines producing the required template let template = [ \ 'procedure TWatchIntegrationTests.Test{TestNumber};', \ 'begin', \ ' //***** Setup', \ ' builder', \ ' .withInstallation({Installation})', \ ' .withIsotope({Isotope})', \ ' .Build;', \ '', \ ' //***** Execute', \ ' CreateAndCollectWatches;', \ '', \ ' //***** Verify', \ ' VerifyThat', \ ' .toDo;', \ 'end;', \ ''] " For each line in the provided range (default, the whole file) for linenr in range(a:firstline,a:lastline) " Copy the template for this entry let this_entry = template[:] " Get the line and split it on whitespace let line = getline(linenr) let parts = split(line, '\s\+') " Make a dictionary from the entries in the line. " The keys in the dictionary match the bits inside " the { and } in the template. let lookup = {'TestNumber': parts[0], \ 'Installation': parts[1], \ 'Isotope': parts[2]} " Iterate through this copy of the template and " substitute the {..} bits with the contents of " the dictionary for template_line in range(len(this_entry)) let this_entry[template_line] = \ substitute(this_entry[template_line], \ '{\(\k\+\)}', \ '\=lookup[submatch(1)]', 'g') endfor " Add the filled-in template to the end of the range call append(a:lastline, this_entry) endfor " Now remove the original lines exe a:firstline.','.a:lastline.'d' endfunction
Do it in python
This is a task that is probably easier to do in python:
import sys template = ''' procedure TWatchIntegrationTests.Test%(TestNumber)s; begin //***** Setup builder .withInstallation(%(Installation)s) .withIsotope(%(Isotope)s) .Build; //***** Execute CreateAndCollectWatches; //***** Verify VerifyThat .toDo; end; ''' input_file = sys.argv[1] output_file = input_file + '.output' keys = ['TestNumber', 'Installation', 'Isotope'] fhIn = open(input_file, 'r') fhOut = open(output_file, 'w') for line in fhIn: parts = line.split(' ') if len(parts) == len(keys): fhOut.write(template % dict(zip(keys, parts))) fhIn.close() fhOut.close()
To use this, save it as (e.g.) pict_convert.py and run:
python pict_convert.py input_file.txt
As a result, it will produce input_file.txt.output .