# LPeg Minimal Guide: Finding Partial Strings

LPeg is NOT regex. Use these patterns instead:

- <https://www.inf.puc-rio.br/~roberto/lpeg/>

## Basic String Finding

```lua
local peg = require "peg"

-- Simple string finding
peg.found(text, "error")        -- finds "error" anywhere
peg.found(text, "warning")      -- finds "warning" anywhere

-- Pattern matching with peg module (for complex patterns)
local errorPattern = peg.pattern("error") + peg.pattern("warning") -- error OR warning
-- error FOLLOWED BY warning (concatenation)
local errorThenWarning = peg.pattern("error") * peg.pattern("warning")
peg.match(text, errorPattern)
```

## Pattern Matching Numbers

```lua
-- Ranges: peg.range("09") = [0-9], peg.range("az") = [a-z], peg.range("AZ") = [A-Z]
local digit = peg.range("09")  -- single digit 0-9
local letter = peg.range("az") + peg.range("AZ")  -- Any letter
-- Match "1 error", "2 errors", "10 warnings", etc.
local nonZeroDigit = peg.range("19")  -- [1-9]
local singularError = peg.pattern("1") * peg.pattern(" error")      -- "1 error"
local pluralErrors = nonZeroDigit * digit * peg.pattern(" errors") -- "2-99 errors"
```

## Common Patterns

```lua
-- Match "not found"
peg.found(text, "not found")
-- Match "command not found"
peg.found(text, "command not found")
-- Match file not found patterns
peg.found(text, "No such file or directory")
-- Match I/O error
peg.found(text, "I/O error")
-- Match luacheck specific patterns
peg.found(text, "unfinished string")
peg.found(text, "syntax error")
```

## Combining Patterns

```lua
-- Multiple alternatives with OR (use peg for complex patterns)
local errorPatterns = peg.pattern("error") + peg.pattern("warning") + peg.pattern("I/O error")
peg.match(text, errorPatterns)

-- NOT found pattern (negation) - use peg.other()
local goodPattern = peg.pattern("0 errors") + peg.pattern("0 warnings")
local hasErrors = peg.other(goodPattern) * peg.pattern("error")  -- error that's not "0 errors"

-- Search pattern anywhere in string (not just from start)
-- This is a more advanced pattern using recursion - see peg source for details
local function anywherePattern(patt)
  -- Implementation requires peg grammar table syntax
  return patt -- Simplified for documentation - use peg.found() instead
end
```

## Key Differences from Regex

- No `[a-z]` character classes - use `peg.range("az")`
- No `+` quantifier - use `peg.least(pattern, 1)` for one or more
- No `*` quantifier - use `peg.least(pattern, 0)` for zero or more
- No `|` OR - use `peg.pattern(p1) + peg.pattern(p2)` for OR
- No `^` start - use `peg.pattern("^")` for literal ^
- No `$` end - use `-1` for end of string

## Important Notes

- `peg.toPattern(pattern)` takes **only one parameter**, not multiple
- Use `peg.found(text, "string-to-find")` for simple string finding
- Use `peg.pattern()`, `peg.range()`, `peg.match()` for complex patterns
- `*` = concatenation (A followed by B) - works with peg patterns
- `+` = OR (A or B) - works with peg patterns
- `peg.least(pattern, 0)` = zero or more repetitions
- `peg.least(pattern, 1)` = one or more repetitions
- `peg.most(pattern, n)` = at most n repetitions

## For fix.lua

Instead of regex `[1-9]%d* errors?` use:

```lua
-- Create proper range patterns using peg
local nonZeroDigit = peg.range("19")  -- digits 1-9 (non-zero)
local digit = peg.range("09")         -- digits 0-9
local singularError = peg.pattern("1") * peg.pattern(" error")      -- "1 error"
local pluralErrors = nonZeroDigit * digit * peg.pattern(" errors") -- "2 errors" to "99 errors"
local luacheckErrorPattern = singularError + pluralErrors + peg.pattern("1 warning") + peg.pattern("I/O error")

-- Usage with peg.found
if peg.found(output, luacheckErrorPattern) then
  -- Found errors like "2 errors", "10 errors", "1 error", etc.
end
```

## Essential PEG Functions

### Pattern Creation

```lua
peg.pattern("string")     -- Literal string pattern
peg.set("abc")           -- Character set: any of a, b, or c
peg.range("az")          -- Character range: a-z
peg.range("09")          -- Character range: 0-9
peg.toPattern("string")  -- Convert string to pattern (single parameter)
```

### Pattern Operations

```lua
peg.least(pattern, 0)    -- Zero or more repetitions (like regex *)
peg.least(pattern, 1)    -- One or more repetitions (like regex +)
peg.most(pattern, n)     -- At most n repetitions
peg.pattern1 + peg.pattern2  -- OR (pattern1 OR pattern2)
peg.pattern1 * peg.pattern2  -- Concatenation (pattern1 FOLLOWED BY pattern2)
```

### String Finding & Matching

```lua
peg.found(text, pattern)      -- Find pattern anywhere in text (returns boolean)
peg.match(text, pattern)      -- Match pattern from start (returns position)
peg.find(text, pattern)       -- Find pattern position (returns number)
peg.startsWith(text, pattern) -- Check if text starts with pattern
peg.endsWith(text, pattern)   -- Check if text ends with pattern
```

### String Manipulation

```lua
peg.replace(text, old, new)        -- Replace all occurrences
peg.replaceOnce(text, old, new)     -- Replace first occurrence
peg.parseBefore(text, divider)      -- Get text before divider
peg.parseAfter(text, divider)       -- Get text after divider
peg.parseLast(text, divider)        -- Get last part after divider
peg.splitToArray(text, separator)   -- Split text to array
peg.trimFunction(separator)         -- Returns trim function, faster to create pattern once
peg.trim(text)                      -- Trim whitespace from both ends of string
```

### Examples

```lua
-- Find digits in text
local digitPattern = peg.range("09")
if peg.found("file123", digitPattern) then print("Found digits") end

-- Replace words
peg.replace("hello world", "world", "universe") -- "hello universe"

-- Parse file extension
peg.parseAfter("script.lua", ".") -- "lua"

-- Split CSV
local arr = peg.splitToArray("a,b,c", ",") -- {"a", "b", "c"}

-- Trim whitespace
local trimmed = peg.trim("  hello world  ") -- "hello world"
```
