if hasMessage {
vloc.X += 2
}
+ if b.Settings["diffgutter"].(bool) {
+ vloc.X++
+ }
if b.Settings["ruler"].(bool) {
vloc.X += maxLineNumLength + 1
}
if vloc.Y >= bufHeight {
break
}
- vloc.X = 0
- // This will draw an empty line number because the current line is wrapped
- if b.Settings["ruler"].(bool) {
- vloc.X += maxLineNumLength + 1
- }
+ vloc.X = w.gutterOffset
}
}
}
vloc.X++
}
+func (w *BufWindow) drawDiffGutter(backgroundStyle tcell.Style, softwrapped bool, vloc *buffer.Loc, bloc *buffer.Loc) {
+ symbol := ' '
+ styleName := ""
+
+ switch w.Buf.DiffStatus(bloc.Y) {
+ case buffer.DSAdded:
+ symbol = '\u258C' // Left half block
+ styleName = "diff-added"
+ case buffer.DSModified:
+ symbol = '\u258C' // Left half block
+ styleName = "diff-modified"
+ case buffer.DSDeletedAbove:
+ if !softwrapped {
+ symbol = '\u2594' // Upper one eighth block
+ styleName = "diff-deleted"
+ }
+ }
+
+ style := backgroundStyle
+ if s, ok := config.Colorscheme[styleName]; ok {
+ foreground, _, _ := s.Decompose()
+ style = style.Foreground(foreground)
+ }
+
+ screen.SetContent(w.X+vloc.X, w.Y+vloc.Y, symbol, nil, style)
+ vloc.X++
+}
+
func (w *BufWindow) drawLineNum(lineNumStyle tcell.Style, softwrapped bool, maxLineNumLength int, vloc *buffer.Loc, bloc *buffer.Loc) {
lineNum := strconv.Itoa(bloc.Y + 1)
bufWidth--
}
- if b.Settings["syntax"].(bool) && b.SyntaxDef != nil {
- for _, r := range b.Modifications {
- final := -1
- for i := r.X; i <= r.Y; i++ {
- final = util.Max(b.Highlighter.ReHighlightStates(b, i), final)
+ if len(b.Modifications) > 0 {
+ if b.Settings["syntax"].(bool) && b.SyntaxDef != nil {
+ for _, r := range b.Modifications {
+ rx := util.Clamp(r.X, 0, b.LinesNum())
+ ry := util.Clamp(r.Y, 0, b.LinesNum())
+ final := -1
+ for i := rx; i <= ry; i++ {
+ final = util.Max(b.Highlighter.ReHighlightStates(b, i), final)
+ }
+ b.Highlighter.HighlightMatches(b, rx, final+1)
}
- b.Highlighter.HighlightMatches(b, r.X, final+1)
}
+
b.ClearModifications()
+
+ if b.Settings["diffgutter"].(bool) {
+ b.UpdateDiff(func(synchronous bool) {
+ // If the diff was updated asynchronously, the outer call to
+ // displayBuffer might already be completed and we need to
+ // schedule a redraw in order to display the new diff.
+ // Note that this cannot lead to an infinite recursion
+ // because the modifications were cleared above so there won't
+ // be another call to UpdateDiff when displayBuffer is called
+ // during the redraw.
+ if !synchronous {
+ screen.Redraw()
+ }
+ })
+ }
}
var matchingBraces []buffer.Loc
r := c.RuneUnder(curX)
rl := c.RuneUnder(curX - 1)
if r == bp[0] || r == bp[1] || rl == bp[0] || rl == bp[1] {
- mb, left := b.FindMatchingBrace(bp, curLoc)
- matchingBraces = append(matchingBraces, mb)
- if !left {
- matchingBraces = append(matchingBraces, curLoc)
- } else {
- matchingBraces = append(matchingBraces, curLoc.Move(-1, b))
+ mb, left, found := b.FindMatchingBrace(bp, curLoc)
+ if found {
+ matchingBraces = append(matchingBraces, mb)
+ if !left {
+ matchingBraces = append(matchingBraces, curLoc)
+ } else {
+ matchingBraces = append(matchingBraces, curLoc.Move(-1, b))
+ }
}
}
}
for vloc.Y = 0; vloc.Y < bufHeight; vloc.Y++ {
vloc.X = 0
+ currentLine := false
+ for _, c := range cursors {
+ if bloc.Y == c.Y && w.active {
+ currentLine = true
+ break
+ }
+ }
+
+ s := lineNumStyle
+ if currentLine {
+ s = curNumStyle
+ }
+
if hasMessage {
w.drawGutter(&vloc, &bloc)
}
+ if b.Settings["diffgutter"].(bool) {
+ w.drawDiffGutter(s, false, &vloc, &bloc)
+ }
+
if b.Settings["ruler"].(bool) {
- s := lineNumStyle
- for _, c := range cursors {
- if bloc.Y == c.Y && w.active {
- s = curNumStyle
- break
- }
- }
w.drawLineNum(s, false, maxLineNumLength, &vloc, &bloc)
}
break
}
vloc.X = 0
+ if hasMessage {
+ w.drawGutter(&vloc, &bloc)
+ }
+ if b.Settings["diffgutter"].(bool) {
+ w.drawDiffGutter(lineNumStyle, true, &vloc, &bloc)
+ }
+
// This will draw an empty line number because the current line is wrapped
if b.Settings["ruler"].(bool) {
w.drawLineNum(lineNumStyle, true, maxLineNumLength, &vloc, &bloc)