EliziumNet/Loopz

Show-Signals: emojis of length 3 not rendered properly

Closed this issue · 5 comments

In the screen-shot below:

show-signals emoji-length-3 bad

... the signals 'PASTE-A' and 'PATTERN'

are of length 3 and causes rendering failure (see the gap).

Actually, there are other length 3 emojis in the signal list, but they occur on the dark lines so this gap is hidden.

I think this is impossible to fix. Because the length of some emojis doesnt actually match its real length eg:

the length of 🛡️ is 3, why?

According to the link below, in unicode v13.1, that is supposed to be length 2.

See: http://randomguy32.de/unicode/misc/emoji-length/

For the shield emoji (🛡️, which is defined as length 2 in unicode spec 13.1, but in windows has length 3), the following code is able to return 2:

    $symbol = "🛡️";
    $enumerator = $symbol.EnumerateRunes();
    $count = 0;

    while ($enumerator.MoveNext()) {
      $count++;
    }

But we need a much more graceful and succinct way to get the count. This article suggests that:

$symbol.EnumerateRunes().Count()

but running this results in:

 RuntimeException: Method invocation failed because [System.Text.Rune] does not contain a method named 'Count'.
 at <ScriptBlock>, C:\Users\Plastikfan\dev\github\PoSh\Hoopz\Elizium.Loopz\Tests\Public\commands\Show-Signals.tests.ps1:30

PS: We need it to return 2, because that is the correct number of display characters that the shield takes up not the 3 that it is reported as having, causing subtle bugs, like this one being addressed, but even this doesn't fix the issue

Some experimntal code:

  It 'emojis' {

    #    (new System.Globalization.StringInfo("e\u0301")).LengthInTextElements

    $symbol = "🛡️"; # U+1F6E1
    # $length = (new System.Globalization.StringInfo($symbol)).LengthInTextElements;

    $utf16codepoints = $symbol.utf16

    $stringInfo = [System.Globalization.StringInfo]::new($symbol);
    $length = $stringInfo.LengthInTextElements;

    # $stringInfo.
    # $bytes = [System.Text.Encoding]::Unicode.GetBytes($symbol);
    # $rune = [System.Text.Rune]::DecodeLastFromUtf16($symbol, )

    $runes = $symbol.EnumerateRunes().ToString();
    $enumerator = $symbol.EnumerateRunes();
    $count = 0;

    while ($enumerator.MoveNext()) {
      $count++;
    }

    # $charCount = [System.Text.Encoding]::Default.GetCharCount($Symbol);

    # Write-Host "--> BYTES: '$bytes'"
    Write-Host "--> Length: $($symbol.Length)"
    Write-Host "--> LengthInTextElements: $($length)"
    Write-Host "--> Grapheme Count: $($count)"
    Write-Host "--> SYMBOL-INFO: '$($stringInfo.String)'"
    Write-Host "--> SYMBOL-INFO length: '$($stringInfo.String.Length)'"
    Write-Host "--> SYMBOL code points: '$($utf16codepoints)'"
    Write-Host "--> SYMBOL runes: '$($runes)'"
    Write-Host "--> FIRST: $($symbol[0])"
    Write-Host "--> SECOND: $($symbol[1])"
    Write-Host "--> THIRD: $($symbol[2])"
    # Write-Host "--> Char Count: '$charCount'"

    
  }

  It 'question' {
    function get-GraphemeLength {
      [OutputType([int])]
      param(
        [Parameter(Position = 0)]
        [string]$Value
      )
      [System.Text.StringRuneEnumerator]$enumerator = $Value.EnumerateRunes();
      [int]$count = 0;

      while ($enumerator.MoveNext()) {
        $count++;
      }

      return $count;
    }

    function show-Grapheme {
      param(
        [Parameter(Position = 0)]
        [string]$Value
      )
      [int]$graphemeLength = get-GraphemeLength $Value;
      Write-Host "Symbol: '$Value', length: '$($Value.Length)', grapheme length: '$graphemeLength'";
    }

    #                      "--", "---", "---"
    #                      012345678901234567890123456789
    [string[]]$symbols = @("🛡️", "🏷️", "🎯");
    [int]$graphemeLength = get-GraphemeLength $symbol;
    Write-Host "Ruler: ->0123456789";
    
    foreach ($sym in $symbols) {
      show-Grapheme $sym;
    }

    # [string]$format = "Greetings: '{0}'";
    [int]$width = 10;
    foreach ($sym in $symbols) {
      # Write-Host $($format -f $sym);
      [int]$filler = $width - $sym.Length;
      Write-Host "$([string]::new('*', $filler))$sym"
    }
  }

this issue is a FUCKING nightmare