
# Tekstihaku

Greph:n tekstihaku on rivipohjainen tavuhaku läpikäydystä tiedostopuusta. Se on oletustila kohteille `greph` CLI ja `Greph::searchText()`-julkisivulle. Tuloste noudattaa kanonista `file:line:content`-muotoa, jota grep, ripgrep ja useimmat editori-integraatiot jäsentävät.

## Esimerkkejä

```bash
# Regex search across the current directory
./vendor/bin/greph "function\s+\w+"

# Fixed-string search across src/
./vendor/bin/greph -F "function" src

# Case-insensitive whole-word search
./vendor/bin/greph -F -i -w "function" src

# Two lines of context around each match
./vendor/bin/greph -F -C 2 "TODO" src

# Stop after the first three matches per file
./vendor/bin/greph -F -m 3 "TODO" src

# Files that contain the pattern
./vendor/bin/greph -F -l "TODO" src

# Files that do not contain the pattern
./vendor/bin/greph -F -L "TODO" src

# Count matches per file
./vendor/bin/greph -F -c "TODO" src

# Inverted match
./vendor/bin/greph -F -v "TODO" src/notes.txt
```

## Kuviot

Oletusarvoisesti kuviota käsitellään PCRE2-säännöllisenä lausekkeena. PHP:n `preg_*`-funktiot toteuttavat hakukoneen, joten syntaksi vastaa [PHP PCRE-viitettä](https://www.php.net/manual/en/pcre.pattern.php).

Poista regex-moottori käytöstä valitsimella `-F`, jolloin kuviota käsitellään kirjaimellisena tavujonona. Kiinteän merkkijonon tila on nopea polku: se käyttää täsmäykseen `strpos()`-toimintoa ja ohittaa PCRE2:n käännösvaiheen kokonaan.

`-i` tekee kummastakin tilasta kirjainkoosta riippumattoman. `-w` lisää täsmäyksen molemmille puolille kokonaisen sanan rajat.

## Tiedostojen suodatus

Greph käy tiedostopuun läpi ennen hakua. Sama läpikäynti toimii AST-tilassa ja indeksoidussa tilassa, joten samat suodatusvalitsimet pätevät kaikkialla.

| Valitsin | Vaikutus |
|---|---|
| `--type NAME` | Sisällytä vain tiedostot, jotka vastaavat nimettyä tyyppialiasta (`php`, `js`, `md`, ...) |
| `--type-not NAME` | Jätä pois tiedostot, jotka vastaavat nimettyä tyyppialiasta |
| `--glob GLOB` | Sisällytä vain tiedostot, joiden polut vastaavat GLOB-kuviota. Toistettavissa. |
| `--no-ignore` | Älä noudata kohteita `.gitignore` tai `.grephignore` |
| `--hidden` | Sisällytä piilotetut tiedostot |

Läpikäynti noudattaa oletusarvoisesti kohteita `.gitignore` ja `.grephignore`, ohittaa binääritiedostot (tunnistaa ne ensimmäisten 512 tavun nollatavuista) ja rajoittaa tiedostokoon 10 MiB:iin. Molemmat rajat voi määrittää asetuksella `WalkOptions`.

Katso [API / FileTypeFilter](https://greph.inline0.dev/fi/docs/api#grephwalkerfiletypefilter), josta löydät kaikki sisäänrakennetut tyyppialiakset.

## Konteksti, määrät ja vain tiedostoihin kohdistuvat tilat

```bash
# Two lines before and after each match
./vendor/bin/greph -F -C 2 "needle" src

# Two lines after, no lines before
./vendor/bin/greph -F -A 2 "needle" src

# Two lines before, no lines after
./vendor/bin/greph -F -B 2 "needle" src

# Count matches per file
./vendor/bin/greph -F -c "needle" src

# List matching files only
./vendor/bin/greph -F -l "needle" src

# List non-matching files only
./vendor/bin/greph -F -L "needle" src
```

`-c`, `-l` ja `-L` ohittavat muotoilijan, joten kaikkia rivejä ei tarvitse muodostaa muistiin. Ne sopivat parhaiten kyselyihin "kuinka monta" ja "missä".

## Rinnakkaiset haut

Välitä `-j N`, niin haku jaetaan N työntekijälle. Greph käyttää työntekijäpoolissa `pcntl_fork()`-toimintoa ja siirtyy yhden prosessin suoritukseen, jos `ext-pcntl` ei ole käytettävissä.

```bash
./vendor/bin/greph -F -j 8 "function" src
```

Julkisivu laskee tiedostomäärän, tilan ja kuvion muodon perusteella, kannattaako rinnakkaissuoritus. Kynnysarvon alapuolella käytetään yhtä prosessia. Katso heuristiikat kohdasta [Lisäasetukset / Rinnakkaiset työntekijät](https://greph.inline0.dev/fi/docs/advanced/parallel).

## JSON-tulostus

`--json` tuottaa rakenteisen tietosisällön, jota jatkokäsittelytyökalut voivat jäsentää ilman grep-muodon näytön kaavintaa:

```bash
./vendor/bin/greph --json -F "function" src
```

```json
[
  {
    "file": "src/Greph.php",
    "matches": [
      {
        "line": 31,
        "column": 1,
        "content": "final class Greph",
        "matched_text": "function",
        "captures": []
      }
    ]
  }
]
```

Kääre `rg` tuottaa sen sijaan ripgrep-tapahtuman muotoista JSON-tulostetta. Käytä sitä, kun olemassa oleva kuluttaja odottaa ripgrep-skeemaa.

## Käyttö ohjelmallisesti

```php
use Greph\Greph;
use Greph\Text\TextSearchOptions;

$results = Greph::searchText(
    'function',
    'src',
    new TextSearchOptions(
        fixedString: true,
        caseInsensitive: true,
        beforeContext: 1,
        afterContext: 1,
        jobs: 4,
    ),
);

foreach ($results as $file) {
    foreach ($file->matches as $match) {
        echo "{$file->file}:{$match->line}:{$match->content}\n";
    }
}
```

Tulosten objektit on dokumentoitu kohdassa [API / Tulosten objektit](https://greph.inline0.dev/fi/docs/api#result-objects).

## Näin se toimii

Tekstihakukoneessa on kaksi polkua:

- **Kirjaimellinen polku**: kun `-F` on asetettu, haku suoritetaan `strpos()`-toiminnolla 64 KiB:n puskuroitua lukijaa käyttäen ja rivinumerointia varten rivinvaihtoja seuraten. Säännöllistä lauseketta ei käännetä.
- **Regex-polku**: kun `-F` ei ole asetettu, Greph poimii kuviosta kirjaimelliset osajonot pienellä PCRE-tyylisellä analysoijalla (`Greph\Text\LiteralExtractor`) ja käyttää niitä `strpos()`-esikäsittelysuodattimena. Suodattimen läpäisevät rivit täsmäytetään sitten käännettyä PCRE2-kuviota vasten JIT-käännös käytössä.

Molemmat polut käyttävät samaa `BufferedReader`-toimintoa I/O:hon. Lukija lukee 64 KiB:n osissa `fgets()`-rivi kerrallaan -tavan sijaan, mikä vähentää järjestelmäkutsujen määrää merkittävästi suurissa tiedostoissa.

Toistuvissa työkuormissa [indeksoitu tekstihaku](https://greph.inline0.dev/fi/docs/indexed/text) korvaa puskuroidun lukijan valmiiksi lämmitetyllä trigrammi- ja tunnisteosumien tietovarastolla ja ohittaa useimmat tiedostot kokonaan.
