ajr has asked for the wisdom of the Perl Monks concerning the following question:

Hi!

I am trying to find the visible length of a string (I print the same number of backspaces as the string, so I can provide a crude 'progress meter').

The addition of colour codes has really complicated things as "\033[32m" doesn't display on screen, yet length("\033[32m") returns 5.

I have got round the problem with:

#!/usr/bin/perl -w use strict; my $str = "\033[32m coloured! \033[m"; my $visible_length = length( $str ); while ( $str =~ /\033\[\d*m/g ) { $visible_length -= length($&); } print "Visible Length = $visible_length (should be 11)\n";
Is there a better way of doing this?

Edit by tye to put [ inside CODE tags

Replies are listed 'Best First'.
Re: finding visible length of string?
by BrowserUk (Patriarch) on Sep 18, 2002 at 23:51 UTC

    Why not bypass the problem of the length by using \r?

     print "\r\033[32m coloured! \033[m           ";

    Note the extra spaces on the end to ensure that if one string is shorter than that which preceeded it, the remnents of the preceeding one get erased.


    Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!

      A variation on this would be to just clear the whole line between prints. Something like:

      $|++; my $clear = "\r" . ' 'x80 . "\r"; print "quux"; sleep 1; print $clear, "foo"; sleep 1; print "\n";

      -sauoq
      "My two cents aren't worth a dime.";
      
        I was using "\b" x $i , but I was deleting up to a point which changed as the script progressed, with or without colours in the string (Aaarrgh!). A horrible mess!

        Removing the whole line seems the simplest way.

        <slaps forhead!>

        Thanks, O'holy ones!

Re: finding visible length of string?
by greenFox (Vicar) on Sep 19, 2002 at 01:45 UTC
    There was a previous thread on clearing a line here (Super Search is always your friend :-)) see my node for an approach using tput (works on *nix boxes). Depending on what else you are doing in your code but Curses or Curses:UI may also be worth looking at.

    --
    Until you've lost your reputation, you never realize what a burden it was or what freedom really is. -Margaret Mitchell

Re: finding visible length of string?
by alien_life_form (Pilgrim) on Sep 19, 2002 at 07:18 UTC
    Greetings,

    regardless of the proposed workarounds, the original formulation of the problem is interesting in its own right tho'...
    How would one compute the visible length? One obvious way would be by finding the screen position of the cursor before and after printing - something which I hazily remember was possible under curses...
    Other solutions?
    Cheers,
    alf


    You can't have everything: where would you put it?

      As the original questioner was using ANSI/VT100 escape sequences, depending on how faithfully they have been implemented, one way to find out the visible length of a printed string would be to use the Query Cursor Position sequence <ESC>[6n before and then after printing the string. On the original VT100's this used to cause the terminal to generate a sequence that looked like <ESC>[{ROW};{COLUMN}R. This had to be captured and parsed by the program. Issue the sequence, read the reply, parse out COLUMN. Print string and the sequence again, read the reply, parse the new COLUMN and subtract.

      Of course, if the implementation is sufficiently faithful to allow that sequence, then its much easier to simple postion the cursor absolutely using the Set Cursor Position sequence <ESC>[{ROW};{COLUMN}f each time before printing the string. That has the limitation that if the text beng printed is part of a larger body of text, then setting the position absolutely and getting it in the right place is difficult as terminals vary in width and height.

      If the terminal emulation supports it, possibly the very best way to do this would be to use the Save <ESC>[s and Restore <ESC>[u Cursor position sequences as prefix/suffix to the string being printed, but my previous experience of trying these is that they are often not supported.

      If the full ANSI/VT100 escape sequence set is supported, there are many other ways of achieving the original aim as well.


      Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!
        Note that not all terminal emulators provide this function. My favourite, rxvt, does not f.ex. Update: right, I should read closer..

        Makeshifts last the longest.

Re: finding visible length of string?
by jsprat (Curate) on Sep 19, 2002 at 17:33 UTC
    Another way to do it - just store the visible contents of the string in another variable.

    my $unformatted_str = ' coloured! '; my $str = "\033[32m $uf_str \033[m"; $visible_length = length $unformatted_str;