tags:

views:

164

answers:

6

I have the requirement of separating an ASCII document into pages of max length 58 lines per page. At the bottom of each page there is a 3 line footer. I'm not aware of any pagination abilities within Vim that would accomplish this.

Is there a good way to do this with Vim? Perhaps highlighting every 58th line or something of the sort.

N.B. I'm seeing answers involving using a separate tool to do this; which I have thought of. What I'm interested in is a Vim solution.

Thanks.

+2  A: 

Why is it important to use vim? You could use split and cat more efficiently.

Assuming your original file is called file and you have a file, footer, created that includes your footer text.

$ split -l 58 file file_parts
$ for i in file_parts*; do cat $i footer > $i.footered; done
$ cat file_parts*.footered > file.footered

file.footered would have your original file with the contents of footer inserted at every 58th line.

This is assuming you want it all back in the original file. If you don't, then the resulting file_parts*.footered files would be the already separated pages so you could skip the last step.

jsoverson
+1  A: 

You're probably trying to use the wrong tool for this. You could do it much easier programmatically, for example with this simple Perl oneliner:

perl -pe'print "your\nfooter\nhere\n" unless $. % 58' inputfilename > outputfilename
Ether
+3  A: 

The proper tool you're looking for is very likely a2ps.

a2ps --lines-per-page 58 --footer=footer_text document.txt
MikeyB
Good answer but I want to know if Vim can be used for this.
Pierre-Antoine LaFayette
+2  A: 

It's possible in vim as a script. Put the following in a file and :source it while the file to change is open. The s:footer list are the lines to insert after each run of 58 lines.

let s:footer = ["","Footer",""]
let s:line = 0

while s:line <= line("$") - 58
  let s:line = s:line + 58
  call append(s:line, s:footer)
  let s:line = s:line + len(s:footer)
endwhile
Geoff Reedy
I guess this is the best Vim only solution. It would be nice if there was some native way to do this.
Pierre-Antoine LaFayette
You could also make this into a function and command (optionally in a plugin) with an argument for the number of lines. Then it becomes a simple case of typing `:Paginate 58` or something like that. If you want to be REALLY clever, you could automatically remove the old footers and re-add them (as long as there's no risk of matching text in the body of your document).
Al
+2  A: 

The most effective ways for doing that in vim are script (like Geoff Reedy already suggested) and substitution (like :%s@\%(.*\n\)\{58}@\0---\rfooter\r---\r@). Macro (as suggested in comment to this question) is the slowest, script is the fastest. Substitution is slower than script, but much faster than a macro.

So probably substitution is the best Vim-only solution unless its performance is unacceptable. In this case it's worth writing a script.

ib
+1  A: 

A recursive macro might work. Experiment with the following (position the cursor on the first character of the first line and switch to normal mode):

qqq
qq
57j
:read footer.txt
3j
@q
q

Note that the register to which you record the macro must be cleared (qqq) and that you must not use tab-completion when reading the footer-file (:read footer.txt).

You can then use the macro (normal mode):

@q
Gurraman