parallel: --latest-line supports utf8, --colorfailed and line long --tag.

This commit is contained in:
Ole Tange 2022-11-09 00:09:33 +01:00
parent 3fa3bb6c5f
commit 77e9f59abb
5 changed files with 172 additions and 142 deletions

View file

@ -230,7 +230,9 @@ https://savannah.gnu.org/news/approve.php?group=parallel
// FreeCode is dying
http://freshmeat.net/projects/parallel/releases/new
== Update Diaspora Twitter ==
== Update Mastodon Twitter ==
https://hostux.social/web/@GNU_Parallel
https://joindiaspora.com/stream
@ -259,7 +261,7 @@ from:tange@gnu.org
to:parallel@gnu.org, bug-parallel@gnu.org
stable-bcc: Jesse Alama <jessealama@fastmail.fm>
Subject: GNU Parallel 20221122 ('Lula/#MashaAmina') released
Subject: GNU Parallel 20221122 ('Херсо́н/Lula/#MashaAmina') released
GNU Parallel 20221122 ('<<>>') has been released. It is available for download at: lbry://@GnuParallel:4
@ -269,6 +271,16 @@ Quote of the month:
New in this release:
* JoinDiaspora is closing. New Mastodon account: @GNU_Parallel@hostux.social
* Allow IPv6 and _ in hostname.
* Use --total-jobs if you use --bar and input is generated slowly.
* --latest-line deals correcly with jobs not visible yet.
* --bar supports utf8
* <<>>
* Bug fixes and man page updates.

View file

@ -2228,6 +2228,7 @@ sub parse_options(@) {
}
if($opt::linebuffer or $opt::latestline) {
$Global::linebuffer = 1;
Job::latestline_init();
}
if(defined $opt::tag and not defined $opt::tagstring) {
# Default = {}
@ -2486,21 +2487,21 @@ sub parse_options(@) {
parse_semaphore();
if(defined $opt::eta) { $opt::progress = $opt::eta; }
if(defined $opt::bar) {
if(defined $opt::bar) { $opt::progress = $opt::bar; }
if(defined $opt::bar or defined $opt::latestline) {
my $fh = $Global::status_fd || *STDERR;
eval q{
# Enable utf8 if possible
use utf8;
binmode $fh, "encoding(utf8)";
*decode = \&Encode::decode_utf8;
*decode_utf8 = \&Encode::decode_utf8;
};
if(eval { decode("x") }) {
if(eval { decode_utf8("x") }) {
# Great: decode works
} else {
# UTF8-decode not supported: Dummy decode
eval q{sub decode { $_[0]; }};
eval q{sub decode_utf8($;$) { $_[0]; }};
}
$opt::progress = $opt::bar;
}
# Funding a free software project is hard. GNU Parallel is no
@ -4413,7 +4414,7 @@ sub progress() {
my $arg = $Global::newest_job ?
$Global::newest_job->{'commandline'}->
replace_placeholders(["\257<\257>"],0,0) : "";
$arg = decode($arg);
$arg = decode_utf8($arg);
my $eta_dhms = ::seconds_to_time_units($eta);
my $bar_text =
sprintf("%d%% %d:%d=%s %s",
@ -5453,6 +5454,7 @@ sub reaper() {
$Global::timeoutq->update_median_runtime($job->runtime());
}
if($opt::keeporder and not $opt::latestline) {
# --latestline fixes --keeporder in Job::row()
$job->print_earlier_jobs();
} else {
$job->print();
@ -9005,9 +9007,9 @@ sub replaced($) {
my $self = shift;
if(not defined $self->{'row'}) {
if($opt::keeporder) {
$self->{'row'} = $self->seq()-1;
$self->{'row'} = $self->seq();
} else {
$self->{'row'} = $next_available_row++;
$self->{'row'} = ++$next_available_row;
}
}
return $self->{'row'};
@ -11302,10 +11304,22 @@ sub print_files($) {
# --tag
# --bar
{
my ($up,$init,$currow,$maxrow);
my ($up,$currow,$maxrow);
my ($minvisible,%print_later,%notvisible);
my (%binmodeset,%tab);
sub latestline_init() {
# cursor_up cuu1 = up one line
$up = `sh -c "tput cuu1 </dev/tty" 2>/dev/null`;
chomp($up);
$currow = 1;
$maxrow = 1;
$minvisible = 1;
for(0..8) {
$tab{$_} = " "x(8-($_%8));
}
}
sub print_linebuffer($) {
sub print_latest_line($) {
my $self = shift;
my $out_fh = shift;
@ -11313,67 +11327,67 @@ sub print_files($) {
# Is row visible?
if(not ($minvisible <= $row
and
$row < $minvisible -1 + ::terminal_rows())) {
$row < $minvisible + ::terminal_rows() - 1)) {
return;
}
my ($color,$reset_color) = $self->color();
# Strings with TABs give the wrong length.
# Untabify strings, add " " till full terminal width to overwrite
# earlier longer line.
my $termcol = ::terminal_columns();
my $untabify_tag = $self->untabtag();
my $taglen = ::min(length $untabify_tag,$termcol);
my $strlen = $termcol - $taglen;
my $untabify_str = $self->{$out_fh,'latestline'};
$untabify_str =~ s/\t/" "x(8-($-[0]%8))/eg;
my $strspc = $strlen - length $untabify_str;
if($strspc > 0) {
# Line is shorter than terminal width: fill with spc
$untabify_str = $untabify_str." "x$strspc;
} else {
# Line is longer than terminal width: chop + add ">"
$untabify_str = substr($untabify_str,0,$strlen-1).">";
if(not $binmodeset{$out_fh}++) {
# Enable utf8 if possible
eval q{ binmode $out_fh, "encoding(utf8)"; };
}
my ($color,$reset_color) = $self->color();
# Strings with TABs give the wrong length. Untabify strings
my $termcol = ::terminal_columns();
my $untabify_tag = ::decode_utf8($self->untabtag());
my $taglen = length $untabify_tag;
my $truncated_tag = "";
my $strlen = $termcol - $taglen;
my $untabify_str = ::decode_utf8($self->{$out_fh,'latestline'});
$untabify_str =~ s/\t/$tab{$-[0]%8}/g;
my $strspc = $strlen - length $untabify_str;
$strlen--;
if($strlen < 0) { $strlen = 0;}
# Line is shorter than terminal width: add " "
# Line is longer than terminal width: add ">"
my $truncated = ($strspc > 0) ? " " : ">";
if($taglen > $termcol) {
# Tag is longer than terminal width: add ">" to tag
# Remove $truncated (it will not be shown at all)
$taglen = $termcol - 1;
$truncated_tag = ">";
$truncated = "";
}
$untabify_tag = substr($untabify_tag,0,$taglen);
$maxrow = $row > $maxrow ? $row : $maxrow;
printf($out_fh
"%s%s%s%.${taglen}s%s%.${strlen}s%s%s",
("%s%s%s". # up down \r
"%.${taglen}s%s". # tag
"%s%.${strlen}s%s%s". # color + line
"%s" # down
),
"$up"x($currow - $row),
"\n"x($row - $currow),
"\r", $untabify_tag,
$color, $untabify_str, $reset_color,
"\r", $untabify_tag,$truncated_tag,
$color, $untabify_str, $truncated, $reset_color,
"\n"x($maxrow - $row + 1));
$currow = $maxrow + 1;
}
sub print_linebuffer($) {
my $self = shift;
my ($fdno,$in_fh,$out_fh) = @_;
if(defined $self->{'exitstatus'}) {
# If the job is dead: close printing fh. Needed for --compress
close $self->fh($fdno,"w");
if($? and $opt::compress) {
if($opt::compress) {
if($?) {
::error($opt::compress_program." failed.");
$self->set_exitstatus(255);
}
if($opt::compress) {
# Blocked reading in final round
for my $fdno (1,2) {
::set_fh_blocking($self->fh($fdno,'r'));
}
for my $fdno (1,2) { ::set_fh_blocking($self->fh($fdno,'r')); }
}
if($opt::latestline) { $print_later{$self->row()} = $self; }
}
if(not $init) {
$init = 1;
if($opt::latestline) {
# cursor_up cuu1 = up one line
$up = `tput cuu1 </dev/tty`;
chomp($up);
$currow = 0;
$maxrow = 0;
$minvisible = 0;
}
}
if(not $self->virgin()) {
if($opt::files or ($opt::results and not $Global::csvsep)) {
# Print filename
@ -11475,13 +11489,14 @@ sub print_files($) {
}
}
$self->add_returnsize($outputlength);
if($opt::latestline) {
$self->print_latest_line($out_fh);
}
if($opt::latestline) { $self->print_latest_line($out_fh); }
}
if(defined $self->{'exitstatus'}) {
if($opt::latestline) {
# Print latest line from jobs that are already scrolled by
# Force re-computing color if --colorfailed
if($opt::colorfailed) { delete $self->{'color'}; }
$self->print_latest_line($out_fh);
# Print latest line from jobs that are already done
while($print_later{$minvisible}) {
$print_later{$minvisible}->print_latest_line($out_fh);
delete $print_later{$minvisible};

View file

@ -25,15 +25,20 @@ par_totaljobs() {
par_ll_long_line() {
echo '### --latest-line with lines longer than terminal width'
COLUMNS=30 parallel --delay 0.3 --tagstring '{=$_.="x"x$_=}' \
--ll 'echo {}00000 | sed -e "s/$/' {1..100} /'"' ::: {1..30} |
perl -pe 's/.\[A//'
--ll 'echo {}00000 | sed -e "s/$/' {1..100} /'"' ::: {01..30} |
perl -ne 's/.\[A//g;
/.\[K .{4}\[m/ and next;
/x\s*$/ and next;
/\S/ && print'| sort -u
}
par_ll_color_long_line() {
echo '### --latest-line --color with lines longer than terminal width'
COLUMNS=30 parallel --delay 0.3 --color --tagstring '{=$_.="x"x$_=}' \
--ll 'echo {}00000 | sed -e "s/$/' {1..100} /'"' ::: {1..30} |
perl -pe 's/.\[A//'
--ll 'echo {}00000 | sed -e "s/$/' {1..100} /'"' ::: {01..30} |
perl -ne 's/.\[A//g;
/.\[K .{4}\[m/ and next;
/\S/ && print'| sort -u
}
par_reload_slf_every_second() {

View file

@ -530,69 +530,67 @@ par_line_buffer ### --line-buffer
par_line_buffer 55 55 120
par_line_buffer These must diff: 1
par_ll_color_long_line ### --latest-line --color with lines longer than terminal width
par_ll_color_long_line par_ll_color_long_line 1x 100000 1 2 3 4 5 6 7 8(B
par_ll_color_long_line
par_ll_color_long_line par_ll_color_long_line 2xx 200000 1 2 3 4 5 6 7 8(B
par_ll_color_long_line par_ll_color_long_line 3xxx 300000 1 2 3 4 5 6 7 8(B
par_ll_color_long_line par_ll_color_long_line 4xxxx 400000 1 2 3 4 5 6 7 8(B
par_ll_color_long_line par_ll_color_long_line 5xxxxx 500000 1 2 3 4 5 6 7 8(B
par_ll_color_long_line par_ll_color_long_line 6xxxxxx 600000 1 2 3 4 5 6 7 8(B
par_ll_color_long_line par_ll_color_long_line 7xxxxxxx 700000 1 2 3 4(B
par_ll_color_long_line par_ll_color_long_line 8xxxxxxxx 800000 1 2 3 4(B
par_ll_color_long_line par_ll_color_long_line 9xxxxxxxxx 900000 1 2 3 4(B
par_ll_color_long_line par_ll_color_long_line 10xxxxxxxxxx 1000000 1 2 3 (B
par_ll_color_long_line par_ll_color_long_line 11xxxxxxxxxxx 1100000 1 2 3 (B
par_ll_color_long_line par_ll_color_long_line 12xxxxxxxxxxxx 1200000 1 2 3 (B
par_ll_color_long_line par_ll_color_long_line 13xxxxxxxxxxxxx 1300000 1 2 3 (B
par_ll_color_long_line par_ll_color_long_line 14xxxxxxxxxxxxxx 140000(B
par_ll_color_long_line par_ll_color_long_line 15xxxxxxxxxxxxxxx 150000(B
par_ll_color_long_line par_ll_color_long_line 16xxxxxxxxxxxxxxxx 160000(B
par_ll_color_long_line par_ll_color_long_line 17xxxxxxxxxxxxxxxxx 170000(B
par_ll_color_long_line par_ll_color_long_line 18xxxxxxxxxxxxxxxxxx 180000(B
par_ll_color_long_line par_ll_color_long_line 19xxxxxxxxxxxxxxxxxxx 190000(B
par_ll_color_long_line par_ll_color_long_line 20xxxxxxxxxxxxxxxxxxxx 200000(B
par_ll_color_long_line par_ll_color_long_line 21xxxxxxxxxxxxxxxxxxxxx 210000(B
par_ll_color_long_line par_ll_color_long_line 22xxxxxxxxxxxxxxxxxxxxxx (B
par_ll_color_long_line par_ll_color_long_line 23xxxxxxxxxxxxxxxxxxxxxxx (B
par_ll_color_long_line par_ll_color_long_line 24xxxxxxxxxxxxxxxxxxxxxxxx (B
par_ll_color_long_line par_ll_color_long_line 25xxxxxxxxxxxxxxxxxxxxxxxxx (B
par_ll_color_long_line par_ll_color_long_line 26xxxxxxxxxxxxxxxxxxxxxxxxxx (B
par_ll_color_long_line par_ll_color_long_line 27xxxxxxxxxxxxxxxxxxxxxxxxxxx (B
par_ll_color_long_line par_ll_color_long_line 28xxxxxxxxxxxxxxxxxxxxxxxxxxxx(B
par_ll_color_long_line par_ll_color_long_line 29xxxxxxxxxxxxxxxxxxxxxxxxxxxx(B
par_ll_color_long_line par_ll_color_long_line 30xxxxxxxxxxxxxxxxxxxxxxxxxxxx(B
par_ll_color_long_line par_ll_color_long_line 01x 0100000 1 2 3 4 5 6 7>(B
par_ll_color_long_line par_ll_color_long_line 02xx 0200000 1 2 3 4 5 6 7>(B
par_ll_color_long_line par_ll_color_long_line 03xxx 0300000 1 2 3 4 5 6 7>(B
par_ll_color_long_line par_ll_color_long_line 04xxxx 0400000 1 2 3 4 5 6 7>(B
par_ll_color_long_line par_ll_color_long_line 05xxxxx 0500000 1 2 3 4 5 6 7>(B
par_ll_color_long_line par_ll_color_long_line 06xxxxxx 0600000 1 2 3>(B
par_ll_color_long_line par_ll_color_long_line 07xxxxxxx 0700000 1 2 3>(B
par_ll_color_long_line par_ll_color_long_line 08xxxxxxxx 0800000 1 2 3>(B
par_ll_color_long_line par_ll_color_long_line 09xxxxxxxxx 0900000 1 2 3>(B
par_ll_color_long_line par_ll_color_long_line 10xxxxxxxxxx 1000000 1 2 3>(B
par_ll_color_long_line par_ll_color_long_line 11xxxxxxxxxxx 1100000 1 2 3>(B
par_ll_color_long_line par_ll_color_long_line 12xxxxxxxxxxxx 1200000 1 2 3>(B
par_ll_color_long_line par_ll_color_long_line 13xxxxxxxxxxxxx 1300000 1 2 3>(B
par_ll_color_long_line par_ll_color_long_line 14xxxxxxxxxxxxxx 14000>(B
par_ll_color_long_line par_ll_color_long_line 15xxxxxxxxxxxxxxx 15000>(B
par_ll_color_long_line par_ll_color_long_line 16xxxxxxxxxxxxxxxx 16000>(B
par_ll_color_long_line par_ll_color_long_line 17xxxxxxxxxxxxxxxxx 17000>(B
par_ll_color_long_line par_ll_color_long_line 18xxxxxxxxxxxxxxxxxx 18000>(B
par_ll_color_long_line par_ll_color_long_line 19xxxxxxxxxxxxxxxxxxx 19000>(B
par_ll_color_long_line par_ll_color_long_line 20xxxxxxxxxxxxxxxxxxxx 20000>(B
par_ll_color_long_line par_ll_color_long_line 21xxxxxxxxxxxxxxxxxxxxx 21000>(B
par_ll_color_long_line par_ll_color_long_line 22xxxxxxxxxxxxxxxxxxxxxx >(B
par_ll_color_long_line par_ll_color_long_line 23xxxxxxxxxxxxxxxxxxxxxxx >(B
par_ll_color_long_line par_ll_color_long_line 24xxxxxxxxxxxxxxxxxxxxxxxx >(B
par_ll_color_long_line par_ll_color_long_line 25xxxxxxxxxxxxxxxxxxxxxxxxx >(B
par_ll_color_long_line par_ll_color_long_line 26xxxxxxxxxxxxxxxxxxxxxxxxxx >(B
par_ll_color_long_line par_ll_color_long_line 27xxxxxxxxxxxxxxxxxxxxxxxxxxx>(B
par_ll_color_long_line par_ll_color_long_line 28xxxxxxxxxxxxxxxxxxxxxxxxxxx>(B
par_ll_color_long_line par_ll_color_long_line 29xxxxxxxxxxxxxxxxxxxxxxxxxxx>(B
par_ll_color_long_line par_ll_color_long_line 30xxxxxxxxxxxxxxxxxxxxxxxxxxx>(B
par_ll_long_line ### --latest-line with lines longer than terminal width
par_ll_long_line par_ll_long_line 1x 100000 1 2 3 4 5 6 7 8
par_ll_long_line
par_ll_long_line par_ll_long_line 2xx 200000 1 2 3 4 5 6 7 8
par_ll_long_line par_ll_long_line 3xxx 300000 1 2 3 4 5 6 7 8
par_ll_long_line par_ll_long_line 4xxxx 400000 1 2 3 4 5 6 7 8
par_ll_long_line par_ll_long_line 5xxxxx 500000 1 2 3 4 5 6 7 8
par_ll_long_line par_ll_long_line 6xxxxxx 600000 1 2 3 4 5 6 7 8
par_ll_long_line par_ll_long_line 7xxxxxxx 700000 1 2 3 4
par_ll_long_line par_ll_long_line 8xxxxxxxx 800000 1 2 3 4
par_ll_long_line par_ll_long_line 9xxxxxxxxx 900000 1 2 3 4
par_ll_long_line par_ll_long_line 10xxxxxxxxxx 1000000 1 2 3
par_ll_long_line par_ll_long_line 11xxxxxxxxxxx 1100000 1 2 3
par_ll_long_line par_ll_long_line 12xxxxxxxxxxxx 1200000 1 2 3
par_ll_long_line par_ll_long_line 13xxxxxxxxxxxxx 1300000 1 2 3
par_ll_long_line par_ll_long_line 14xxxxxxxxxxxxxx 140000
par_ll_long_line par_ll_long_line 15xxxxxxxxxxxxxxx 150000
par_ll_long_line par_ll_long_line 16xxxxxxxxxxxxxxxx 160000
par_ll_long_line par_ll_long_line 17xxxxxxxxxxxxxxxxx 170000
par_ll_long_line par_ll_long_line 18xxxxxxxxxxxxxxxxxx 180000
par_ll_long_line par_ll_long_line 19xxxxxxxxxxxxxxxxxxx 190000
par_ll_long_line par_ll_long_line 20xxxxxxxxxxxxxxxxxxxx 200000
par_ll_long_line par_ll_long_line 21xxxxxxxxxxxxxxxxxxxxx 210000
par_ll_long_line par_ll_long_line 22xxxxxxxxxxxxxxxxxxxxxx
par_ll_long_line par_ll_long_line 23xxxxxxxxxxxxxxxxxxxxxxx
par_ll_long_line par_ll_long_line 24xxxxxxxxxxxxxxxxxxxxxxxx
par_ll_long_line par_ll_long_line 25xxxxxxxxxxxxxxxxxxxxxxxxx
par_ll_long_line par_ll_long_line 26xxxxxxxxxxxxxxxxxxxxxxxxxx
par_ll_long_line par_ll_long_line 27xxxxxxxxxxxxxxxxxxxxxxxxxxx
par_ll_long_line par_ll_long_line 28xxxxxxxxxxxxxxxxxxxxxxxxxxxx
par_ll_long_line par_ll_long_line 29xxxxxxxxxxxxxxxxxxxxxxxxxxxx
par_ll_long_line par_ll_long_line 30xxxxxxxxxxxxxxxxxxxxxxxxxxxx
par_ll_long_line par_ll_long_line 01x 0100000 1 2 3 4 5 6 7>
par_ll_long_line par_ll_long_line 02xx 0200000 1 2 3 4 5 6 7>
par_ll_long_line par_ll_long_line 03xxx 0300000 1 2 3 4 5 6 7>
par_ll_long_line par_ll_long_line 04xxxx 0400000 1 2 3 4 5 6 7>
par_ll_long_line par_ll_long_line 05xxxxx 0500000 1 2 3 4 5 6 7>
par_ll_long_line par_ll_long_line 06xxxxxx 0600000 1 2 3>
par_ll_long_line par_ll_long_line 07xxxxxxx 0700000 1 2 3>
par_ll_long_line par_ll_long_line 08xxxxxxxx 0800000 1 2 3>
par_ll_long_line par_ll_long_line 09xxxxxxxxx 0900000 1 2 3>
par_ll_long_line par_ll_long_line 10xxxxxxxxxx 1000000 1 2 3>
par_ll_long_line par_ll_long_line 11xxxxxxxxxxx 1100000 1 2 3>
par_ll_long_line par_ll_long_line 12xxxxxxxxxxxx 1200000 1 2 3>
par_ll_long_line par_ll_long_line 13xxxxxxxxxxxxx 1300000 1 2 3>
par_ll_long_line par_ll_long_line 14xxxxxxxxxxxxxx 14000>
par_ll_long_line par_ll_long_line 15xxxxxxxxxxxxxxx 15000>
par_ll_long_line par_ll_long_line 16xxxxxxxxxxxxxxxx 16000>
par_ll_long_line par_ll_long_line 17xxxxxxxxxxxxxxxxx 17000>
par_ll_long_line par_ll_long_line 18xxxxxxxxxxxxxxxxxx 18000>
par_ll_long_line par_ll_long_line 19xxxxxxxxxxxxxxxxxxx 19000>
par_ll_long_line par_ll_long_line 20xxxxxxxxxxxxxxxxxxxx 20000>
par_ll_long_line par_ll_long_line 21xxxxxxxxxxxxxxxxxxxxx 21000>
par_ll_long_line par_ll_long_line 22xxxxxxxxxxxxxxxxxxxxxx >
par_ll_long_line par_ll_long_line 23xxxxxxxxxxxxxxxxxxxxxxx >
par_ll_long_line par_ll_long_line 24xxxxxxxxxxxxxxxxxxxxxxxx >
par_ll_long_line par_ll_long_line 25xxxxxxxxxxxxxxxxxxxxxxxxx >
par_ll_long_line par_ll_long_line 26xxxxxxxxxxxxxxxxxxxxxxxxxx >
par_ll_long_line par_ll_long_line 27xxxxxxxxxxxxxxxxxxxxxxxxxxx>
par_ll_long_line par_ll_long_line 28xxxxxxxxxxxxxxxxxxxxxxxxxxx>
par_ll_long_line par_ll_long_line 29xxxxxxxxxxxxxxxxxxxxxxxxxxx>
par_ll_long_line par_ll_long_line 30xxxxxxxxxxxxxxxxxxxxxxxxxxx>
par_load_blocks ### Test if --load blocks. Bug.
par_load_blocks 53d025127ae99ab79e8502aae2d9bea6 -
par_load_blocks 53d025127ae99ab79e8502aae2d9bea6 -

View file

@ -120,7 +120,7 @@ par_kill_hup parallel: bash -c 'sleep 3 & pid=$!; wait $pid'
par_kill_hup bash---pstree
par_ll_lb_color bug #62386: --color (--ctag but without --tag)
par_ll_lb_color bug #62438: See last line from multiple jobslots
par_ll_lb_color c13699ada05324a5bab5aee05d97aa55 -
par_ll_lb_color c9a124d7cbd2d04b1201b297ef7cefa1 -
par_more_than_9_relative_sshlogin ### Check more than 9(relative) simultaneous sshlogins
par_more_than_9_relative_sshlogin 1
par_more_than_9_relative_sshlogin 2