2

I am trying to update the progress of my Perl script on the terminal. The output looks something like this

  Progress: |||||||||            [46%]

The progress keeps on getting updated until it reaches 100%. This is being done by printing "\r" after updating the progress. I wish to update multiple lines at the same time, how can it be done? The expectation is something like this

  Progress: |||||||||            [46%]
  Run-time: 100sec

After some progress(and or time) I wish to update it like this

  Progress: ||||||||||           [50%]
  Run-time: 150sec

I tried printing "\r" two times to go to the previous line. But it didn't work.

I found similar questions (here and here), but they were answered for Python using modules. Mine is a Perl script, and I am not preferring to use external modules.

srand9
  • 337
  • 1
  • 6
  • 20

1 Answers1

2

Term::ANSIScreen provides terminal control using ANSI escape sequences:

use Term::ANSIScreen qw!savepos loadpos!;

print savepos();
for my $i (1..10) {
    print '|' x $i, "\n";
    print "Step: $i\n";
    sleep 1;
    print loadpos();
}

or

use Term::ANSIScreen qw!up!;

for my $i (1..10) {
    print '|' x $i, "\n";
    print "Step: $i\n";
    sleep 1;
    print up(2);
}

These constants can be used instead of the module:

my $savepos = "\e[s";
my $loadpos = "\e[u";
my $up2 = "\e[2A";

ANSI escape codes

UjinT34
  • 4,784
  • 1
  • 12
  • 26
  • 1
    The general approach is solid, but `savepos`/`loadpos` doesn't work for me either. (It appears to only save/restore the X position, as you can see using `print "abc", savepos(), "def\n", loadpos(), "ghi\n";`.) I've added an alternative that works. (@toolic) – ikegami Aug 01 '20 at 14:16
  • 1
    (Tip: Always remember to print something at least as long as the message being overwritten or you can get garbage. Spaces can be used to erase. Shouldn't be a problem for the OP.) – ikegami Aug 01 '20 at 14:21
  • hey UjinT34 and @ikegami, thank you for adding your answers. Sorry for sounding finicky, but I do not wish to use any external modules. (Moreover, I'm working in a little restricted environment where I can't install any modules). Is there a direct way to jump back two lines without using any modules? I believe there must be some way to do it without modules. Thank you. – srand9 Aug 02 '20 at 14:39
  • 1
    `Term::ANSIScreen` returns ansi escape sequences. You can copy them to your script. – UjinT34 Aug 02 '20 at 15:07
  • Thank you @UjinT34. Escape sequences did the job. This is exactly what I've been looking for. – srand9 Aug 03 '20 at 13:59