From 59c20fa26595ed0f2f43bc13585c5496c07291a1 Mon Sep 17 00:00:00 2001 From: Ole Tange Date: Sat, 30 Apr 2022 14:28:26 +0200 Subject: [PATCH] parallel: --color implemented. --- src/parallel | 59 +++++++++++++++------- src/parallel.pod | 17 +++++-- src/parallel_alternatives.pod | 6 ++- testsuite/wanted-results/parallel-tutorial | 2 +- 4 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/parallel b/src/parallel index 72633895..e9ac1e60 100755 --- a/src/parallel +++ b/src/parallel @@ -1801,6 +1801,7 @@ sub options_completion_hash() { "[Tag lines with a string]:str" => \$opt::tagstring), "ctag[Color tag]:str" => \$opt::ctag, "ctag-string|ctagstring=s[Color tagstring]:str" => \$opt::ctagstring, + "color|colour[Colorize output]" => \$opt::color, ("onall[Run all the jobs on all computers given with --sshlogin]" => \$opt::onall), "nonall[--onall with no arguments]" => \$opt::nonall, @@ -2150,7 +2151,8 @@ sub parse_options(@) { parse_replacement_string_options(); $opt::tag ||= $opt::ctag; $opt::tagstring ||= $opt::ctagstring; - if(defined $opt::ctag or defined $opt::ctagstring) { + if(defined $opt::ctag or defined $opt::ctagstring + or defined $opt::color) { $Global::color = 1; } if(defined $opt::tag and not defined $opt::tagstring) { @@ -11098,7 +11100,18 @@ sub print_linebuffer($) { $i = ((rindex($buf,"\n")+1) || (rindex($buf,"\r")+1)); if($i) { # One or more complete lines were found - if($opt::tag or defined $opt::tagstring) { + if($Global::color) { + # To paint a full line, we need to turn on paint + # BEFORE printing \n + # print @$halfline_ref, substr($buf,0,$i); + my $print = join("",@$halfline_ref, substr($buf,0,$i)); + chomp($print); + # print color-on \n tag + my $tag = $self->tag(); + # TODO fix \r + $print =~ s/([\n\r])(?=.|$)/$tag/gs; + print $out_fh $tag,$print; + } elsif($opt::tag or defined $opt::tagstring) { # Replace ^ with $tag within the full line if($Global::cache_replacement_eval) { # Replace with the same value for tag @@ -11119,9 +11132,12 @@ sub print_linebuffer($) { $i = ::max((rindex($buf,"\n")+1), (rindex($buf,"\r")+1)); } + # Print the partial line (halfline) and the last half + print $out_fh @$halfline_ref, substr($buf,0,$i); + } else { + # Print the partial line (halfline) and the last half + print $out_fh @$halfline_ref, substr($buf,0,$i); } - # Print the partial line (halfline) and the last half - print $out_fh @$halfline_ref, substr($buf,0,$i); # Buffer in memory for SQL and CSV-output if($Global::membuffer) { push(@{$self->{'output'}{$fdno}}, @@ -11252,7 +11268,8 @@ sub print_normal($) { if($Global::parset and $fdno == 1) { $outputlength += $self->print_parset($fdno,$in_fh,$out_fh); - } elsif(defined $opt::tag or defined $opt::tagstring) { + } elsif(defined $opt::tag or defined $opt::tagstring + or $Global::color) { # Read line by line local $/ = "\n"; my $tag = $self->tag(); @@ -11260,6 +11277,7 @@ sub print_normal($) { $outputlength += length $_; # Tag lines with \r, too $_ =~ s/(?<=[\r])(?=.|$)/$tag/gs; + $Global::color and chomp(); print $out_fh $tag,$_; if($Global::membuffer) { push @{$self->{'output'}{$fdno}}, $tag, $_; @@ -11365,6 +11383,7 @@ sub print_joblog($) { { my @color; + my $color_on = ""; sub tag($) { sub init_color() { @@ -11388,22 +11407,20 @@ sub print_joblog($) { } my $self = shift; if(not defined $self->{'tag'} or not $Global::cache_replacement_eval) { + if($Global::color) { + if(not @color) { init_color() } + # Choose a value based on the seq + my $col = @color[$self->seq() % ($#color+1)]; + $color_on = "\033[48;5;".$col->[0].";38;5;".$col->[1]."m\n"; + } if(defined $opt::tag or defined $opt::tagstring) { - if($Global::color) { - if(not @color) { init_color() } - # Choose a value based on the seq - my $col = @color[$self->seq() % ($#color+1)]; - $self->{'tag'} = "\033[48;5;".$col->[0]. - ";38;5;".$col->[1]."m". - ($self->{'commandline'}-> - replace_placeholders([$opt::tagstring],0,0)). - "\033[00m\t"; - } else { - $self->{'tag'} = $self->{'commandline'}-> - replace_placeholders([$opt::tagstring],0,0)."\t"; - } + $self->{'tag'} = + $color_on . + ($self->{'commandline'}-> + replace_placeholders([$opt::tagstring],0,0)). + "\t"; } else { - $self->{'tag'} = ""; + $self->{'tag'} = $color_on; } } return $self->{'tag'}; @@ -14509,6 +14526,10 @@ sub main() { drain_job_queue(@command); ::debug("init", "Done draining\n"); reapers(); + if($Global::color) { + print $Global::original_stderr "\033[00m\n"; + print "\033[00m\n"; + } ::debug("init", "Done reaping\n"); if($Global::semaphore) { $sem->release(); diff --git a/src/parallel.pod b/src/parallel.pod index aa446812..ad18b054 100644 --- a/src/parallel.pod +++ b/src/parallel.pod @@ -748,6 +748,15 @@ B<--transfer>, B<--transferfile> or B<--return>. See also: B<--basefile> B<--transfer> B<--transferfile> B<--sshlogin> B<--return> +=item B<--color> + +Colour output. + +Colour the output. Each job gets its own color combination +(background+foreground). + +See also: B<--ctag> B<--ctagstring> + =item B<--colsep> I @@ -825,7 +834,7 @@ When used with B<--pipe> only pass full CSV-records. See also: B<--pipe> B<--link> B<{>IB<}> B<--colsep> B<--header> -=item B<--ctag> I +=item B<--ctag> (obsolete: use B<--color> B<--tag>) Color tag. @@ -833,14 +842,14 @@ If the values look very similar looking at the output it can be hard to tell when a new value is used. B<--ctag> gives each value a random color. -See also: B<--tag> +See also: B<--color> B<--tag> -=item B<--ctagstring> I +=item B<--ctagstring> I (obsolete: use B<--color> B<--tagstring>) Color tagstring. -See also: B<--ctag> B<--tagstring> +See also: B<--color> B<--ctag> B<--tagstring> =item B<--delay> I diff --git a/src/parallel_alternatives.pod b/src/parallel_alternatives.pod index d3fb6492..6120c618 100644 --- a/src/parallel_alternatives.pod +++ b/src/parallel_alternatives.pod @@ -3375,10 +3375,14 @@ Summary (see legend above): B

is a tiny shell script. It can color output with some predefined colors, but is otherwise quite limited. -It maxes out at 116000 jobs (probably due to limitations in Bash). +It maxes out at 116260 jobs (probably due to limitations in Bash). =head3 EXAMPLES FROM p +Some of the examples from B

cannot be implemented 100% by GNU +B: The coloring is a bit different, and GNU B +cannot have B<--tag> for some inputs and not for others. + The coloring done by GNU B is not exactly the same as B

. 1$ p -bc blue "ping 127.0.0.1" -uc red "ping 192.168.0.1" \ diff --git a/testsuite/wanted-results/parallel-tutorial b/testsuite/wanted-results/parallel-tutorial index 5f90d342..967974f1 100644 --- a/testsuite/wanted-results/parallel-tutorial +++ b/testsuite/wanted-results/parallel-tutorial @@ -847,7 +847,7 @@ For details: see man env_parallel export -f my_func3 parallel -vv --workdir ... --nice 17 --env _ --trc {}.out \ -S $SERVER1 my_func3 {} ::: abc-file -ssh -l parallel lo -- exec mkdir -p ./.TMPWORKDIR && rsync --protocol 30 -rlDzR -e'ssh -l parallel' ./abc-file lo:./.TMPWORKDIR;ssh -l parallel lo -- exec perl -X -e GNU_Parallel_worker,eval+pack+q/H10000000/,join+q//,@ARGV BASE64.BASE64;_EXIT_status=$?; mkdir -p ./. && rsync --protocol 30 -rlDzR -e'ssh -l parallel' --rsync-path='cd ./.TMPWORKDIR/./.; rsync' -- lo:./abc-file.out ./.;ssh -l parallel lo -- exec 'sh -c '"'"'rm -f ./.TMPWORKDIR/abc-file 2>/dev/null;rmdir ./.TMPWORKDIR/ ./.parallel/tmp/ ./.parallel/ 2>/dev/null;rm -rf ./.TMPWORKDIR;'"'";ssh -l parallel lo -- exec 'sh -c '"'"'rm -f ./.TMPWORKDIR/abc-file.out 2>/dev/null;rmdir ./.TMPWORKDIR/ ./.parallel/tmp/ ./.parallel/ 2>/dev/null;rm -rf ./.TMPWORKDIR;'"'";ssh -l parallel lo -- exec rm -rf .TMPWORKDIR;exit $_EXIT_status; +ssh -l parallel lo -- exec mkdir -p ./.TMPWORKDIR && rsync --protocol 30 -rlDzR -e'ssh -l parallel' ./abc-file lo:./.TMPWORKDIR;ssh -l parallel lo -- exec perl -X -e GNU_Parallel_worker,eval+pack+q/H10000000/,join+q//,@ARGV BASE64;_EXIT_status=$?; mkdir -p ./. && rsync --protocol 30 -rlDzR -e'ssh -l parallel' --rsync-path='cd ./.TMPWORKDIR/./.; rsync' -- lo:./abc-file.out ./.;ssh -l parallel lo -- exec 'sh -c '"'"'rm -f ./.TMPWORKDIR/abc-file 2>/dev/null;rmdir ./.TMPWORKDIR/ ./.parallel/tmp/ ./.parallel/ 2>/dev/null;rm -rf ./.TMPWORKDIR;'"'";ssh -l parallel lo -- exec 'sh -c '"'"'rm -f ./.TMPWORKDIR/abc-file.out 2>/dev/null;rmdir ./.TMPWORKDIR/ ./.parallel/tmp/ ./.parallel/ 2>/dev/null;rm -rf ./.TMPWORKDIR;'"'";ssh -l parallel lo -- exec rm -rf .TMPWORKDIR;exit $_EXIT_status; parset myvar1,myvar2 echo ::: a b echo $myvar1 echo $myvar2