alto / code-snippet
Represent immutable code snippets with source lines, selections, and presentation-neutral annotations.
Fund package maintenance!
Requires
- php: ^8.4
- alto/language: ^1.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.94
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^12.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Represent immutable code snippets with source lines, selections, and presentation-neutral annotations.
Code Snippet turns source code into a portable model with original line numbers, selected lines, and generic byte-range annotations. Renderers can consume that model without coupling this package to HTML, SVG, terminals, slides, or a syntax highlighter.
use Alto\Code\Snippet\CodeSnippet; $snippet = CodeSnippet::fromCode($code, 'php', startLine: 24) ->selectLines(3); echo $snippet->lines()[2]->number; // 26
Installation
composer require alto/code-snippet
Code Snippet requires PHP 8.4 or later and installs alto/language.
Quick start
Create a snippet, keep its original source position, and select one line:
use Alto\Code\Snippet\CodeSnippet; $snippet = CodeSnippet::fromCode( "public function run(): void\n{\n execute();\n}", 'php', sourceName: 'src/Runner.php', startLine: 24, )->selectLines(3); $line = $snippet->lines()[2]; printf("line=%d selected=%s %s\n", $line->number, $line->selected ? 'true' : 'false', $line->code);
The result is:
line=26 selected=true execute();
Every transformation returns a new value. The original snippet remains unchanged.
Lines and selections
lines() returns CodeLine values with both coordinate systems:
indexis one-based and relative to the snippet;numberrefers to the original source;codeexcludes the line break;selectedcarries line-level emphasis;annotations()contains line-relative annotations.
$line = $snippet->lines()[2]; $line->index; // 3 $line->number; // 26 $line->code; // " execute();" $line->selected; // true $line->annotations(); $line->segments();
Source content and LF, CRLF, or CR line endings remain byte-for-byte identical.
Annotations and segments
CodeAnnotation describes a byte range relative to code(), an application-defined type, and
optional generic data:
$annotated = $snippet->annotate( new CodeAnnotation(0, 6, 'syntax', ['scope' => 'keyword']), new CodeAnnotation(16, 3, 'emphasis', ['name' => 'primary']), );
Annotations may overlap or cross line breaks. Each CodeLine clips and shifts them to its own
content. segments() derives contiguous text regions with stable annotation sets.
When the caller knows the text instead of its byte offsets, highlight('sum') adds focus
annotations to every literal match. annotateText() accepts another type, optional data, and a
one-based occurrence number.
Slicing and indentation
slice() projects an already annotated snippet onto a half-open byte range:
$projected = $annotatedSource ->slice($range->start, $range->end) ->dedent();
This lets a consumer analyze a complete source before projecting the selected region. Crossing annotations are clipped and shifted, while source line numbers and selections are retained.
Use dedent() or its unindent() alias to remove common indentation. indent() adds spaces to
non-empty lines. These explicit transformations update annotation offsets and preserve the original
line-ending style.
Export
CodeSnippet, CodeLine, CodeAnnotation, and CodeSegment implement JsonSerializable.
toArray() exports code, provenance, selections, and annotations:
$payload = $snippet->toArray(); $json = json_encode($snippet, JSON_THROW_ON_ERROR);
Package boundary
Code Snippet does not read files, detect languages, locate declarations, tokenize code, or render output. It only owns the immutable, presentation-neutral data model passed between those steps.
Documentation
- Installation: install the development package and verify it.
- Getting started: create a snippet and inspect a selected line.
- Usage: work with snippets, lines, annotations, segments, and transformations.
- Documentation index: read the package overview and boundaries.
Contributing
Contributions of all kinds are welcome. Visit the project on GitHub to report a bug, suggest a feature, or open a pull request.
Before submitting code, run:
# Runs PHP CS Fixer, PHPStan, and PHPUnit
composer qa
Changes to public behavior should include tests and documentation.
Support
ALTO Code Snippet is open source and independently maintained by Simon André. If it is useful to your work, you can support its continued development through GitHub Sponsors.
Sharing the package or starring it on GitHub also helps.
License
ALTO Code Snippet is released by ALTO PHP under the MIT License.