Skip to content

Commit

Permalink
Add better matchbrace
Browse files Browse the repository at this point in the history
  • Loading branch information
zyedidia committed Dec 25, 2019
1 parent f39a916 commit d1e713c
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 23 deletions.
11 changes: 8 additions & 3 deletions internal/action/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -933,9 +933,14 @@ func (h *BufPane) paste(clip string) {
func (h *BufPane) JumpToMatchingBrace() bool {
for _, bp := range buffer.BracePairs {
r := h.Cursor.RuneUnder(h.Cursor.X)
if r == bp[0] || r == bp[1] {
matchingBrace := h.Buf.FindMatchingBrace(bp, h.Cursor.Loc)
h.Cursor.GotoLoc(matchingBrace)
rl := h.Cursor.RuneUnder(h.Cursor.X - 1)
if r == bp[0] || r == bp[1] || rl == bp[0] || rl == bp[1] {
matchingBrace, left := h.Buf.FindMatchingBrace(bp, h.Cursor.Loc)
if left {
h.Cursor.GotoLoc(matchingBrace)
} else {
h.Cursor.GotoLoc(matchingBrace.Move(1, h.Buf))
}
}
}

Expand Down
42 changes: 33 additions & 9 deletions internal/buffer/buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -651,16 +651,30 @@ var BracePairs = [][2]rune{
// It is given a brace type containing the open and closing character, (for example
// '{' and '}') as well as the location to match from
// TODO: maybe can be more efficient with utf8 package
func (b *Buffer) FindMatchingBrace(braceType [2]rune, start Loc) Loc {
// returns the location of the matching brace
// if the boolean returned is true then the original matching brace is one character left
// of the starting location
func (b *Buffer) FindMatchingBrace(braceType [2]rune, start Loc) (Loc, bool) {
curLine := []rune(string(b.LineBytes(start.Y)))
startChar := curLine[start.X]
startChar := ' '
if start.X >= 0 && start.X < len(curLine) {
startChar = curLine[start.X]
}
leftChar := ' '
if start.X-1 >= 0 && start.X-1 < len(curLine) {
leftChar = curLine[start.X-1]
}
var i int
if startChar == braceType[0] {
if startChar == braceType[0] || leftChar == 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
if startChar == braceType[0] {
xInit = start.X
} else {
xInit = start.X - 1
}
}
for x := xInit; x < len(l); x++ {
r := l[x]
Expand All @@ -669,32 +683,42 @@ func (b *Buffer) FindMatchingBrace(braceType [2]rune, start Loc) Loc {
} else if r == braceType[1] {
i--
if i == 0 {
return Loc{x, y}
if startChar == braceType[0] {
return Loc{x, y}, false
}
return Loc{x, y}, true
}
}
}
}
} else if startChar == braceType[1] {
} else if startChar == braceType[1] || leftChar == 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
if leftChar == braceType[1] {
xInit = start.X - 1
} else {
xInit = start.X
}
}
for x := xInit; x >= 0; x-- {
r := l[x]
if r == braceType[0] {
i--
if i == 0 {
return Loc{x, y}
if leftChar == braceType[1] {
return Loc{x, y}, true
}
return Loc{x, y}, false
}
} else if r == braceType[1] {
i++
}
}
}
}
return start
return start, true
}

// Retab changes all tabs to spaces or vice versa
Expand Down
2 changes: 1 addition & 1 deletion internal/config/runtime.go

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions internal/config/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,7 @@ var defaultCommonSettings = map[string]interface{}{
"ignorecase": false,
"indentchar": " ",
"keepautoindent": false,
"matchbrace": false,
"matchbraceleft": false,
"matchbrace": true,
"mkparents": false,
"readonly": false,
"rmtrailingws": false,
Expand Down
27 changes: 27 additions & 0 deletions internal/display/bufwindow.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,27 @@ func (w *BufWindow) displayBuffer() {
b.Highlighter.HighlightMatches(b, w.StartLine, w.StartLine+bufHeight)
}

var matchingBraces []buffer.Loc
// bracePairs is defined in buffer.go
if b.Settings["matchbrace"].(bool) {
for _, bp := range buffer.BracePairs {
for _, c := range b.GetCursors() {
if c.HasSelection() {
continue
}
curX := c.X
curLoc := c.Loc

r := c.RuneUnder(curX)
rl := c.RuneUnder(curX - 1)
if r == bp[0] || r == bp[1] || rl == bp[0] || rl == bp[1] {
mb, _ := b.FindMatchingBrace(bp, curLoc)
matchingBraces = append(matchingBraces, mb)
}
}
}
}

lineNumStyle := config.DefStyle
if style, ok := config.Colorscheme["line-number"]; ok {
lineNumStyle = style
Expand Down Expand Up @@ -477,6 +498,12 @@ func (w *BufWindow) displayBuffer() {
}
}

for _, mb := range matchingBraces {
if mb.X == bloc.X && mb.Y == bloc.Y {
style = style.Underline(true)
}
}

screen.Screen.SetContent(w.X+vloc.X, w.Y+vloc.Y, r, nil, style)

if showcursor {
Expand Down
11 changes: 3 additions & 8 deletions runtime/help/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,10 @@ Here are the options that you can set:

default value: `false`

* `matchbrace`: highlight matching braces for '()', '{}', '[]'
* `matchbrace`: underline matching braces for '()', '{}', '[]' when the cursor
is on a brace character.

default value: `false`

* `matchbraceleft`: when matching a closing brace, should matching match the
brace directly under the cursor, or the character to the left? only matters
if `matchbrace` is true

default value: `false`
default value: `true`

* `mkparents`: if a file is opened on a path that does not exist, the file cannot
be saved because the parent directories don't exist. This option lets micro
Expand Down

0 comments on commit d1e713c

Please sign in to comment.