]> git.lizzy.rs Git - micro.git/commitdiff
Implement moving cursor up/down within a wrapped line
authorDmitry Maluka <dmitrymaluka@gmail.com>
Sat, 6 Mar 2021 22:43:36 +0000 (23:43 +0100)
committerDmitry Maluka <dmitrymaluka@gmail.com>
Thu, 8 Apr 2021 21:54:02 +0000 (23:54 +0200)
Modified behavior of CursorUp, CursorDown, CursorPageUp etc:
if softwrap is enabled, cursor moves by visual lines, not logical lines.

TODO: implement it also for Home and End keys: move cursor to the
visual start or end of a line. I haven't implemented it for now, because
I'm not sure what should be the behavior of StartOfTextToggle then
(considering that Home key is bound to StartOfTextToggle by default).

Fixes #1598

internal/action/actions.go
internal/buffer/buffer.go
internal/buffer/cursor.go
internal/display/bufwindow.go

index c0334a6ae090e6f2ebbc9f1b931d612efc2f7c13..f25ad04e525c8288f8a9f21be9d802ece0745d52 100644 (file)
@@ -123,10 +123,49 @@ func (h *BufPane) Center() bool {
        return true
 }
 
+// MoveCursorUp is not an action
+func (h *BufPane) MoveCursorUp(n int) {
+       if !h.Buf.Settings["softwrap"].(bool) {
+               h.Cursor.UpN(n)
+       } else {
+               vloc := h.VLocFromLoc(h.Cursor.Loc)
+               sloc := h.Scroll(vloc.SLoc, -n)
+               if sloc == vloc.SLoc {
+                       // we are at the beginning of buffer
+                       h.Cursor.Loc = h.Buf.Start()
+                       h.Cursor.LastVisualX = 0
+               } else {
+                       vloc.SLoc = sloc
+                       vloc.VisualX = h.Cursor.LastVisualX
+                       h.Cursor.Loc = h.LocFromVLoc(vloc)
+               }
+       }
+}
+
+// MoveCursorDown is not an action
+func (h *BufPane) MoveCursorDown(n int) {
+       if !h.Buf.Settings["softwrap"].(bool) {
+               h.Cursor.DownN(n)
+       } else {
+               vloc := h.VLocFromLoc(h.Cursor.Loc)
+               sloc := h.Scroll(vloc.SLoc, n)
+               if sloc == vloc.SLoc {
+                       // we are at the end of buffer
+                       h.Cursor.Loc = h.Buf.End()
+                       vloc = h.VLocFromLoc(h.Cursor.Loc)
+                       h.Cursor.LastVisualX = vloc.VisualX
+               } else {
+                       vloc.SLoc = sloc
+                       vloc.VisualX = h.Cursor.LastVisualX
+                       h.Cursor.Loc = h.LocFromVLoc(vloc)
+               }
+       }
+}
+
 // CursorUp moves the cursor up
 func (h *BufPane) CursorUp() bool {
        h.Cursor.Deselect(true)
-       h.Cursor.Up()
+       h.MoveCursorUp(1)
        h.Relocate()
        return true
 }
@@ -134,7 +173,7 @@ func (h *BufPane) CursorUp() bool {
 // CursorDown moves the cursor down
 func (h *BufPane) CursorDown() bool {
        h.Cursor.Deselect(true)
-       h.Cursor.Down()
+       h.MoveCursorDown(1)
        h.Relocate()
        return true
 }
@@ -212,7 +251,7 @@ func (h *BufPane) SelectUp() bool {
        if !h.Cursor.HasSelection() {
                h.Cursor.OrigSelection[0] = h.Cursor.Loc
        }
-       h.Cursor.Up()
+       h.MoveCursorUp(1)
        h.Cursor.SelectTo(h.Cursor.Loc)
        h.Relocate()
        return true
@@ -223,7 +262,7 @@ func (h *BufPane) SelectDown() bool {
        if !h.Cursor.HasSelection() {
                h.Cursor.OrigSelection[0] = h.Cursor.Loc
        }
-       h.Cursor.Down()
+       h.MoveCursorDown(1)
        h.Cursor.SelectTo(h.Cursor.Loc)
        h.Relocate()
        return true
@@ -1274,7 +1313,7 @@ func (h *BufPane) SelectPageUp() bool {
        if !h.Cursor.HasSelection() {
                h.Cursor.OrigSelection[0] = h.Cursor.Loc
        }
-       h.Cursor.UpN(h.BufHeight())
+       h.MoveCursorUp(h.BufHeight())
        h.Cursor.SelectTo(h.Cursor.Loc)
        h.Relocate()
        return true
@@ -1285,7 +1324,7 @@ func (h *BufPane) SelectPageDown() bool {
        if !h.Cursor.HasSelection() {
                h.Cursor.OrigSelection[0] = h.Cursor.Loc
        }
-       h.Cursor.DownN(h.BufHeight())
+       h.MoveCursorDown(h.BufHeight())
        h.Cursor.SelectTo(h.Cursor.Loc)
        h.Relocate()
        return true
@@ -1300,7 +1339,7 @@ func (h *BufPane) CursorPageUp() bool {
                h.Cursor.ResetSelection()
                h.Cursor.StoreVisualX()
        }
-       h.Cursor.UpN(h.BufHeight())
+       h.MoveCursorUp(h.BufHeight())
        h.Relocate()
        return true
 }
@@ -1314,7 +1353,7 @@ func (h *BufPane) CursorPageDown() bool {
                h.Cursor.ResetSelection()
                h.Cursor.StoreVisualX()
        }
-       h.Cursor.DownN(h.BufHeight())
+       h.MoveCursorDown(h.BufHeight())
        h.Relocate()
        return true
 }
index 718510dd041ed6522b72fd3027a438ac6fa954c0..034e28e5686576d69366bc575b0a278d2d632285 100644 (file)
@@ -196,6 +196,12 @@ type Buffer struct {
        // the buffer module cannot directly call the display's API (it would mean
        // a circular dependency between packages).
        OptionCallback func(option string, nativeValue interface{})
+
+       // The display module registers its own GetVisualX function for getting
+       // the correct visual x location of a cursor when softwrap is used.
+       // This is hacky. Maybe it would be better to move all the visual x logic
+       // from buffer to display, but it would require rewriting a lot of code.
+       GetVisualX func(loc Loc) int
 }
 
 // NewBufferFromFileAtLoc opens a new buffer with a given cursor location
index aa3daf023463c27d80a687db66e64958f64ac669..12fc5db2962c3b620a286f23958ac15eacfbc05c 100644 (file)
@@ -67,6 +67,10 @@ func (c *Cursor) GotoLoc(l Loc) {
 
 // GetVisualX returns the x value of the cursor in visual spaces
 func (c *Cursor) GetVisualX() int {
+       if c.buf.GetVisualX != nil {
+               return c.buf.GetVisualX(c.Loc)
+       }
+
        if c.X <= 0 {
                c.X = 0
                return 0
index e493547bedfce84b24cfe33b9b04993140545789..930d9c36936af10690d4a75cc58b357ddd962438 100644 (file)
@@ -54,8 +54,15 @@ func (w *BufWindow) SetBuffer(b *buffer.Buffer) {
                                w.StartLine.Row = 0
                        }
                        w.Relocate()
+
+                       for _, c := range w.Buf.GetCursors() {
+                               c.LastVisualX = c.GetVisualX()
+                       }
                }
        }
+       b.GetVisualX = func(loc buffer.Loc) int {
+               return w.VLocFromLoc(loc).VisualX
+       }
 }
 
 func (w *BufWindow) GetView() *View {
@@ -68,7 +75,15 @@ func (w *BufWindow) SetView(view *View) {
 
 func (w *BufWindow) Resize(width, height int) {
        w.Width, w.Height = width, height
+       w.updateDisplayInfo()
+
        w.Relocate()
+
+       if w.Buf.Settings["softwrap"].(bool) {
+               for _, c := range w.Buf.GetCursors() {
+                       c.LastVisualX = c.GetVisualX()
+               }
+       }
 }
 
 func (w *BufWindow) SetActive(b bool) {