#!/usr/bin/env perl
|
|
|
|
# Execute shell commands with the included block passed to their stdin.
|
|
#
|
|
# I haven't wound up using this much, but in principle it has some
|
|
# applications.
|
|
#
|
|
# See also: filter-exec, filter-exec-raw.
|
|
|
|
use strict;
|
|
use warnings;
|
|
use 5.10.0;
|
|
|
|
use IPC::Cmd qw(can_run run_forked);
|
|
|
|
my $text;
|
|
{
|
|
# line separator:
|
|
local $/ = undef;
|
|
$text = <>;
|
|
}
|
|
|
|
$text =~ s{
|
|
<!--[ ]exec-stdin[ ](.*?)[ ]-->\n
|
|
(.*?)\n
|
|
<!--[ ]end[ ]-->
|
|
}{
|
|
handle_block($1, $2);
|
|
}egsx;
|
|
|
|
print $text;
|
|
|
|
sub handle_block {
|
|
my ($command, $input) = @_;
|
|
|
|
my $output_text = '';
|
|
|
|
my $result = run_forked($command, {
|
|
child_stdin => $input,
|
|
timeout => 300,
|
|
stdout_handler => sub { $output_text .= $_[0]; },
|
|
stderr_handler => sub { $output_text .= $_[0]; }
|
|
});
|
|
|
|
# Kill any trailing newlines so that the output will fit between markers
|
|
# without adding a blank line (something about this will probably lead to
|
|
# bugs eventually):
|
|
chomp($output_text);
|
|
|
|
my $starter = 'exec-stdin';
|
|
return "<!-- $starter $command -->\n$output_text\n<!-- end -->";
|
|
}
|
|
|
|
__DATA__
|
|
A self-test - add some numbers and use ,r in vim to check:
|
|
|
|
<!-- exec-stdin sort -n -->
|
|
1
|
|
2
|
|
3
|
|
8
|
|
9
|
|
10
|
|
<!-- end -->
|