Adding Jumping to opening and closing brace logic and actions, ...

Simplifying findMatchingBrace(),
Adding FindOpeningBrace() and FindClosingBrace(),
Adding JumpToOpeningBrace() and JumpToClosingBrace()
Adding brace jumping to default bindings
This commit is contained in:
Neko Box Coder 2024-07-13 15:39:36 +01:00
parent a10624cc33
commit bdc57b472d
No known key found for this signature in database
GPG Key ID: E33FCF170345E0F5
7 changed files with 160 additions and 37 deletions

View File

@ -1407,6 +1407,28 @@ func (h *BufPane) JumpToMatchingBrace() bool {
return false
}
// JumpToOpeningBrace moves the cursor to the opening brace in current brace scope
func (h *BufPane) JumpToOpeningBrace() bool {
matchingBrace, found := h.Buf.FindOpeningBrace(h.Cursor.Loc)
if found {
h.Cursor.GotoLoc(matchingBrace)
h.Relocate()
return true
}
return false
}
// JumpToClosingBrace moves the cursor to the closing brace in current brace scope
func (h *BufPane) JumpToClosingBrace() bool {
matchingBrace, found := h.Buf.FindClosingBrace(h.Cursor.Loc)
if found {
h.Cursor.GotoLoc(matchingBrace)
h.Relocate()
return true
}
return false
}
// SelectAll selects the entire buffer
func (h *BufPane) SelectAll() bool {
h.Cursor.SetSelectionStart(h.Buf.Start())

View File

@ -840,6 +840,8 @@ var BufKeyActions = map[string]BufKeyAction{
"RemoveAllMultiCursors": (*BufPane).RemoveAllMultiCursors,
"SkipMultiCursor": (*BufPane).SkipMultiCursor,
"JumpToMatchingBrace": (*BufPane).JumpToMatchingBrace,
"JumpToOpeningBrace": (*BufPane).JumpToOpeningBrace,
"JumpToClosingBrace": (*BufPane).JumpToClosingBrace,
"JumpLine": (*BufPane).JumpLine,
"Deselect": (*BufPane).Deselect,
"ClearInfo": (*BufPane).ClearInfo,
@ -922,4 +924,6 @@ var MultiActions = map[string]bool{
"StartOfTextToggle": true,
"EndOfLine": true,
"JumpToMatchingBrace": true,
"JumpToOpeningBrace": true,
"JumpToClosingBrace": true,
}

View File

@ -74,6 +74,8 @@ var bufdefaults = map[string]string{
"Ctrl-u": "ToggleMacro",
"Ctrl-j": "PlayMacro",
"Insert": "ToggleOverwriteMode",
"Alt-<": "JumpToOpeningBrace",
"Alt->": "JumpToClosingBrace",
// Emacs-style keybindings
"Alt-f": "WordRight",

View File

@ -77,6 +77,8 @@ var bufdefaults = map[string]string{
"Ctrl-u": "ToggleMacro",
"Ctrl-j": "PlayMacro",
"Insert": "ToggleOverwriteMode",
"Alt-<": "JumpToOpeningBrace",
"Alt->": "JumpToClosingBrace",
// Emacs-style keybindings
"Alt-f": "WordRight",

View File

@ -1140,46 +1140,133 @@ var BracePairs = [][2]rune{
{'[', ']'},
}
func (b *Buffer) findOpeningBrace(braceType [2]rune, start Loc) (Loc, bool) {
// Bound guard
start = clamp(start, b.LineArray)
if len(b.lines) == 0 {
return start, false
}
i := 1
// If we are on a closing brace, let the counter be incremented below when we traverse
curLine := []rune(string(b.LineBytes(start.Y)))
if start.X >= 0 && start.X < len(curLine) {
startChar := curLine[start.X]
if startChar == braceType[1] {
i = 0
}
}
for y := start.Y; y >= 0; y-- {
l := []rune(string(b.lines[y].data))
xInit := len(l) - 1
if y == start.Y && start.X < len(curLine) {
xInit = start.X
}
for x := xInit; x >= 0; x-- {
r := l[x]
if r == braceType[1] {
i++
} else if r == braceType[0] {
i--
if i == 0 {
return Loc{x, y}, true
}
}
}
}
return start, false
}
// Returns the opening brace in current brace scope starting at the start location and a boolean
// indicating if an opening brace is found
func (b *Buffer) FindOpeningBrace(start Loc) (Loc, bool) {
currentDist := -1
currentMb := Loc{-1, -1}
for _, bp := range BracePairs {
mb, found := b.findOpeningBrace(bp, start)
if found {
dist := DiffLA(start, mb, b.LineArray)
if currentDist < 0 || dist < currentDist {
currentMb = mb
currentDist = dist
}
}
}
if currentDist == -1 {
return start, false
} else {
return currentMb, true
}
}
func (b *Buffer) findClosingBrace(braceType [2]rune, start Loc) (Loc, bool) {
// Bound guard
start = clamp(start, b.LineArray)
if len(b.lines) == 0 {
return start, false
}
i := 1
// If we are on an opening brace, let the counter be incremented below when we traverse
curLine := []rune(string(b.LineBytes(start.Y)))
if start.X >= 0 && start.X < len(curLine) {
startChar := curLine[start.X]
if startChar == braceType[0] {
i = 0
}
}
for y := start.Y; y < b.LinesNum(); y++ {
l := []rune(string(b.LineBytes(y)))
xInit := 0
if y == start.Y && start.X >= 0 {
xInit = start.X
}
for x := xInit; x < len(l); x++ {
r := l[x]
if r == braceType[0] {
i++
} else if r == braceType[1] {
i--
if i == 0 {
return Loc{x, y}, true
}
}
}
}
return start, false
}
// Returns the closing brace in current brace scope starting at the start location and a boolean
// indicating if an closing brace is found
func (b *Buffer) FindClosingBrace(start Loc) (Loc, bool) {
currentDist := -1
currentMb := Loc{-1, -1}
for _, bp := range BracePairs {
mb, found := b.findClosingBrace(bp, start)
if found {
dist := DiffLA(start, mb, b.LineArray)
if currentDist < 0 || dist < currentDist {
currentMb = mb
currentDist = dist
}
}
}
if currentDist == -1 {
return start, false
} else {
return currentMb, true
}
}
func (b *Buffer) findMatchingBrace(braceType [2]rune, start Loc, char rune) (Loc, bool) {
var i int
if char == braceType[0] {
for y := start.Y; y < b.LinesNum(); y++ {
l := []rune(string(b.LineBytes(y)))
xInit := 0
if y == start.Y {
xInit = start.X
}
for x := xInit; x < len(l); x++ {
r := l[x]
if r == braceType[0] {
i++
} else if r == braceType[1] {
i--
if i == 0 {
return Loc{x, y}, true
}
}
}
}
return b.findClosingBrace(braceType, start)
} else if char == braceType[1] {
for y := start.Y; y >= 0; y-- {
l := []rune(string(b.lines[y].data))
xInit := len(l) - 1
if y == start.Y {
xInit = start.X
}
for x := xInit; x >= 0; x-- {
r := l[x]
if r == braceType[1] {
i++
} else if r == braceType[0] {
i--
if i == 0 {
return Loc{x, y}, true
}
}
}
}
return b.findOpeningBrace(braceType, start)
}
return start, false
}

View File

@ -33,6 +33,8 @@ can change it!
| PageDown | Move cursor down one page |
| Ctrl-Home or Ctrl-UpArrow | Move cursor to start of document |
| Ctrl-End or Ctrl-DownArrow | Move cursor to end of document |
| Alt-< | Move cursor to opening brace in current brace scope |
| Alt-> | Move cursor to closing brace in current brace scope |
| Ctrl-l | Jump to a line in the file (prompts with #) |
| Ctrl-w | Cycle between splits in the current tab (use `> vsplit` or `> hsplit` to create a split) |

View File

@ -268,6 +268,8 @@ RemoveAllMultiCursors
SkipMultiCursor
None
JumpToMatchingBrace
JumpToOpeningBrace
JumpToClosingBrace
Autocomplete
```
@ -520,6 +522,8 @@ conventions for text editing defaults.
"Ctrl-u": "ToggleMacro",
"Ctrl-j": "PlayMacro",
"Insert": "ToggleOverwriteMode",
"Alt-<": "JumpToOpeningBrace",
"Alt->": "JumpToClosingBrace",
// Emacs-style keybindings
"Alt-f": "WordRight",