ab5tract / Terminal-Print

Terminal::Print is a pure Raku layer for printing to terminal screens
Other
25 stars 18 forks source link

Character width is not addressed #10

Open ab5tract opened 8 years ago

ab5tract commented 8 years ago

We need to decide on an approach for character width.

I will likely use bluebear94's Terminal::WCWidth module for this, as it seems that you really do need some kind of lookup file for this -- it doesn't seem to be something you can derive from Str or Uni (please correct me if I am wrong!).

We have Cell objects that already enable us to have color information, so presumably this should be relatively trivial.

Perhaps an attribute on Cell that, when defined, means that it is part of a double-width character?

multi method change-cell($x, $y, $char where *.is-wide) { # psuedocoded subset
    @grid[$x][$y] = Cell.new( :$char );
    @grid[$x+1][$y] = Cell.new( char => '', :invisible);
}

multi method print-cell($x, $y) {
    my $cell = @grid[$x][$y];
    print ~$cell unless $cell.invisible;
}

I'm open to other ideas as well, of course!

jjatria commented 4 years ago

I have a branch where I've added Terminal::WCWidth to Terminal::Print, and it works fine (the only problem is that the Terminal::WCWidth tables are pretty outdated, but if my https://github.com/bluebear94/Terminal-WCWidth/pull/6 gets merged that shouldn't be an issue).

It does have a performance impact, though, since it does a lookup each time. On my machine it meant a good extra ~2s when running raku examples/rpg-ui.p6 --bench. I managed to get rid of this using a cache (I used Cache::LRU, but something else would also work).

For what it's worth, you can also skip the external dependency with something like

my $cache = ...
sub wcswidth ( Str:D $str --> Int ) {
    [+] $str.comb.map: {
        $cache{$_}
            //= .uniprop                     eq 'Mn' | 'Me' ?? 0
            !!  .uniprop('East_Asian_Width') eq 'W'  | 'F'  ?? 2
            !!  1;
    }
}

which is basically the same that Terminal::WCWidth does (with the difference it does the lookups in advance and it does not cache).