Skip to content

Commit

Permalink
v2
Browse files Browse the repository at this point in the history
  • Loading branch information
Félix Dorn committed Mar 14, 2024
1 parent b0d9576 commit 9d0e1c8
Show file tree
Hide file tree
Showing 15 changed files with 293 additions and 226 deletions.
38 changes: 12 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# tin

tin is a PHP code highlighter for the terminal.
tin is a code highlighter for PHP (Terminal, HTML, etc.).

[![Tests](https://github.com/felixdorn/tin/actions/workflows/tests.yml/badge.svg)](https://github.com/felixdorn/tin/actions/workflows/tests.yml)
[![Formats](https://github.com/felixdorn/tin/actions/workflows/formats.yml/badge.svg)](https://github.com/felixdorn/tin/actions/workflows/formats.yml)
Expand Down Expand Up @@ -39,30 +39,20 @@ echo Tin::from(JetbrainsDark::class, $ansi = true)->highlight("<?php\n\necho 'He

## Customizing the output

Apart from using a custom theme to change the colors, you have complete control over the highlighting proccess.
You have complete control over the highlighting process. Implement
the [`Felix\Tin\Contracts\OutputInterface`](src/Contracts/OutputInterface.php) interface or implement a custom theme if
you are just looking to change the colors.

```php
$tin->process(
$code,
function (\Felix\Tin\Line $line) {
$lineNumber = $line->output->transform(
\Felix\Tin\Enums\TokenType::LineNumber,
str_pad(
(string) $line->number,
strlen((string) $line->totalCount), ' ',
STR_PAD_LEFT
) . ' | ',
);

return $lineNumber . $line->toString() . $line->output->newLine();
}
);
```
## Outputs

> Returning null skips the line entirely.
* [`Felix\Tin\Themes\AnsiOutput`](src/Outputs/AnsiOutput.php)
* [`Felix\Tin\Themes\CallableOutput`](src/Outputs/CallableOutput.php)
* [`Felix\Tin\Themes\HtmlOutput`](src/Outputs/HtmlOutput.php)

## Themes

Themes define the colors used by outputs. The format is `r;g;b`, to match ANSI default format.

* [`Felix\Tin\Themes\JetbrainsDark`](src/Themes/JetbrainsDark.php)
* [`Felix\Tin\Themes\OneDark`](src/Themes/OneDark.php)

Expand All @@ -73,10 +63,10 @@ You need to extend `Felix\Tin\Themes\Theme` and set the colors to whatever you w
The color are RGB values separated by a `;`.

```php
use Felix\Tin\Contracts\Theme;
use Felix\Tin\Contracts\ThemeInterface;
use Felix\Tin\Enums\TokenType;

class OneDark extends Theme
class OneDark extends ThemeInterface
{
/** {@inheritDoc} */
public function color(TokenType $type): string
Expand All @@ -94,10 +84,6 @@ class OneDark extends Theme
}
```

## Future

* PHPDoc

## Testing

```bash
Expand Down
6 changes: 3 additions & 3 deletions src/Contracts/OutputInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
namespace Felix\Tin\Contracts;

use Felix\Tin\Enums\TokenType;
use Felix\Tin\Line;

interface OutputInterface
{
/** Transform the token value to the desired output format with respect to the token type and theme */
public function transform(TokenType $type, string $value): string;

/** Returns a new line, usually PHP_EOL or <br /> */
public function newLine(): string;
public function transformLine(Line $line): ?string;

/** Returns the theme used by the output */
public function theme(): Theme;
public function theme(): ThemeInterface;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Felix\Tin\Enums\TokenType;

abstract class Theme
abstract class ThemeInterface
{
/** @return string formatted as follow: `r;g;b` with r, g, b, base 10 integers in the range [0-256) */
abstract public function color(TokenType $type): string;
Expand Down
20 changes: 13 additions & 7 deletions src/Outputs/AnsiOutput.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
namespace Felix\Tin\Outputs;

use Felix\Tin\Contracts\OutputInterface;
use Felix\Tin\Contracts\Theme;
use Felix\Tin\Contracts\ThemeInterface;
use Felix\Tin\Enums\TokenType;
use Felix\Tin\Line;

class AnsiOutput implements OutputInterface
readonly class AnsiOutput implements OutputInterface
{
public function __construct(
protected readonly Theme $theme,
protected readonly bool $ansiEnabled = true)
protected ThemeInterface $theme,
protected bool $ansiEnabled = true)
{
}

Expand All @@ -23,13 +24,18 @@ public function transform(TokenType $type, string $value): string
return "\e[38;2;{$this->theme->color($type)}m{$value}\e[0m";
}

public function theme(): Theme
public function theme(): ThemeInterface
{
return $this->theme;
}

public function newLine(): string
public function transformLine(Line $line): string
{
return PHP_EOL;
return str_pad(
(string) $line->number,
strlen((string) $line->totalCount),
' ',
STR_PAD_LEFT
) . ' | ' . $line->toString() . PHP_EOL;
}
}
36 changes: 36 additions & 0 deletions src/Outputs/CallableOutput.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Felix\Tin\Outputs;

use Felix\Tin\Contracts\OutputInterface;
use Felix\Tin\Contracts\ThemeInterface;
use Felix\Tin\Enums\TokenType;
use Felix\Tin\Line;

class CallableOutput implements OutputInterface
{
/** @var callable */
private $transformer;

public function __construct(
protected ThemeInterface $theme,
callable $transformer
) {
$this->transformer = $transformer;
}

public function transform(TokenType $type, string $value): string
{
return $value;
}

public function transformLine(Line $line): ?string
{
return ($this->transformer)($line);
}

public function theme(): ThemeInterface
{
return $this->theme;
}
}
38 changes: 38 additions & 0 deletions src/Outputs/HtmlOutput.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace Felix\Tin\Outputs;

use Felix\Tin\Contracts\OutputInterface;
use Felix\Tin\Contracts\ThemeInterface;
use Felix\Tin\Enums\TokenType;
use Felix\Tin\Line;

readonly class HtmlOutput implements OutputInterface
{
public function __construct(
protected ThemeInterface $theme,
) {
}

public function transform(TokenType $type, string $value): string
{
return sprintf(
'<span style="color:rgb(%s);">%s</span>',
str_replace(';', ',', $this->theme->color($type)),
$value
);
}

public function theme(): ThemeInterface
{
return $this->theme;
}

public function transformLine(Line $line): string
{
return sprintf(
'<div class="line"><span class="line-number">%s</span>%s</div>',
$line->number, $line->toString()
);
}
}
15 changes: 8 additions & 7 deletions src/Outputs/TestOutput.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
namespace Felix\Tin\Outputs;

use Felix\Tin\Contracts\OutputInterface;
use Felix\Tin\Contracts\Theme;
use Felix\Tin\Contracts\ThemeInterface;
use Felix\Tin\Enums\TokenType;
use Felix\Tin\Themes\NullTheme;
use Felix\Tin\Line;
use Felix\Tin\Themes\NullThemeInterface;

class TestOutput implements OutputInterface
readonly class TestOutput implements OutputInterface
{
public function __construct()
{
Expand All @@ -18,13 +19,13 @@ public function transform(TokenType $type, string $value): string
return $value;
}

public function newLine(): string
public function theme(): ThemeInterface
{
return PHP_EOL;
return new NullThemeInterface();
}

public function theme(): Theme
public function transformLine(Line $line): string
{
return new NullTheme();
return $line->toString() . PHP_EOL;
}
}
4 changes: 2 additions & 2 deletions src/Themes/JetbrainsDark.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

namespace Felix\Tin\Themes;

use Felix\Tin\Contracts\Theme;
use Felix\Tin\Contracts\ThemeInterface;
use Felix\Tin\Enums\TokenType;

class JetbrainsDark extends Theme
class JetbrainsDark extends ThemeInterface
{
public function color(TokenType $type): string
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

namespace Felix\Tin\Themes;

use Felix\Tin\Contracts\Theme;
use Felix\Tin\Contracts\ThemeInterface;
use Felix\Tin\Enums\TokenType;

class NullTheme extends Theme
class NullThemeInterface extends ThemeInterface
{
public function color(TokenType $type): string
{
Expand Down
4 changes: 2 additions & 2 deletions src/Themes/OneDark.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

namespace Felix\Tin\Themes;

use Felix\Tin\Contracts\Theme;
use Felix\Tin\Contracts\ThemeInterface;
use Felix\Tin\Enums\TokenType;

class OneDark extends Theme
class OneDark extends ThemeInterface
{
public function color(TokenType $type): string
{
Expand Down
47 changes: 12 additions & 35 deletions src/Tin.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
namespace Felix\Tin;

use Felix\Tin\Contracts\OutputInterface;
use Felix\Tin\Contracts\Theme;
use Felix\Tin\Enums\TokenType;
use Felix\Tin\Contracts\ThemeInterface;
use Felix\Tin\Outputs\AnsiOutput;

class Tin
Expand All @@ -16,12 +15,12 @@ public function __construct(protected OutputInterface $output)
}

/**
* @param class-string<Theme|OutputInterface>|Theme|OutputInterface $theme You may pass a theme/output class name
* or an instance of either, by default the AnsiOutput is used
* @param bool $ansiEnabled Whether to enable ANSI output, by default it is enabled,
* this setting is ignored if you do not pass a theme class or instance
* @param class-string<ThemeInterface|OutputInterface>|ThemeInterface|OutputInterface $theme You may pass a theme/output class name
* or an instance of either, by default the AnsiOutput is used
* @param bool $ansiEnabled Whether to enable ANSI output, by default it is enabled,
* this setting is ignored if you do not pass a theme class or instance
*/
public static function from(string|Theme|OutputInterface $theme, bool $ansiEnabled = true): self
public static function from(string|ThemeInterface|OutputInterface $theme, bool $ansiEnabled = true): self
{
// The logic here is somewhat convoluted to avoid breaking changes, keep it this way for now
if ($theme instanceof OutputInterface) {
Expand All @@ -42,39 +41,17 @@ public static function from(string|Theme|OutputInterface $theme, bool $ansiEnabl
/** Highlights a piece of code with line numbers */
public function highlight(string $code): string
{
return $this->process($code, function (?Line $line): ?string {
if (!$line) {
return null;
}

$lineNumber = $line->output->transform(
TokenType::LineNumber,
str_pad(
(string) $line->number,
strlen((string) $line->totalCount), ' ',
STR_PAD_LEFT
) . ' | ',
);

return $lineNumber . $line->toString() . $line->output->newLine();
});
}

/**
* Converts a piece of code to lines made of tokens and passes each line to a transformer.
*
* @param callable(Line): ?string $transformer
*/
public function process(string $code, callable $transformer): string
{
$buffer = '';
$tokens = $this->groupTokensByLine(
$buffer = '';
$tokens = $this->groupTokensByLine(
Tokenizer::tokenize($code)
);
$totalLines = $tokens->count();

foreach ($tokens as $n => $lineTokens) {
if ($line = $transformer(new Line($n + 1, $lineTokens, $totalLines, $this->output))) {
$line = new Line($n + 1, $lineTokens, $totalLines, $this->output);
$line = $this->output->transformLine($line);

if ($line) {
$buffer .= $line;
}
}
Expand Down
Loading

0 comments on commit 9d0e1c8

Please sign in to comment.