Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 19 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# ALTO CodeSlicer
# ALTO Code Slicer

Extract immutable source-code slices by line, text, or language structure while preserving exact
byte ranges and line numbers.
Expand All @@ -9,7 +9,7 @@ byte ranges and line numbers.
  ![License](https://img.shields.io/github/license/altophp/code-slicer?label=License&labelColor=050608&color=00B7FF)
  [![GitHub Sponsors](https://img.shields.io/github/sponsors/smnandre?logo=githubsponsors&logoColor=00B7FF&label=%20Sponsor&labelColor=050608&color=00B7FF)](https://github.com/sponsors/smnandre)

CodeSlicer loads a complete source and progressively narrows an immutable `CodeSlice`. Every slice
Code Slicer loads a complete source and progressively narrows an immutable `CodeSlice`. Every slice
keeps its language, source name, and original line numbers.

```php
Expand All @@ -23,20 +23,22 @@ echo $slice->content();
echo $slice->startLine();
```

Selection stops before presentation. CodeSlicer returns source ranges and leaves syntax tokens,
Selection stops before presentation. Code Slicer returns source ranges and leaves syntax tokens,
annotations, highlighting, and rendering to downstream consumers.

## Installation

Install ALTO CodeSlicer with Composer:
This package is currently distributed from its development branch; no stable
release is published yet. Configure its VCS repository before installing it:

```bash
composer require alto/code-slicer
composer config repositories.alto-code-slicer vcs https://github.com/altophp/code-slicer
composer require alto/code-slicer:dev-main
```

CodeSlicer requires PHP 8.4 or later, the tokenizer extension, and `alto/language`.
Code Slicer requires PHP 8.4 or later, the tokenizer extension, and `alto/language`.

## Quick Start
## Quick start

Select a PHP method from an in-memory source:

Expand Down Expand Up @@ -156,10 +158,16 @@ and annotations onto the selected range. `content()` remains the exact, unmodifi
`CodeSlice` is the raw result of source extraction. Its complete source and byte range let a
consumer analyze the full context before projecting the selected region into its own model.

CodeSlicer deliberately provides no HTML, SVG, Markdown, syntax tokens, themes, remote loaders, or
Code Slicer deliberately provides no HTML, SVG, Markdown, syntax tokens, themes, remote loaders, or
source rewriting.

See the [documentation](docs/index.md) for installation, a guided example, and the public API.
## Documentation

- [Documentation home](docs/index.md)
- [Installation](docs/installation.md)
- [Getting started](docs/getting-started.md)
- [Selectors](docs/selectors.md)
- [Languages](docs/languages/index.md)

## Contributing

Expand All @@ -178,13 +186,13 @@ Changes to public behavior should include tests and documentation.

## Support

ALTO CodeSlicer is open source. You can support its continued development through
ALTO Code Slicer is open source. You can support its continued development through
[GitHub Sponsors](https://github.com/sponsors/smnandre).

Sharing this package with others or
[starring it on GitHub](https://github.com/altophp/code-slicer) is also much appreciated.

## License

ALTO CodeSlicer is released by [ALTO PHP](https://altophp.com) under the
ALTO Code Slicer is released by [ALTO PHP](https://altophp.com) under the
[MIT License](LICENSE).
87 changes: 44 additions & 43 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
@@ -1,64 +1,65 @@
# Getting started

Start from the complete source so every slice can retain its original context and line numbers.
Extract one method from a complete PHP source and print its original line
number. This gives you an excerpt that remains tied to its source when you
publish or highlight it.

## Select a PHP method
## Extract a PHP method

### Prepare the script

After [installation](installation.md), create `extract.php` beside the
`vendor` directory. This example includes its input, so no separate source
file is needed:

```php
<?php

require __DIR__.'/vendor/autoload.php';

use Alto\Code\Slicer\CodeSource;

$slice = CodeSource::fromFile('src/Checkout.php')
$code = <<<'PHP'
<?php
final class Checkout
{
public function complete(): string
{
return 'Order complete';
}
}
PHP;

$slice = CodeSource::fromString($code, 'php')
->slice()
->class('Checkout')
->method('complete');

echo $slice->content();
echo $slice->startLine();
```

The class selector narrows the search scope. The method selector then returns the declaration,
including attached documentation and attributes.

For an in-memory PHP fragment, pass the language explicitly. Structural selectors accept PHP with
or without an opening tag:

```php
$slice = CodeSource::fromString(
'final class Checkout {}',
'php',
)->slice()->class('Checkout');
printf("Starts at line %d\n", $slice->startLine());
echo $slice->content(), "\n";
```

## Select exact lines
### Run and check the result

Line numbers are one-based, inclusive, and refer to the complete source:
Run the script from the project directory:

```php
$slice = $source->lines(12, 18);
```sh
php extract.php
```

Line endings remain byte-for-byte identical to the source.

## Select between markers

Text selectors search only within the current slice:
The output is:

```php
$slice = $source->slice()
->after("// example:start\n")
->before("\n// example:end");
```text
Starts at line 4
public function complete(): string
{
return 'Order complete';
}
```

Each selector returns a new immutable `CodeSlice`.

## Use the complete context downstream

```php
$completeSource = $slice->source()->content();
$range = $slice->range();

$range->start; // inclusive byte offset
$range->end; // exclusive byte offset
```
The class selector narrows the search to `Checkout`; the method selector
returns `complete` with its closing brace. Indentation and line numbers still
refer to the complete input. Each selection returns a new immutable slice.

A parser or highlighter can analyze the complete source, then project its result onto that range.
Continue with [PHP selectors](languages/php.md) to select methods from files and include
their attached documentation.
40 changes: 23 additions & 17 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
# Alto CodeSlicer documentation
# Alto Code Slicer

Alto CodeSlicer extracts immutable ranges from complete source code while preserving the original
bytes, language, source name, and line numbers.
Alto Code Slicer extracts immutable ranges from source code while preserving
the original bytes, language, source name, and line numbers. It selects by
lines, literal boundaries, or supported language structures and leaves
rendering to the consuming application.

## Documentation
```php
use Alto\Code\Slicer\CodeSource;

$slice = CodeSource::fromString("first\nsecond")->lines(2, 2);
echo $slice->content();
```

- [Installation](installation.md) covers requirements and Composer.
- [Getting started](getting-started.md) builds a slice with line, text, and structural selectors.
- [Public API](public-api.md) defines the supported entry points and selection rules.
The result is `second`, still associated with original source line 2.

## Mental model
## Documentation

`CodeSource` owns the complete input. `CodeSlice` is a half-open byte range over that source.
Selectors return narrower slices without modifying either object.
- [Installation](installation.md): install the package and verify a first selection.
- [Getting started](getting-started.md): extract a complete PHP method with its original line number.
- [Selectors](selectors.md): create sources, chain selections, inspect ranges, and handle failures.
- [Languages](languages/index.md): choose text or structural selectors for each supported source.

```text
CodeSource
-> slice()
-> lines(), after(), before(), or a structural selector
-> CodeSlice
-> content(), source(), range(), and original line numbers
```
## Boundaries

A `CodeSource` owns the complete input. A `CodeSlice` identifies a half-open
byte range within that source, and every selector returns a new narrower slice.
Code Slicer does not highlight, render, rewrite, compile, or execute the
selected source.
42 changes: 26 additions & 16 deletions docs/installation.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,42 @@
# Installation

## Requirements
This package is currently distributed from its development branch; no stable
release is published yet. Use an explicit VCS repository for evaluation.

Alto CodeSlicer requires PHP 8.4 or later, the tokenizer extension, Composer, and
`alto/language`.
Code Slicer requires PHP 8.4 or later and the Tokenizer extension. Composer
installs its `alto/language` dependency automatically.

## Install with Composer
## Install

```bash
composer require alto/code-slicer
Run these commands in your project directory:

```sh
composer config repositories.alto-code-slicer vcs https://github.com/altophp/code-slicer
composer require alto/code-slicer:dev-main
```

Framework applications normally load Composer's autoloader. A standalone script can load it
directly:
## Verify the installation

Create `check.php` beside the `vendor` directory:

```php
require __DIR__.'/vendor/autoload.php';
```
<?php

## Confirm the installation
require __DIR__.'/vendor/autoload.php';

```php
use Alto\Code\Slicer\CodeSource;

$slice = CodeSource::fromString("first\nsecond")
->lines(2, 2);
$slice = CodeSource::fromString("first\nsecond")->lines(2, 2);
echo $slice->content(), "\n";
```

Run `php check.php`. The result should be:

echo $slice->content();
```text
second
```

The script prints `second`.
Framework applications usually load Composer's autoloader already. Standalone
scripts need the `require` statement shown above.

Continue with [Getting started](getting-started.md) to extract a PHP method.
103 changes: 103 additions & 0 deletions docs/languages/css.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# CSS selectors

Select a complete rule with `rule()`, or an at-rule with `atRule()`. Closing braces are
matched automatically, including nested rule bodies. Use these selectors on a
CSS source when line numbers may change but the rule you want has a stable
selector or at-rule name.

The examples below assume [Code Slicer is installed](../installation.md) and
Composer's autoloader is loaded. Save the input as `checkout.css` in the working
directory before running the PHP selections. The `.css` extension identifies
the language automatically.

## Select a rule

**Source: `checkout.css`**

```css
.checkout {
display: grid;
gap: 1rem;
}

@media (width >= 48rem) {
.checkout {
grid-template-columns: 2fr 1fr;
}
}
```

**Selection**

```php
use Alto\Code\Slicer\CodeSource;

$slice = CodeSource::fromFile('checkout.css')->slice()->rule('.checkout');
echo $slice->content();
```

**Result**

```css
.checkout {
display: grid;
gap: 1rem;
}
```

The first matching rule in the current slice is selected. Attached CSS comments are included
when present. Selector lists must be supplied in full: `.button, .button--ghost` selects that
list; `.button` alone does not. Whitespace in the selector is normalized for matching.

## Select a rule inside a media query

**Selection**

```php
use Alto\Code\Slicer\CodeSource;

$slice = CodeSource::fromFile('checkout.css')->slice()
->atRule('media', '(width >= 48rem)')
->rule('.checkout');
echo $slice->content();
```

**Result**

```css
.checkout {
grid-template-columns: 2fr 1fr;
}
```

Narrowing to the media query selects the second `.checkout` rule without relying on line numbers.

## Select the whole media query

**Selection**

```php
use Alto\Code\Slicer\CodeSource;

$slice = CodeSource::fromFile('checkout.css')->slice()->atRule('media');
echo $slice->content();
```

**Result**

```css
@media (width >= 48rem) {
.checkout {
grid-template-columns: 2fr 1fr;
}
}
```

The at-rule name omits `@`. Its second argument is optional: `atRule('media')` finds the first
media query; supplying `(width >= 48rem)` also matches its condition. `atRule('keyframes', 'pulse')`
selects named keyframes. At-rules without bodies, such as `@import`, end at their semicolon.

A missing rule or at-rule raises `SourceSymbolNotFound`. Check the full selector
list and any containing media query; narrowing the slice may exclude a match.

See [selection rules](../selectors.md) or choose another [language](index.md).
Loading
Loading