mirror of
https://github.com/zyedidia/micro.git
synced 2026-03-29 22:27:13 +09:00
Merge pull request #3503 from dmaluka/spawcursorup-logical-lines
Revert `SpawnMultiCursor{Up,Down}` honoring softwrap + overhaul `LastVisualX` usage
This commit is contained in:
@@ -170,10 +170,10 @@ func (h *BufPane) MoveCursorUp(n int) {
|
|||||||
if sloc == vloc.SLoc {
|
if sloc == vloc.SLoc {
|
||||||
// we are at the beginning of buffer
|
// we are at the beginning of buffer
|
||||||
h.Cursor.Loc = h.Buf.Start()
|
h.Cursor.Loc = h.Buf.Start()
|
||||||
h.Cursor.LastVisualX = 0
|
h.Cursor.StoreVisualX()
|
||||||
} else {
|
} else {
|
||||||
vloc.SLoc = sloc
|
vloc.SLoc = sloc
|
||||||
vloc.VisualX = h.Cursor.LastVisualX
|
vloc.VisualX = h.Cursor.LastWrappedVisualX
|
||||||
h.Cursor.Loc = h.LocFromVLoc(vloc)
|
h.Cursor.Loc = h.LocFromVLoc(vloc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,11 +189,10 @@ func (h *BufPane) MoveCursorDown(n int) {
|
|||||||
if sloc == vloc.SLoc {
|
if sloc == vloc.SLoc {
|
||||||
// we are at the end of buffer
|
// we are at the end of buffer
|
||||||
h.Cursor.Loc = h.Buf.End()
|
h.Cursor.Loc = h.Buf.End()
|
||||||
vloc = h.VLocFromLoc(h.Cursor.Loc)
|
h.Cursor.StoreVisualX()
|
||||||
h.Cursor.LastVisualX = vloc.VisualX
|
|
||||||
} else {
|
} else {
|
||||||
vloc.SLoc = sloc
|
vloc.SLoc = sloc
|
||||||
vloc.VisualX = h.Cursor.LastVisualX
|
vloc.VisualX = h.Cursor.LastWrappedVisualX
|
||||||
h.Cursor.Loc = h.LocFromVLoc(vloc)
|
h.Cursor.Loc = h.LocFromVLoc(vloc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -657,7 +656,7 @@ func (h *BufPane) InsertNewline() bool {
|
|||||||
h.Buf.Remove(buffer.Loc{X: 0, Y: h.Cursor.Y - 1}, buffer.Loc{X: util.CharacterCount(line), Y: h.Cursor.Y - 1})
|
h.Buf.Remove(buffer.Loc{X: 0, Y: h.Cursor.Y - 1}, buffer.Loc{X: util.CharacterCount(line), Y: h.Cursor.Y - 1})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
h.Cursor.LastVisualX = h.Cursor.GetVisualX()
|
h.Cursor.StoreVisualX()
|
||||||
h.Relocate()
|
h.Relocate()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -687,7 +686,7 @@ func (h *BufPane) Backspace() bool {
|
|||||||
h.Buf.Remove(loc.Move(-1, h.Buf), loc)
|
h.Buf.Remove(loc.Move(-1, h.Buf), loc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
h.Cursor.LastVisualX = h.Cursor.GetVisualX()
|
h.Cursor.StoreVisualX()
|
||||||
h.Relocate()
|
h.Relocate()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -889,7 +888,7 @@ func (h *BufPane) InsertTab() bool {
|
|||||||
b := h.Buf
|
b := h.Buf
|
||||||
indent := b.IndentString(util.IntOpt(b.Settings["tabsize"]))
|
indent := b.IndentString(util.IntOpt(b.Settings["tabsize"]))
|
||||||
tabBytes := len(indent)
|
tabBytes := len(indent)
|
||||||
bytesUntilIndent := tabBytes - (h.Cursor.GetVisualX() % tabBytes)
|
bytesUntilIndent := tabBytes - (h.Cursor.GetVisualX(false) % tabBytes)
|
||||||
b.Insert(h.Cursor.Loc, indent[:bytesUntilIndent])
|
b.Insert(h.Cursor.Loc, indent[:bytesUntilIndent])
|
||||||
h.Relocate()
|
h.Relocate()
|
||||||
return true
|
return true
|
||||||
@@ -1275,6 +1274,7 @@ func (h *BufPane) Copy() bool {
|
|||||||
func (h *BufPane) CopyLine() bool {
|
func (h *BufPane) CopyLine() bool {
|
||||||
origLoc := h.Cursor.Loc
|
origLoc := h.Cursor.Loc
|
||||||
origLastVisualX := h.Cursor.LastVisualX
|
origLastVisualX := h.Cursor.LastVisualX
|
||||||
|
origLastWrappedVisualX := h.Cursor.LastWrappedVisualX
|
||||||
origSelection := h.Cursor.CurSelection
|
origSelection := h.Cursor.CurSelection
|
||||||
|
|
||||||
nlines := h.selectLines()
|
nlines := h.selectLines()
|
||||||
@@ -1291,6 +1291,7 @@ func (h *BufPane) CopyLine() bool {
|
|||||||
|
|
||||||
h.Cursor.Loc = origLoc
|
h.Cursor.Loc = origLoc
|
||||||
h.Cursor.LastVisualX = origLastVisualX
|
h.Cursor.LastVisualX = origLastVisualX
|
||||||
|
h.Cursor.LastWrappedVisualX = origLastWrappedVisualX
|
||||||
h.Cursor.CurSelection = origSelection
|
h.Cursor.CurSelection = origSelection
|
||||||
h.Relocate()
|
h.Relocate()
|
||||||
return true
|
return true
|
||||||
@@ -1360,6 +1361,7 @@ func (h *BufPane) DuplicateLine() bool {
|
|||||||
if h.Cursor.HasSelection() {
|
if h.Cursor.HasSelection() {
|
||||||
origLoc := h.Cursor.Loc
|
origLoc := h.Cursor.Loc
|
||||||
origLastVisualX := h.Cursor.LastVisualX
|
origLastVisualX := h.Cursor.LastVisualX
|
||||||
|
origLastWrappedVisualX := h.Cursor.LastWrappedVisualX
|
||||||
origSelection := h.Cursor.CurSelection
|
origSelection := h.Cursor.CurSelection
|
||||||
|
|
||||||
start := h.Cursor.CurSelection[0]
|
start := h.Cursor.CurSelection[0]
|
||||||
@@ -1380,6 +1382,7 @@ func (h *BufPane) DuplicateLine() bool {
|
|||||||
|
|
||||||
h.Cursor.Loc = origLoc
|
h.Cursor.Loc = origLoc
|
||||||
h.Cursor.LastVisualX = origLastVisualX
|
h.Cursor.LastVisualX = origLastVisualX
|
||||||
|
h.Cursor.LastWrappedVisualX = origLastWrappedVisualX
|
||||||
h.Cursor.CurSelection = origSelection
|
h.Cursor.CurSelection = origSelection
|
||||||
|
|
||||||
if start.Y < end.Y {
|
if start.Y < end.Y {
|
||||||
@@ -2058,35 +2061,20 @@ func (h *BufPane) SpawnCursorAtLoc(loc buffer.Loc) *buffer.Cursor {
|
|||||||
// SpawnMultiCursorUpN is not an action
|
// SpawnMultiCursorUpN is not an action
|
||||||
func (h *BufPane) SpawnMultiCursorUpN(n int) bool {
|
func (h *BufPane) SpawnMultiCursorUpN(n int) bool {
|
||||||
lastC := h.Buf.GetCursor(h.Buf.NumCursors() - 1)
|
lastC := h.Buf.GetCursor(h.Buf.NumCursors() - 1)
|
||||||
var c *buffer.Cursor
|
if n > 0 && lastC.Y == 0 {
|
||||||
if !h.Buf.Settings["softwrap"].(bool) {
|
return false
|
||||||
if n > 0 && lastC.Y == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if n < 0 && lastC.Y+1 == h.Buf.LinesNum() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
h.Buf.DeselectCursors()
|
|
||||||
|
|
||||||
c = buffer.NewCursor(h.Buf, buffer.Loc{lastC.X, lastC.Y - n})
|
|
||||||
c.LastVisualX = lastC.LastVisualX
|
|
||||||
c.X = c.GetCharPosInLine(h.Buf.LineBytes(c.Y), c.LastVisualX)
|
|
||||||
c.Relocate()
|
|
||||||
} else {
|
|
||||||
vloc := h.VLocFromLoc(lastC.Loc)
|
|
||||||
sloc := h.Scroll(vloc.SLoc, -n)
|
|
||||||
if sloc == vloc.SLoc {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
h.Buf.DeselectCursors()
|
|
||||||
|
|
||||||
vloc.SLoc = sloc
|
|
||||||
vloc.VisualX = lastC.LastVisualX
|
|
||||||
c = buffer.NewCursor(h.Buf, h.LocFromVLoc(vloc))
|
|
||||||
c.LastVisualX = lastC.LastVisualX
|
|
||||||
}
|
}
|
||||||
|
if n < 0 && lastC.Y+1 == h.Buf.LinesNum() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
h.Buf.DeselectCursors()
|
||||||
|
|
||||||
|
c := buffer.NewCursor(h.Buf, buffer.Loc{lastC.X, lastC.Y - n})
|
||||||
|
c.LastVisualX = lastC.LastVisualX
|
||||||
|
c.LastWrappedVisualX = lastC.LastWrappedVisualX
|
||||||
|
c.X = c.GetCharPosInLine(h.Buf.LineBytes(c.Y), c.LastVisualX)
|
||||||
|
c.Relocate()
|
||||||
|
|
||||||
h.Buf.AddCursor(c)
|
h.Buf.AddCursor(c)
|
||||||
h.Buf.SetCurCursor(h.Buf.NumCursors() - 1)
|
h.Buf.SetCurCursor(h.Buf.NumCursors() - 1)
|
||||||
|
|||||||
@@ -20,8 +20,14 @@ type Cursor struct {
|
|||||||
buf *Buffer
|
buf *Buffer
|
||||||
Loc
|
Loc
|
||||||
|
|
||||||
// Last cursor x position
|
// Last visual x position of the cursor. Used in cursor up/down movements
|
||||||
|
// for remembering the original x position when moving to a line that is
|
||||||
|
// shorter than current x position.
|
||||||
LastVisualX int
|
LastVisualX int
|
||||||
|
// Similar to LastVisualX but takes softwrapping into account, i.e. last
|
||||||
|
// visual x position in a visual (wrapped) line on the screen, which may be
|
||||||
|
// different from the line in the buffer.
|
||||||
|
LastWrappedVisualX int
|
||||||
|
|
||||||
// The current selection as a range of character numbers (inclusive)
|
// The current selection as a range of character numbers (inclusive)
|
||||||
CurSelection [2]Loc
|
CurSelection [2]Loc
|
||||||
@@ -61,8 +67,9 @@ func (c *Cursor) Buf() *Buffer {
|
|||||||
// Goto puts the cursor at the given cursor's location and gives
|
// Goto puts the cursor at the given cursor's location and gives
|
||||||
// the current cursor its selection too
|
// the current cursor its selection too
|
||||||
func (c *Cursor) Goto(b Cursor) {
|
func (c *Cursor) Goto(b Cursor) {
|
||||||
c.X, c.Y, c.LastVisualX = b.X, b.Y, b.LastVisualX
|
c.X, c.Y = b.X, b.Y
|
||||||
c.OrigSelection, c.CurSelection = b.OrigSelection, b.CurSelection
|
c.OrigSelection, c.CurSelection = b.OrigSelection, b.CurSelection
|
||||||
|
c.StoreVisualX()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GotoLoc puts the cursor at the given cursor's location and gives
|
// GotoLoc puts the cursor at the given cursor's location and gives
|
||||||
@@ -73,8 +80,8 @@ func (c *Cursor) GotoLoc(l Loc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetVisualX returns the x value of the cursor in visual spaces
|
// GetVisualX returns the x value of the cursor in visual spaces
|
||||||
func (c *Cursor) GetVisualX() int {
|
func (c *Cursor) GetVisualX(wrap bool) int {
|
||||||
if c.buf.GetVisualX != nil {
|
if wrap && c.buf.GetVisualX != nil {
|
||||||
return c.buf.GetVisualX(c.Loc)
|
return c.buf.GetVisualX(c.Loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +107,7 @@ func (c *Cursor) GetCharPosInLine(b []byte, visualPos int) int {
|
|||||||
// Start moves the cursor to the start of the line it is on
|
// Start moves the cursor to the start of the line it is on
|
||||||
func (c *Cursor) Start() {
|
func (c *Cursor) Start() {
|
||||||
c.X = 0
|
c.X = 0
|
||||||
c.LastVisualX = c.GetVisualX()
|
c.StoreVisualX()
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartOfText moves the cursor to the first non-whitespace rune of
|
// StartOfText moves the cursor to the first non-whitespace rune of
|
||||||
@@ -131,7 +138,7 @@ func (c *Cursor) IsStartOfText() bool {
|
|||||||
// End moves the cursor to the end of the line it is on
|
// End moves the cursor to the end of the line it is on
|
||||||
func (c *Cursor) End() {
|
func (c *Cursor) End() {
|
||||||
c.X = util.CharacterCount(c.buf.LineBytes(c.Y))
|
c.X = util.CharacterCount(c.buf.LineBytes(c.Y))
|
||||||
c.LastVisualX = c.GetVisualX()
|
c.StoreVisualX()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopySelection copies the user's selection to either "primary"
|
// CopySelection copies the user's selection to either "primary"
|
||||||
@@ -615,5 +622,6 @@ func (c *Cursor) RuneUnder(x int) rune {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cursor) StoreVisualX() {
|
func (c *Cursor) StoreVisualX() {
|
||||||
c.LastVisualX = c.GetVisualX()
|
c.LastVisualX = c.GetVisualX(false)
|
||||||
|
c.LastWrappedVisualX = c.GetVisualX(true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ func (eh *EventHandler) DoTextEvent(t *TextEvent, useUndo bool) {
|
|||||||
c.OrigSelection[0] = move(c.OrigSelection[0])
|
c.OrigSelection[0] = move(c.OrigSelection[0])
|
||||||
c.OrigSelection[1] = move(c.OrigSelection[1])
|
c.OrigSelection[1] = move(c.OrigSelection[1])
|
||||||
c.Relocate()
|
c.Relocate()
|
||||||
c.LastVisualX = c.GetVisualX()
|
c.StoreVisualX()
|
||||||
}
|
}
|
||||||
|
|
||||||
if useUndo {
|
if useUndo {
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ func (w *BufWindow) SetBuffer(b *buffer.Buffer) {
|
|||||||
if option == "softwrap" || option == "wordwrap" {
|
if option == "softwrap" || option == "wordwrap" {
|
||||||
w.Relocate()
|
w.Relocate()
|
||||||
for _, c := range w.Buf.GetCursors() {
|
for _, c := range w.Buf.GetCursors() {
|
||||||
c.LastVisualX = c.GetVisualX()
|
c.LastWrappedVisualX = c.GetVisualX(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ func (w *BufWindow) updateDisplayInfo() {
|
|||||||
|
|
||||||
if w.bufWidth != prevBufWidth && w.Buf.Settings["softwrap"].(bool) {
|
if w.bufWidth != prevBufWidth && w.Buf.Settings["softwrap"].(bool) {
|
||||||
for _, c := range w.Buf.GetCursors() {
|
for _, c := range w.Buf.GetCursors() {
|
||||||
c.LastVisualX = c.GetVisualX()
|
c.LastWrappedVisualX = c.GetVisualX(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,7 +238,7 @@ func (w *BufWindow) Relocate() bool {
|
|||||||
|
|
||||||
// horizontal relocation (scrolling)
|
// horizontal relocation (scrolling)
|
||||||
if !b.Settings["softwrap"].(bool) {
|
if !b.Settings["softwrap"].(bool) {
|
||||||
cx := activeC.GetVisualX()
|
cx := activeC.GetVisualX(false)
|
||||||
rw := runewidth.RuneWidth(activeC.RuneUnder(activeC.X))
|
rw := runewidth.RuneWidth(activeC.RuneUnder(activeC.X))
|
||||||
if rw == 0 {
|
if rw == 0 {
|
||||||
rw = 1 // tab or newline
|
rw = 1 // tab or newline
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ function commentLine(bp, lineN, indentLen)
|
|||||||
bp.Cursor.Y = curpos.Y
|
bp.Cursor.Y = curpos.Y
|
||||||
end
|
end
|
||||||
bp.Cursor:Relocate()
|
bp.Cursor:Relocate()
|
||||||
bp.Cursor.LastVisualX = bp.Cursor:GetVisualX()
|
bp.Cursor:StoreVisualX()
|
||||||
end
|
end
|
||||||
|
|
||||||
function uncommentLine(bp, lineN, commentRegex)
|
function uncommentLine(bp, lineN, commentRegex)
|
||||||
@@ -135,7 +135,7 @@ function uncommentLine(bp, lineN, commentRegex)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
bp.Cursor:Relocate()
|
bp.Cursor:Relocate()
|
||||||
bp.Cursor.LastVisualX = bp.Cursor:GetVisualX()
|
bp.Cursor:StoreVisualX()
|
||||||
end
|
end
|
||||||
|
|
||||||
function toggleCommentLine(bp, lineN, commentRegex)
|
function toggleCommentLine(bp, lineN, commentRegex)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ function lines(b)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function vcol(b)
|
function vcol(b)
|
||||||
return tostring(b:GetActiveCursor():GetVisualX())
|
return tostring(b:GetActiveCursor():GetVisualX(false))
|
||||||
end
|
end
|
||||||
|
|
||||||
function bytes(b)
|
function bytes(b)
|
||||||
|
|||||||
Reference in New Issue
Block a user