Skip to content
57 changes: 48 additions & 9 deletions internal/action/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -1068,6 +1068,9 @@ func (h *BufPane) ToggleHighlightSearch() bool {

// UnhighlightSearch unhighlights all instances of the last used search term
func (h *BufPane) UnhighlightSearch() bool {
if !h.Buf.HighlightSearch {
return false
}
h.Buf.HighlightSearch = false
return true
}
Expand Down Expand Up @@ -1163,15 +1166,19 @@ func (h *BufPane) DiffPrevious() bool {

// Undo undoes the last action
func (h *BufPane) Undo() bool {
h.Buf.Undo()
if !h.Buf.Undo() {
return false
}
InfoBar.Message("Undid action")
h.Relocate()
return true
}

// Redo redoes the last action
func (h *BufPane) Redo() bool {
h.Buf.Redo()
if !h.Buf.Redo() {
return false
}
InfoBar.Message("Redid action")
h.Relocate()
return true
Expand Down Expand Up @@ -1570,10 +1577,9 @@ func (h *BufPane) ToggleRuler() bool {
return true
}

// ClearStatus clears the messenger bar
// ClearStatus clears the infobar. It is an alias for ClearInfo.
func (h *BufPane) ClearStatus() bool {
InfoBar.Message("")
return true
return h.ClearInfo()
}

// ToggleHelp toggles the help screen
Expand Down Expand Up @@ -1628,12 +1634,18 @@ func (h *BufPane) Escape() bool {

// Deselect deselects on the current cursor
func (h *BufPane) Deselect() bool {
if !h.Cursor.HasSelection() {
return false
}
h.Cursor.Deselect(true)
return true
}

// ClearInfo clears the infobar
func (h *BufPane) ClearInfo() bool {
if InfoBar.Msg == "" {
return false
}
InfoBar.Message("")
return true
}
Expand Down Expand Up @@ -1724,6 +1736,10 @@ func (h *BufPane) AddTab() bool {
// PreviousTab switches to the previous tab in the tab list
func (h *BufPane) PreviousTab() bool {
tabsLen := len(Tabs.List)
if tabsLen == 1 {
return false
}

a := Tabs.Active() + tabsLen
Tabs.SetActive((a - 1) % tabsLen)

Expand All @@ -1732,8 +1748,13 @@ func (h *BufPane) PreviousTab() bool {

// NextTab switches to the next tab in the tab list
func (h *BufPane) NextTab() bool {
tabsLen := len(Tabs.List)
if tabsLen == 1 {
return false
}

a := Tabs.Active()
Tabs.SetActive((a + 1) % len(Tabs.List))
Tabs.SetActive((a + 1) % tabsLen)

return true
}
Expand Down Expand Up @@ -1769,6 +1790,10 @@ func (h *BufPane) Unsplit() bool {

// NextSplit changes the view to the next split
func (h *BufPane) NextSplit() bool {
if len(h.tab.Panes) == 1 {
return false
}

a := h.tab.active
if a < len(h.tab.Panes)-1 {
a++
Expand All @@ -1783,6 +1808,10 @@ func (h *BufPane) NextSplit() bool {

// PreviousSplit changes the view to the previous split
func (h *BufPane) PreviousSplit() bool {
if len(h.tab.Panes) == 1 {
return false
}

a := h.tab.active
if a > 0 {
a--
Expand Down Expand Up @@ -1984,6 +2013,9 @@ func (h *BufPane) MouseMultiCursor(e *tcell.EventMouse) bool {
// SkipMultiCursor moves the current multiple cursor to the next available position
func (h *BufPane) SkipMultiCursor() bool {
lastC := h.Buf.GetCursor(h.Buf.NumCursors() - 1)
if !lastC.HasSelection() {
return false
}
sel := lastC.GetSelection()
searchStart := lastC.CurSelection[1]

Expand Down Expand Up @@ -2019,17 +2051,24 @@ func (h *BufPane) RemoveMultiCursor() bool {
h.Buf.RemoveCursor(h.Buf.NumCursors() - 1)
h.Buf.SetCurCursor(h.Buf.NumCursors() - 1)
h.Buf.UpdateCursors()
} else {
} else if h.multiWord {
h.multiWord = false
h.Cursor.Deselect(true)
} else {
return false
}
h.Relocate()
return true
}

// RemoveAllMultiCursors removes all cursors except the base cursor
func (h *BufPane) RemoveAllMultiCursors() bool {
h.Buf.ClearCursors()
h.multiWord = false
if h.Buf.NumCursors() > 1 || h.multiWord {
h.Buf.ClearCursors()
h.multiWord = false
} else {
return false
}
h.Relocate()
return true
}
Expand Down
69 changes: 34 additions & 35 deletions internal/action/bufpane.go
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing refactoring! It is way clearer now what the code is suppose to do. And you squashed a bug along the way. In the original implementation the correct cursors reference gets lost after switching to a different BufPane.

Original file line number Diff line number Diff line change
Expand Up @@ -150,29 +150,31 @@ func BufMapEvent(k Event, action string) {
actionfns = append(actionfns, afn)
}
bufAction := func(h *BufPane, te *tcell.EventMouse) bool {
cursors := h.Buf.GetCursors()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cursors assignment would need to be moved 2 lines down into the actions loop. Otherwise you would still use the cursors of the original pane even though you switched to a new one in a next iteration. Line 170 updates the reference to h. 👍

success := true
for i, a := range actionfns {
innerSuccess := true
for j, c := range cursors {
if c == nil {
continue
}
h.Buf.SetCurCursor(c.Num)
h.Cursor = c
if i == 0 || (success && types[i-1] == '&') || (!success && types[i-1] == '|') || (types[i-1] == ',') {
innerSuccess = innerSuccess && h.execAction(a, names[i], j, te)
} else {
break
var success bool
if _, ok := MultiActions[names[i]]; ok {
success = true
for _, c := range h.Buf.GetCursors() {
h.Buf.SetCurCursor(c.Num)
h.Cursor = c
success = success && h.execAction(a, names[i], te)
}
} else {
h.Buf.SetCurCursor(0)
h.Cursor = h.Buf.GetActiveCursor()
success = h.execAction(a, names[i], te)
}

// if the action changed the current pane, update the reference
h = MainTab().CurPane()
success = innerSuccess
if h == nil {
// stop, in case the current pane is not a BufPane
break
}

if (!success && types[i] == '&') || (success && types[i] == '|') {
break
}
}
return true
}
Expand Down Expand Up @@ -562,36 +564,33 @@ func (h *BufPane) DoKeyEvent(e Event) bool {
return more
}

func (h *BufPane) execAction(action BufAction, name string, cursor int, te *tcell.EventMouse) bool {
func (h *BufPane) execAction(action BufAction, name string, te *tcell.EventMouse) bool {
if name != "Autocomplete" && name != "CycleAutocompleteBack" {
h.Buf.HasSuggestions = false
}

_, isMulti := MultiActions[name]
if (!isMulti && cursor == 0) || isMulti {
if h.PluginCB("pre" + name) {
var success bool
switch a := action.(type) {
case BufKeyAction:
success = a(h)
case BufMouseAction:
success = a(h, te)
}
success = success && h.PluginCB("on"+name)
if !h.PluginCB("pre" + name) {
return false
}

if isMulti {
if recordingMacro {
if name != "ToggleMacro" && name != "PlayMacro" {
curmacro = append(curmacro, action)
}
}
}
var success bool
switch a := action.(type) {
case BufKeyAction:
success = a(h)
case BufMouseAction:
success = a(h, te)
}
success = success && h.PluginCB("on"+name)

return success
if _, ok := MultiActions[name]; ok {
if recordingMacro {
if name != "ToggleMacro" && name != "PlayMacro" {
curmacro = append(curmacro, action)
}
}
}

return false
return success
}

func (h *BufPane) completeAction(action string) {
Expand Down
2 changes: 1 addition & 1 deletion internal/buffer/buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,7 @@ func (b *Buffer) ClearCursors() {
b.cursors = b.cursors[:1]
b.UpdateCursors()
b.curCursor = 0
b.GetActiveCursor().ResetSelection()
b.GetActiveCursor().Deselect(true)
}

// MoveLinesUp moves the range of lines up one row
Expand Down
22 changes: 12 additions & 10 deletions internal/buffer/eventhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,11 @@ func (eh *EventHandler) Execute(t *TextEvent) {
ExecuteTextEvent(t, eh.buf)
}

// Undo the first event in the undo stack
func (eh *EventHandler) Undo() {
// Undo the first event in the undo stack. Returns false if the stack is empty.
func (eh *EventHandler) Undo() bool {
t := eh.UndoStack.Peek()
if t == nil {
return
return false
}

startTime := t.Time.UnixNano() / int64(time.Millisecond)
Expand All @@ -266,15 +266,16 @@ func (eh *EventHandler) Undo() {
for {
t = eh.UndoStack.Peek()
if t == nil {
return
break
}

if t.Time.UnixNano()/int64(time.Millisecond) < endTime {
return
break
}

eh.UndoOneEvent()
}
return true
}

// UndoOneEvent undoes one event
Expand Down Expand Up @@ -303,11 +304,11 @@ func (eh *EventHandler) UndoOneEvent() {
eh.RedoStack.Push(t)
}

// Redo the first event in the redo stack
func (eh *EventHandler) Redo() {
// Redo the first event in the redo stack. Returns false if the stack is empty.
func (eh *EventHandler) Redo() bool {
t := eh.RedoStack.Peek()
if t == nil {
return
return false
}

startTime := t.Time.UnixNano() / int64(time.Millisecond)
Expand All @@ -316,15 +317,16 @@ func (eh *EventHandler) Redo() {
for {
t = eh.RedoStack.Peek()
if t == nil {
return
break
}

if t.Time.UnixNano()/int64(time.Millisecond) > endTime {
return
break
}

eh.RedoOneEvent()
}
return true
}

// RedoOneEvent redoes one event
Expand Down
1 change: 1 addition & 0 deletions runtime/help/keybindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ ToggleDiffGutter
ToggleRuler
JumpLine
ResetSearch
ClearInfo
ClearStatus
ShellMode
CommandMode
Expand Down