]> git.lizzy.rs Git - micro.git/blobdiff - internal/display/bufwindow.go
Search and replace within a selection
[micro.git] / internal / display / bufwindow.go
index 20bac4abd0ffded47fd58ba92d7884eb6f80f446..42fd489c31faa6d03745ca3ab7b787e7ec84cac0 100644 (file)
@@ -212,6 +212,9 @@ func (w *BufWindow) LocFromVisual(svloc buffer.Loc) buffer.Loc {
                if hasMessage {
                        vloc.X += 2
                }
+               if b.Settings["diffgutter"].(bool) {
+                       vloc.X++
+               }
                if b.Settings["ruler"].(bool) {
                        vloc.X += maxLineNumLength + 1
                }
@@ -272,11 +275,7 @@ func (w *BufWindow) LocFromVisual(svloc buffer.Loc) buffer.Loc {
                                        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
                                }
                        }
                }
@@ -311,6 +310,34 @@ func (w *BufWindow) drawGutter(vloc *buffer.Loc, bloc *buffer.Loc) {
        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)
 
@@ -373,15 +400,35 @@ func (w *BufWindow) displayBuffer() {
                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
@@ -398,12 +445,14 @@ func (w *BufWindow) displayBuffer() {
                                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))
+                                               }
                                        }
                                }
                        }
@@ -416,10 +465,10 @@ func (w *BufWindow) displayBuffer() {
        }
        curNumStyle := config.DefStyle
        if style, ok := config.Colorscheme["current-line-number"]; ok {
-               curNumStyle = style
                if !b.Settings["cursorline"].(bool) {
-                       _, bg, _ := lineNumStyle.Decompose()
-                       curNumStyle = curNumStyle.Background(bg)
+                       curNumStyle = lineNumStyle
+               } else {
+                       curNumStyle = style
                }
        }
 
@@ -444,18 +493,28 @@ func (w *BufWindow) displayBuffer() {
        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)
                }
 
@@ -579,6 +638,13 @@ func (w *BufWindow) displayBuffer() {
                                                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)