package motion import "git.gophernest.net/azpect/TextEditor/internal/core" // Delimiter matching helpers operate on byte-indexed columns, which matches the // rest of the editor cursor model. func isDelimiter(ch byte) bool { switch ch { case '{', '}', '[', ']', '(', ')': return true default: return false } } func isOpeningDelimiter(ch byte) bool { return ch == '{' || ch == '[' || ch == '(' } func getOppositeDelimiter(ch byte) (byte, bool) { switch ch { case '{': return '}', true case '}': return '{', true case '[': return ']', true case ']': return '[', true case '(': return ')', true case ')': return '(', true default: return 0, false } } func findDelimiterOnLine(line string, startCol int) (int, byte, bool) { if len(line) == 0 { return 0, 0, false } col := max(0, startCol) for col < len(line) { ch := line[col] if isDelimiter(ch) { return col, ch, true } col++ } return 0, 0, false } func findMatchingForward(buf *core.Buffer, line, col int, startDelim, matchDelim byte) (core.Position, bool) { depth := 0 for y := line; y < buf.LineCount(); y++ { text := buf.Line(y) xStart := 0 if y == line { xStart = col + 1 } for x := xStart; x < len(text); x++ { ch := text[x] if ch == startDelim { depth++ continue } if ch == matchDelim { if depth == 0 { return core.Position{Line: y, Col: x}, true } depth-- } } } return core.Position{}, false } func findMatchingBackward(buf *core.Buffer, line, col int, startDelim, matchDelim byte) (core.Position, bool) { depth := 0 for y := line; y >= 0; y-- { text := buf.Line(y) xStart := len(text) - 1 if y == line { xStart = col - 1 } for x := xStart; x >= 0; x-- { ch := text[x] if ch == startDelim { depth++ continue } if ch == matchDelim { if depth == 0 { return core.Position{Line: y, Col: x}, true } depth-- } } } return core.Position{}, false }