final protected function getPrettyContext()

in src/_Private/CLIOutputHandler.hack [118:213]


  final protected function getPrettyContext(
    \Throwable $ex,
    string $file,
  ): ?string {
    if (!\file_exists($file)) {
      // Possibly running in repo-authoritative mode
      return null;
    }

    $frame = $ex->getTrace()
      |> Vec\filter(
        $$,
        $row ==>
          (($row as KeyedContainer<_, _>)['file'] ?? null) as ?string === $file,
      )
      |> C\last($$);

    if (!$frame is KeyedContainer<_, _>) {
      return null;
    }
    $colors = $this->terminal->supportsColors();
    $c_light = $colors ? "\e[2m" : '';
    $c_bold = $colors ? "\e[1m" : '';
    $c_red = $colors ? "\e[31m" : '';
    $c_reset = $colors ? "\e[0m" : '';

    $line = $frame['line'] as int;
    $line_number_width = Str\length((string)$line) + 2;

    $first_line = Math\maxva(1, $line - self::CONTEXT_LINES);
    $all_lines = \file_get_contents($file)
      |> Str\split($$, "\n");

    $context_lines = Vec\slice(
      $all_lines,
      $first_line - 1,
      ($line - $first_line),
    )
      |> Vec\map_with_key(
        $$,
        ($n, $content) ==> Str\format(
          '%s| %s%s%s',
          Str\pad_left((string)($n + $first_line), $line_number_width, ' '),
          $c_light,
          $content,
          $c_reset,
        ),
      );

    $blame_line = $all_lines[$line - 1];
    $fun = $frame['function'] as string;
    $fun_offset = Str\search($blame_line, $fun.'(');
    if ($fun_offset is null && Str\contains($fun, '\\')) {
      $fun = Str\split($fun, '\\') |> C\lastx($$);
      $fun_offset = Str\search($blame_line, $fun.'(');
    }
    if (
      $fun_offset is null && $frame['function'] === 'HH\\invariant_violation'
    ) {
      $fun = 'invariant';
      $fun_offset = Str\search($blame_line, 'invariant(');
    }

    if ($fun_offset is null) {
      $context_lines[] = Str\format(
        '%s%s>%s %s%s',
        Str\pad_left((string)$line, $line_number_width),
        $c_red,
        $c_reset.$c_bold,
        $blame_line,
        $c_reset,
      );
    } else {
      $context_lines[] = Str\format(
        '%s%s>%s %s%s%s%s%s%s',
        Str\pad_left((string)$line, $line_number_width),
        $c_red,
        $c_reset.$c_bold,
        Str\slice($blame_line, 0, $fun_offset),
        $c_red,
        $fun,
        $c_reset.$c_bold,
        Str\slice($blame_line, $fun_offset + Str\length($fun)),
        $c_reset,
      );

      $context_lines[] = Str\format(
        '%s%s%s%s',
        Str\repeat(' ', $line_number_width + $fun_offset + 2),
        $c_red,
        Str\repeat('^', Str\length($fun)),
        $c_reset,
      );
    }
    return $file.':'.$line."\n".Str\join($context_lines, "\n");
  }