Skip to content

Commit f293f98

Browse files
authored
Merge pull request zyedidia#3503 from dmaluka/spawcursorup-logical-lines
Revert `SpawnMultiCursor{Up,Down}` honoring softwrap + overhaul `LastVisualX` usage
2 parents 07f8cfb + e6ed161 commit f293f98

File tree

6 files changed

+45
-49
lines changed

6 files changed

+45
-49
lines changed

internal/action/actions.go

Lines changed: 23 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,10 @@ func (h *BufPane) MoveCursorUp(n int) {
170170
if sloc == vloc.SLoc {
171171
// we are at the beginning of buffer
172172
h.Cursor.Loc = h.Buf.Start()
173-
h.Cursor.LastVisualX = 0
173+
h.Cursor.StoreVisualX()
174174
} else {
175175
vloc.SLoc = sloc
176-
vloc.VisualX = h.Cursor.LastVisualX
176+
vloc.VisualX = h.Cursor.LastWrappedVisualX
177177
h.Cursor.Loc = h.LocFromVLoc(vloc)
178178
}
179179
}
@@ -189,11 +189,10 @@ func (h *BufPane) MoveCursorDown(n int) {
189189
if sloc == vloc.SLoc {
190190
// we are at the end of buffer
191191
h.Cursor.Loc = h.Buf.End()
192-
vloc = h.VLocFromLoc(h.Cursor.Loc)
193-
h.Cursor.LastVisualX = vloc.VisualX
192+
h.Cursor.StoreVisualX()
194193
} else {
195194
vloc.SLoc = sloc
196-
vloc.VisualX = h.Cursor.LastVisualX
195+
vloc.VisualX = h.Cursor.LastWrappedVisualX
197196
h.Cursor.Loc = h.LocFromVLoc(vloc)
198197
}
199198
}
@@ -657,7 +656,7 @@ func (h *BufPane) InsertNewline() bool {
657656
h.Buf.Remove(buffer.Loc{X: 0, Y: h.Cursor.Y - 1}, buffer.Loc{X: util.CharacterCount(line), Y: h.Cursor.Y - 1})
658657
}
659658
}
660-
h.Cursor.LastVisualX = h.Cursor.GetVisualX()
659+
h.Cursor.StoreVisualX()
661660
h.Relocate()
662661
return true
663662
}
@@ -687,7 +686,7 @@ func (h *BufPane) Backspace() bool {
687686
h.Buf.Remove(loc.Move(-1, h.Buf), loc)
688687
}
689688
}
690-
h.Cursor.LastVisualX = h.Cursor.GetVisualX()
689+
h.Cursor.StoreVisualX()
691690
h.Relocate()
692691
return true
693692
}
@@ -889,7 +888,7 @@ func (h *BufPane) InsertTab() bool {
889888
b := h.Buf
890889
indent := b.IndentString(util.IntOpt(b.Settings["tabsize"]))
891890
tabBytes := len(indent)
892-
bytesUntilIndent := tabBytes - (h.Cursor.GetVisualX() % tabBytes)
891+
bytesUntilIndent := tabBytes - (h.Cursor.GetVisualX(false) % tabBytes)
893892
b.Insert(h.Cursor.Loc, indent[:bytesUntilIndent])
894893
h.Relocate()
895894
return true
@@ -1275,6 +1274,7 @@ func (h *BufPane) Copy() bool {
12751274
func (h *BufPane) CopyLine() bool {
12761275
origLoc := h.Cursor.Loc
12771276
origLastVisualX := h.Cursor.LastVisualX
1277+
origLastWrappedVisualX := h.Cursor.LastWrappedVisualX
12781278
origSelection := h.Cursor.CurSelection
12791279

12801280
nlines := h.selectLines()
@@ -1291,6 +1291,7 @@ func (h *BufPane) CopyLine() bool {
12911291

12921292
h.Cursor.Loc = origLoc
12931293
h.Cursor.LastVisualX = origLastVisualX
1294+
h.Cursor.LastWrappedVisualX = origLastWrappedVisualX
12941295
h.Cursor.CurSelection = origSelection
12951296
h.Relocate()
12961297
return true
@@ -1360,6 +1361,7 @@ func (h *BufPane) DuplicateLine() bool {
13601361
if h.Cursor.HasSelection() {
13611362
origLoc := h.Cursor.Loc
13621363
origLastVisualX := h.Cursor.LastVisualX
1364+
origLastWrappedVisualX := h.Cursor.LastWrappedVisualX
13631365
origSelection := h.Cursor.CurSelection
13641366

13651367
start := h.Cursor.CurSelection[0]
@@ -1380,6 +1382,7 @@ func (h *BufPane) DuplicateLine() bool {
13801382

13811383
h.Cursor.Loc = origLoc
13821384
h.Cursor.LastVisualX = origLastVisualX
1385+
h.Cursor.LastWrappedVisualX = origLastWrappedVisualX
13831386
h.Cursor.CurSelection = origSelection
13841387

13851388
if start.Y < end.Y {
@@ -2058,35 +2061,20 @@ func (h *BufPane) SpawnCursorAtLoc(loc buffer.Loc) *buffer.Cursor {
20582061
// SpawnMultiCursorUpN is not an action
20592062
func (h *BufPane) SpawnMultiCursorUpN(n int) bool {
20602063
lastC := h.Buf.GetCursor(h.Buf.NumCursors() - 1)
2061-
var c *buffer.Cursor
2062-
if !h.Buf.Settings["softwrap"].(bool) {
2063-
if n > 0 && lastC.Y == 0 {
2064-
return false
2065-
}
2066-
if n < 0 && lastC.Y+1 == h.Buf.LinesNum() {
2067-
return false
2068-
}
2069-
2070-
h.Buf.DeselectCursors()
2071-
2072-
c = buffer.NewCursor(h.Buf, buffer.Loc{lastC.X, lastC.Y - n})
2073-
c.LastVisualX = lastC.LastVisualX
2074-
c.X = c.GetCharPosInLine(h.Buf.LineBytes(c.Y), c.LastVisualX)
2075-
c.Relocate()
2076-
} else {
2077-
vloc := h.VLocFromLoc(lastC.Loc)
2078-
sloc := h.Scroll(vloc.SLoc, -n)
2079-
if sloc == vloc.SLoc {
2080-
return false
2081-
}
2064+
if n > 0 && lastC.Y == 0 {
2065+
return false
2066+
}
2067+
if n < 0 && lastC.Y+1 == h.Buf.LinesNum() {
2068+
return false
2069+
}
20822070

2083-
h.Buf.DeselectCursors()
2071+
h.Buf.DeselectCursors()
20842072

2085-
vloc.SLoc = sloc
2086-
vloc.VisualX = lastC.LastVisualX
2087-
c = buffer.NewCursor(h.Buf, h.LocFromVLoc(vloc))
2088-
c.LastVisualX = lastC.LastVisualX
2089-
}
2073+
c := buffer.NewCursor(h.Buf, buffer.Loc{lastC.X, lastC.Y - n})
2074+
c.LastVisualX = lastC.LastVisualX
2075+
c.LastWrappedVisualX = lastC.LastWrappedVisualX
2076+
c.X = c.GetCharPosInLine(h.Buf.LineBytes(c.Y), c.LastVisualX)
2077+
c.Relocate()
20902078

20912079
h.Buf.AddCursor(c)
20922080
h.Buf.SetCurCursor(h.Buf.NumCursors() - 1)

internal/buffer/cursor.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,14 @@ type Cursor struct {
2020
buf *Buffer
2121
Loc
2222

23-
// Last cursor x position
23+
// Last visual x position of the cursor. Used in cursor up/down movements
24+
// for remembering the original x position when moving to a line that is
25+
// shorter than current x position.
2426
LastVisualX int
27+
// Similar to LastVisualX but takes softwrapping into account, i.e. last
28+
// visual x position in a visual (wrapped) line on the screen, which may be
29+
// different from the line in the buffer.
30+
LastWrappedVisualX int
2531

2632
// The current selection as a range of character numbers (inclusive)
2733
CurSelection [2]Loc
@@ -61,8 +67,9 @@ func (c *Cursor) Buf() *Buffer {
6167
// Goto puts the cursor at the given cursor's location and gives
6268
// the current cursor its selection too
6369
func (c *Cursor) Goto(b Cursor) {
64-
c.X, c.Y, c.LastVisualX = b.X, b.Y, b.LastVisualX
70+
c.X, c.Y = b.X, b.Y
6571
c.OrigSelection, c.CurSelection = b.OrigSelection, b.CurSelection
72+
c.StoreVisualX()
6673
}
6774

6875
// GotoLoc puts the cursor at the given cursor's location and gives
@@ -73,8 +80,8 @@ func (c *Cursor) GotoLoc(l Loc) {
7380
}
7481

7582
// GetVisualX returns the x value of the cursor in visual spaces
76-
func (c *Cursor) GetVisualX() int {
77-
if c.buf.GetVisualX != nil {
83+
func (c *Cursor) GetVisualX(wrap bool) int {
84+
if wrap && c.buf.GetVisualX != nil {
7885
return c.buf.GetVisualX(c.Loc)
7986
}
8087

@@ -100,7 +107,7 @@ func (c *Cursor) GetCharPosInLine(b []byte, visualPos int) int {
100107
// Start moves the cursor to the start of the line it is on
101108
func (c *Cursor) Start() {
102109
c.X = 0
103-
c.LastVisualX = c.GetVisualX()
110+
c.StoreVisualX()
104111
}
105112

106113
// StartOfText moves the cursor to the first non-whitespace rune of
@@ -131,7 +138,7 @@ func (c *Cursor) IsStartOfText() bool {
131138
// End moves the cursor to the end of the line it is on
132139
func (c *Cursor) End() {
133140
c.X = util.CharacterCount(c.buf.LineBytes(c.Y))
134-
c.LastVisualX = c.GetVisualX()
141+
c.StoreVisualX()
135142
}
136143

137144
// CopySelection copies the user's selection to either "primary"
@@ -615,5 +622,6 @@ func (c *Cursor) RuneUnder(x int) rune {
615622
}
616623

617624
func (c *Cursor) StoreVisualX() {
618-
c.LastVisualX = c.GetVisualX()
625+
c.LastVisualX = c.GetVisualX(false)
626+
c.LastWrappedVisualX = c.GetVisualX(true)
619627
}

internal/buffer/eventhandler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func (eh *EventHandler) DoTextEvent(t *TextEvent, useUndo bool) {
104104
c.OrigSelection[0] = move(c.OrigSelection[0])
105105
c.OrigSelection[1] = move(c.OrigSelection[1])
106106
c.Relocate()
107-
c.LastVisualX = c.GetVisualX()
107+
c.StoreVisualX()
108108
}
109109

110110
if useUndo {

internal/display/bufwindow.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func (w *BufWindow) SetBuffer(b *buffer.Buffer) {
5858
if option == "softwrap" || option == "wordwrap" {
5959
w.Relocate()
6060
for _, c := range w.Buf.GetCursors() {
61-
c.LastVisualX = c.GetVisualX()
61+
c.LastWrappedVisualX = c.GetVisualX(true)
6262
}
6363
}
6464
}
@@ -160,7 +160,7 @@ func (w *BufWindow) updateDisplayInfo() {
160160

161161
if w.bufWidth != prevBufWidth && w.Buf.Settings["softwrap"].(bool) {
162162
for _, c := range w.Buf.GetCursors() {
163-
c.LastVisualX = c.GetVisualX()
163+
c.LastWrappedVisualX = c.GetVisualX(true)
164164
}
165165
}
166166
}
@@ -238,7 +238,7 @@ func (w *BufWindow) Relocate() bool {
238238

239239
// horizontal relocation (scrolling)
240240
if !b.Settings["softwrap"].(bool) {
241-
cx := activeC.GetVisualX()
241+
cx := activeC.GetVisualX(false)
242242
rw := runewidth.RuneWidth(activeC.RuneUnder(activeC.X))
243243
if rw == 0 {
244244
rw = 1 // tab or newline

runtime/plugins/comment/comment.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ function commentLine(bp, lineN, indentLen)
107107
bp.Cursor.Y = curpos.Y
108108
end
109109
bp.Cursor:Relocate()
110-
bp.Cursor.LastVisualX = bp.Cursor:GetVisualX()
110+
bp.Cursor:StoreVisualX()
111111
end
112112

113113
function uncommentLine(bp, lineN, commentRegex)
@@ -135,7 +135,7 @@ function uncommentLine(bp, lineN, commentRegex)
135135
end
136136
end
137137
bp.Cursor:Relocate()
138-
bp.Cursor.LastVisualX = bp.Cursor:GetVisualX()
138+
bp.Cursor:StoreVisualX()
139139
end
140140

141141
function toggleCommentLine(bp, lineN, commentRegex)

runtime/plugins/status/status.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function lines(b)
2121
end
2222

2323
function vcol(b)
24-
return tostring(b:GetActiveCursor():GetVisualX())
24+
return tostring(b:GetActiveCursor():GetVisualX(false))
2525
end
2626

2727
function bytes(b)

0 commit comments

Comments
 (0)