Skip to content

Commit

Permalink
Fixes conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
JJ committed Jun 21, 2018
2 parents 81f5da0 + 33a4b40 commit c678f27
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 118 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -26,3 +26,4 @@ highlights/node_modules
highlights/atom-language-perl6/
.DS_store
highlights/package-lock.json
.pod-cache
23 changes: 21 additions & 2 deletions doc/Type/IO.pod6
Expand Up @@ -352,7 +352,9 @@ spurt 'file-that-already-exists', 'new text', :createonly;
sub run(*@args ($, *@) --> Proc)
Runs an external command without involving a shell and returns a L<Proc> object.
Runs an external command I<without involving a shell> and returns a
L<Proc> object. By default, the external command will print to standard
output and error, and read from standard input.
run 'touch', '>foo.txt'; # Create a file named >foo.txt
Expand Down Expand Up @@ -383,14 +385,31 @@ use L<run> in non-sink context:
run 'false'; # SUNK! Will throw
run('false').so; # OK. Evaluates Proc in Bool context; no sinking
To capture output or error you can use the C<:out> or C<:err> arguments respectively:
If you want to capture standard output or error instead of having it
printed directly you can use the C<:out> or C<:err> arguments
respectively, which will make them available using the
L<C<Proc.out>|/type/Proc> method:
my $proc = run 'echo', 'Perl 6 is Great!', :out, :err;
$proc.out.slurp(:close).say; # OUTPUT: «Perl 6 is Great!␤»
$proc.err.slurp(:close).say; # OUTPUT: «␤»
<<<<<<< HEAD
See L<Proc|/type/Proc> and L<Proc::Async|/type/Proc::Async> for more
details.
=======
You can use these arguments to redirect them to a filehandle, thus
creating a kind of I<pipe>:
my $ls-alt-handle = open :w, '/tmp/cur-dir-ls-alt.txt';
my $proc = run "ls", "-alt", :out($ls-alt-handle);
# (The file will contain the output of the ls -alt command)
These argument are quite flexible and admit, for instance, handles to
redirect them. See L<Proc|/type/Proc> and
L<Proc::Async|/type/Proc::Async> for more details.
>>>>>>> 33a4b40ddb3fd10051a1bec568778745f34fe063
=head2 sub shell
Expand Down
46 changes: 26 additions & 20 deletions doc/Type/Proc/Async.pod6
Expand Up @@ -8,11 +8,12 @@
class Proc::Async {}
=end code
B<Note:> only the MoarVM backend of Rakudo implements C<Proc::Async> at the
moment.
B<Note:> only the MoarVM backend of Rakudo implements C<Proc::Async> at
the moment.
C<Proc::Async> allows you to run external commands asynchronously, capturing
standard output and error handles, and optionally write to its standard input.
C<Proc::Async> allows you to run external commands asynchronously,
capturing standard output and error handles, and optionally write to its
standard input.
=begin code
my $file = ‘foo’.IO;
Expand Down Expand Up @@ -127,18 +128,20 @@ An example of piping several commands like C<echo "Hello, world" | cat -n>:
multi method new(*@ ($path, *@args), :$w, :$enc, :$translate-nl --> Proc::Async:D)
multi method new( :$path, :@args, :$w, :$enc, :$translate-nl --> Proc::Async:D)
Creates a new C<Proc::Async> object with external program name or path C<$path>
and the command line arguments C<@args>.
Creates a new C<Proc::Async> object with external program name or path
C<$path> and the command line arguments C<@args>.
If C<:w> is passed to C<new>, then a pipe to the external program's standard
input stream (stdin) is opened, to which you can write with C<write> and
C<say>.
The C<:enc> specifies L<the encoding|/type/IO::Handle#method_encoding> for streams
(can still be overridden in individual methods) and defaults to C<utf8>.
The C<:enc> specifies L<the encoding|/type/IO::Handle#method_encoding>
for streams (can still be overridden in individual methods) and defaults
to C<utf8>.
If C<:translate-nl> is set to C<True> (default value), OS-specific newline
terminators (e.g. C<\r\n> on Windows) will be automatically translated to C<\n>.
If C<:translate-nl> is set to C<True> (default value), OS-specific
newline terminators (e.g. C<\r\n> on Windows) will be automatically
translated to C<\n>.
=head2 method stdout
Expand Down Expand Up @@ -186,8 +189,9 @@ along as L<Str|/type/Str>.
await $promise;
You must call C<stderr> before you call L<#method start>. Otherwise an
exception of class L<X::Proc::Async::TapBeforeSpawn|/type/X::Proc::Async::TapBeforeSpawn> is
thrown.
exception of class
L<X::Proc::Async::TapBeforeSpawn|/type/X::Proc::Async::TapBeforeSpawn>
is thrown.
If C<stderr> is not called, the external program's standard error stream is not
captured at all.
Expand All @@ -203,8 +207,8 @@ Use L«C<.Supply>|/type/Proc::Async#method_Supply» for merged STDOUT and STDERR
multi method bind-stdin(IO::Handle:D $handle)
multi method bind-stdin(Proc::Async::Pipe:D $pipe)
Sets a handle (which must be opened) or a C<Pipe> as a source of C<STDIN>. The C<STDIN> of
the target process must be writable or
Sets a handle (which must be opened) or a C<Pipe> as a source of
C<STDIN>. The C<STDIN> of the target process must be writable or
C<X::Proc::Async::BindOrUse> will be thrown.
my $p = Proc::Async.new("cat", :in);
Expand All @@ -223,16 +227,18 @@ and will print the content of C</etc/profile> to standard output.
method bind-stdout(IO::Handle:D $handle)
Redirects STDOUT of the target process to a handle (which must be opened).
If STDOUT is closed L<X::Proc::Async::BindOrUse|/type/x/proc/async/BindOrUse>
will be thrown.
Redirects STDOUT of the target process to a handle (which must be
opened). If STDOUT is closed
L<X::Proc::Async::BindOrUse|/type/x/proc/async/BindOrUse> will be
thrown.
my $p = Proc::Async.new("ls", :out);
my $h = "ls.out".IO.open(:w);
$p.bind-stdout($h);
$p.start;
This program will pipe the output of the C<ls> shell command to a file called C<ls.out>, which we are opened for reading.
This program will pipe the output of the C<ls> shell command to a file
called C<ls.out>, which we are opened for reading.
=head2 method bind-stderr
Expand Down Expand Up @@ -416,8 +422,8 @@ The C<Proc::Async> object must be created for writing (with
C<Proc::Async.new(:w, $path, @args)>). Otherwise an
L<X::Proc::Async::OpenForWriting> exception will the thrown.
C<start> must have been called before calling method close-stdin, otherwise an
L<X::Proc::Async::MustBeStarted> exception is thrown.
C<start> must have been called before calling method close-stdin,
otherwise an L<X::Proc::Async::MustBeStarted> exception is thrown.
=head2 method kill
Expand Down
23 changes: 23 additions & 0 deletions lib/Pod/Cache.pm
@@ -0,0 +1,23 @@
unit class Pod::Cache;

# Given a filename, generate a cached, rendered version of the POD
# in that file as text.

method cache-file(Str $file --> Str) {
my $outfile = '.pod-cache/' ~ $file;
my $output-io = $outfile.IO;

my $in-time = $file.IO.modified;
my $out-time = $output-io.e ?? $output-io.modified !! 0;

if $in-time > $out-time {
mkdir $output-io.dirname;
my $outfile = $output-io.open(:w);
$outfile.lock;
my $job = Proc::Async.new($*EXECUTABLE-NAME, '--doc', $file);
$job.stdout.tap(-> $buf {$outfile.print: $buf});

await $job.start;
}
$outfile
}
44 changes: 12 additions & 32 deletions xt/aspell.t
Expand Up @@ -2,7 +2,9 @@

use v6;
use Test;

use lib 'lib';
use Pod::Cache;
use Test-Files;

=begin overview
Expand All @@ -23,7 +25,6 @@ text that is part of a code example)
my @files = Test-Files.documents.grep({not $_ ~~ / 'README.' .. '.md' /});

plan +@files;
my $max-jobs = %*ENV<TEST_THREADS> // 2;

my $proc = shell('aspell -v');
if $proc.exitcode {
Expand All @@ -40,11 +41,9 @@ $dict.close;

my %output;

sub test-it($promises) {

sub test-it($promises, $file) {
await Promise.allof: |$promises;
my $tasks = $promises».result;
my $file = $tasks[0].command[*-1];

my $count;
for %output{$file}.lines -> $line {
Expand All @@ -58,35 +57,16 @@ sub test-it($promises) {
ok !$count, "$file has $so-many spelling errors";
}

my @jobs;

for @files -> $file {
if $file ~~ / '.pod6' $/ {
my $pod = Proc::Async.new($*EXECUTABLE-NAME, '--doc', $file);
my $fixer = Proc::Async.new('awk', 'BEGIN {print "!"} {print "^" gsub(/[\\:]/,"",$0)}');
$fixer.bind-stdin: $pod.stdout: :bin;
my $proc = Proc::Async.new(<aspell -a -l en_US --ignore-case --extra-dicts=./xt/aspell.pws>);
$proc.bind-stdin: $fixer.stdout: :bin;
%output{$file}="";
$proc.stdout.tap(-> $buf { %output{$file} = %output{$file} ~ $buf });
$proc.stderr.tap(-> $buf {});
push @jobs, [$pod.start, $fixer.start, $proc.start];
} else {
my $fixer = Proc::Async.new('awk', 'BEGIN {print "!"} {print "^" $0}', $file);
my $proc = Proc::Async.new(<aspell -a -l en_US --ignore-case --extra-dicts=./xt/aspell.pws>);
$proc.bind-stdin: $fixer.stdout: :bin;
%output{$file}="";
$proc.stdout.tap(-> $buf { %output{$file} = %output{$file} ~ $buf });
$proc.stderr.tap(-> $buf {});
push @jobs, [$fixer.start, $proc.start];
}

if +@jobs > $max-jobs {
test-it(@jobs.shift);
}
my $input-file = $file.ends-with('.pod6') ?? Pod::Cache.cache-file($file) !! $file;

my $fixer = Proc::Async.new('awk', 'BEGIN {print "!"} {print "^" gsub(/[\\:]/,"",$0)}', $input-file);
my $proc = Proc::Async.new(<aspell -a -l en_US --ignore-case --extra-dicts=./xt/aspell.pws>);
$proc.bind-stdin: $fixer.stdout: :bin;
%output{$file}="";
$proc.stdout.tap(-> $buf { %output{$file} = %output{$file} ~ $buf });
$proc.stderr.tap(-> $buf {});
test-it([$fixer.start, $proc.start], $file);
}


@jobs.map({test-it($_)});

# vim: expandtab shiftwidth=4 ft=perl6
25 changes: 4 additions & 21 deletions xt/double-dots.t
Expand Up @@ -2,7 +2,9 @@

use v6;
use Test;

use lib 'lib';
use Pod::Cache;
use Test-Files;

=begin overview
Expand All @@ -14,13 +16,6 @@ Avoid using C<..> - usually a typo for C<.> or C<...>
my @files = Test-Files.documents;

plan +@files;
my $max-jobs = %*ENV<TEST_THREADS> // 2;
my %output;

sub test-promise($promise) {
my $file = $promise.command[*-1];
test-it(%output{$file}, $file);
}

sub test-it(Str $output, Str $file) {
my $ok = True;
Expand All @@ -35,24 +30,12 @@ sub test-it(Str $output, Str $file) {
ok $ok, "$error: file contains ..";
}

my @jobs;
for @files -> $file {

my $output = "";

if $file ~~ / '.pod6' $/ {
my $a = Proc::Async.new($*EXECUTABLE-NAME, '--doc', $file);
%output{$file} = "";
$a.stdout.tap(-> $buf { %output{$file} = %output{$file} ~ $buf });
push @jobs: $a.start;
if +@jobs > $max-jobs {
test-promise(await @jobs.shift)
}
if $file.ends-with('.pod6') {
test-it(Pod::Cache.cache-file($file).IO.slurp, $file)
} else {
test-it($file.IO.slurp, $file);
}
}

for @jobs.map: {await $_} -> $r { test-promise($r) }

# vim: expandtab shiftwidth=4 ft=perl6
26 changes: 4 additions & 22 deletions xt/duplicates.t
Expand Up @@ -2,7 +2,9 @@

use v6;
use Test;

use lib 'lib';
use Pod::Cache;
use Test-Files;

=begin overview
Expand All @@ -23,14 +25,6 @@ my @files = Test-Files.documents \

plan +@files;

my $max-jobs = %*ENV<TEST_THREADS> // 2;
my %output;

sub test-promise($promise) {
my $file = $promise.command[*-1];
test-it(%output{$file}, $file);
}

sub test-it(Str $output, Str $file) {
my $ok = True;

Expand Down Expand Up @@ -67,24 +61,12 @@ sub test-it(Str $output, Str $file) {
is @dupes.join("\n"), '', $message;
}

my @jobs;
for @files -> $file {

my $output = '';

if $file ~~ / '.pod6' $/ {
my $a = Proc::Async.new($*EXECUTABLE-NAME, '--doc', $file);
%output{$file} = '';
$a.stdout.tap(-> $buf { %output{$file} = %output{$file} ~ $buf });
push @jobs: $a.start;
if +@jobs > $max-jobs {
test-promise(await @jobs.shift)
}
if $file.ends-with('.pod6') {
test-it(Pod::Cache.cache-file($file).IO.slurp, $file)
} else {
test-it($file.IO.slurp, $file);
}
}

for @jobs.map: {await $_} -> $r { test-promise($r) }

# vim: expandtab shiftwidth=4 ft=perl6
2 changes: 2 additions & 0 deletions xt/examples-compilation.t
Expand Up @@ -112,6 +112,8 @@ for @examples -> $eg {
temp $*ERR = open :w, $*SPEC.devnull;
try EVAL $code;
$status = $!;
close $*OUT;
close $*ERR;
}
todo(1) if $eg<todo>;
if $status {
Expand Down

0 comments on commit c678f27

Please sign in to comment.