Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

scalar or sub that can tell me the terminal print offset ?

by palkia (Monk)
on Mar 17, 2012 at 17:15 UTC ( #960184=perlquestion: print w/replies, xml ) Need Help??
palkia has asked for the wisdom of the Perl Monks concerning the following question:

I'm Looking for a scalar or a subroutine (or whatever),
that can tell me how many chars been printed
since the beginning of the current printed line in the terminal.
Does something like that exist, or do I must write it myself ?


Thanks for replaying everyone
It's not an XY problem, as it is (to me) an abstract problem.
(unless you refer to the flashing marker's XY co-ordinates ^^)
Although I agree it's a good guess, it is not for wrapping purposes.
I just need the column (x co-ordinate) of the marker.
In this specific case it's for a generalized-menu-printing function (specially designed for my format), which I'm working on,
but I found solving this problem necessary many times before for multiple applications (which I can't recall ^^).
So please think about it as a "how to get the marker's column" riddle/abstract problem,
rather than what possible uses can it have, and what alternatives can be used instead.

Thx again
  • Comment on scalar or sub that can tell me the terminal print offset ?

Replies are listed 'Best First'.
Re: scalar or sub that can tell me the terminal print offset ?
by Not_a_Number (Prior) on Mar 17, 2012 at 18:43 UTC

    Not sure what you're actually looking for.

    Would this fit the bill?

    my @strings = ( 'Paint it black', 'Satisfaction', 'Lady Jane' ) ; say $_, ' ', length for @strings;
      Thx, but no it won't.
      This is how I expect such a scalar (or sub) to work:
      1. Say I print a 5 (normal) chars string, than the desired scalar will have a increase in value of 5.
      2. when in the beginning of a line it will be zero.
      3. after a print of \n or \r, reset to zero.
      4. after a print of \t, increase value to the next multiple of 8.
      5. after a print of \b, decrease value by 1.
      6. after a print of \a, no change in value.
      7. modulus: every time it gets over 80 it is reduced by 80 (after 80 chars there's a new line).

      Probably some other rules too.
      I can figure these out, so I can write it (probably),
      but I find it hard to believe this doesn't already exists.
        >but I find it hard to believe this doesn't already exists.

        most probably this is just an xy problem. i.e. you are trying to solve a problem in a wrong way.

        I slightly remember a BASIC dialect which had such a feature to allow positioning the cursor, but in Perl I never missed this.

        IMHO in reality you'd rather prefer using

      • printf or
      • format or
      • templates with here-docs or
      • Term::ReadLine or
      • GUI-library like Tk

        (just some plausible guesses).

        If all of this is wrong and you don't wanna give us more insights, you can still try writing a routine out() to replace your prints, which automatically splits the arguments at newlines and counts the length of the last line in a global var $OUTPOS.

        Cheers Rolf

Re: scalar or sub that can tell me the terminal print offset ?
by Happy-the-monk (Canon) on Mar 17, 2012 at 19:36 UTC

    Feeling like I just returned from the 14th German Perl Workshop I felt markov's words still ringing in my ears: "print returns 1 if successful, whatever that means"

    That's what perldoc says. I had to look it up, because you made me wonder: it might just return any true value, so why not the number of characters printed. But unfortunately no. You may want to write a wrapper including your set of rules.

    Cheers, Sören

Re: scalar or sub that can tell me the terminal print offset ?
by BrowserUk (Pope) on Mar 19, 2012 at 16:22 UTC

    If your terminal has a VT100 mode, then you can use esc[6n to query the current cursor position.

    The device should respond with e[yyy;xxxR; where yyy is the line number on the screen and xxx is the column within the line. (e represent 'escape'.)

    How you obtain the report from the terminal without it printing on screen or moving the cursor is a trick I remember solving when I used to use a real VT100.

    But the (long faded) memory only tells me I solved it -- not how.

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    The start of some sanity?

Re: scalar or sub that can tell me the terminal print offset ?
by thundergnat (Deacon) on Mar 19, 2012 at 15:26 UTC

    I don't know of any module that provides this, but it doesn't seem like it would be that hard to implement.

    Oh what the heck, Something like this perhaps? (Could probably use some further testing.)

    UPDATE: fixed missing \a (bell) handling.

    use warnings; use strict; use Test; my ($linecount, $current_col, $tab) = (0, 0, 4); sub pr { for my $string (@_){ print $string; my $lines += () = $string =~ /[\n\r]/g; $current_col = 0 if $lines; $linecount += $lines; $string =~ s/.*[\n\r](.*)$/$1/sg; $string =~ s/\t/' ' x $tab/eg; my $bs = $string =~ tr/\b//; my $bell = $string =~ tr/\a//; $current_col += (length $string) - $bs * 2 - $bell; $current_col = 0 if $current_col < 0; $linecount += int($current_col / 80); $current_col %= 80; } } BEGIN { plan tests => 24 }; my @tests = ( ["1234567890", 0, 10], ["12345\n67890", 1, 5], ["12345\n67890\n12345", 2, 5], ["12345\r67890", 1, 5], ["12345\r67890\r12345", 2, 5], ["12345\t67890", 0, 10 + $tab], ["1234567890\b\b\b\b\b", 0, 5], [qw/1234567890 1234567890 1234567890 1234567890 1234567890/, 0, 50], ["1234567890" x 10, 1, 20], ["1234567890" x 100, 12, 40], ["1234567890" x 100, "\b" x 50, 12, 0], ["1\b2\b3\b4\b5\b6\b7\b8\b9\b0\b\n12345\t67890\n\t12345\b\b\b\b\b67890 +\t", 2, 5 + $tab*2], ["1234567890\a\b\a\b\a\b", 0, 7], ); for my $test (@tests){ ( $linecount, $current_col ) = ( 0, 0 ); my @strings = @$test; splice @strings, -2, 2, ''; pr $_ for @strings; print "<--\n"; ok($linecount, $test->[-2], "Linecount incorrect"); ok($current_col, $test->[-1], "Column count incorrect"); }
      Very similar to what I've done,
      but note that (at least in my terminal) you can't sub the tab for spaces, since it have a changing length based on previous characters.
      Here's my version (I only needed columns this time):
      my prntOffset = 0; sub prink #(string to print) { my $prntText = shift; print $prntText; if($prntText =~ s/.*[\n\r](.*)$/$1/s){$prntOffset = 0;} while(length $prntText) { if($prntText =~ s/^((\w|[\Q\\\/\{\};'"\[\]\.,\?\~\!@#$%^&* ()\E])+)// ) {$prntOffset += length $1;} #normal chars elsif(substr($prntText,0,1) eq "\b") { $prntText = substr($prntText,1); $prntOffset-- if $prntOffset; } elsif($prntText =~ s/^(\a+)//){} #yes nothing elsif($prntText =~ s/^(\t+)//) {$prntOffset += 8 * (length $1) - ($prntOffset % 8);} else { die "\ano pattern match for \"".substr($prntText,0,1)."\" in \"prink\" function\n"; } } $prntOffset %= 80; }
      Seems to hold for the few but focused tests I ran.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://960184]
Approved by Eliya
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (2)
As of 2018-05-23 01:58 GMT
Find Nodes?
    Voting Booth?