Sunday, May 1, 2011

How can I use vim to edit text from Perl while the script is still running?

I have a Perl script that outputs text. I want to import this text into vim, edit it, save it and then exit. On exit, I want the original Perl script to process the edited file.

E.G. how crontab -e works when you add a new job.

Thanks :)

From stackoverflow
  • You seem to want to pipe the output of your script into vim:

    script | vim

    And then you want the script to somehow know that Vim is finished and resume. That's not how I/O redirection works. The script has no knowledge of what program its output is being piped into.

    You mentioned other programs like crontab and cvs; one thing those have in common is that they invoke the editor themselves. They create temporary files, read the EDITOR or VISUAL environment variables (check the manual for details about how they choose which one), run the given program, and wait for the program to finish. Then they continue running and use the file they specified earlier.

    Turns out I've done exactly that in Perl. I created a temporary file (with tempfile), wrote a bunch of text into it, and then used system to invoke the editor on the file. You don't even have to close the file while you run the editor.

  • Sounds like a very plain case to use system to run vim on the filename. That will wait until vim is done, at which point you can go ahead and read the file's new contents.

    aidan : Cool! thanks - I hadn't thought of that. That's exactly what I need.
    rampion : You may want to use the $EDITOR environment variable to allow your users to select their editor of choice.
  • Pipe the output to vim - and don't forget the dash at the end. | vim -

    This will open vim with the contents of the scripts output. Just save it :w filename and exit :q. This isn't how crontab -e works, but it comes close enough in an easy way.

    I missed this part (or maybe the question was edited afterward):

    On exit, I want the original Perl script to process the edited file.

    This isn't the best way to do this, but going with my original answer, this works (if you save the file as file.txt):

    perl -le 'print "1234"' | vim - && perl -pe '' file.txt

    Just replace the perl commands with your perl commands and it should work. Like I said, this is not the best answer, but it should work.

  • A suggestion: Why don't you grab the source to crontab and see what it does?

    Other than that, unwind has your answer.

    And I think the way to think about this is:

    "Okay, I need a program to write out a file, call vim, then do further processing on the file. So, here's my routine to write the file, here's my routine that calls vim (using system), and here's my routine to do the postprocessing after vim is done. Now I'll lace them all together in my main program, and I'm done!"

  • use File::Temp;
    my $fh = new File::Temp();
    my $fname = $fh->filename;
    print $fh "My Text";
    system('vim', $fname);
    open $fh, '<', $fname or die "Can't open temp file: $!";
    while(<$fh>) { print }
    close $fh;
    ephemient : Might want to `unlink($fname)` after you're done, too.
    Hynek -Pichi- Vychodil : It is unnecessary because File::Temp will do it for you. See File::Temp for details.


Post a Comment