114 lines
1.9 KiB
Go
114 lines
1.9 KiB
Go
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
|
|
}
|