Переглянути джерело

Add repeat functionality, some more tab functionality, ++

Johan Rong 1 тиждень тому
батько
коміт
a1a39bacb8
4 змінених файлів з 196 додано та 88 видалено
  1. 105 68
      internal/editor/action.go
  2. 24 6
      internal/editor/draw.go
  3. 52 7
      internal/editor/keyinput.go
  4. 15 7
      internal/layout/layout.go

+ 105 - 68
internal/editor/action.go

@@ -19,6 +19,7 @@ type ActionManager = struct {
 	Insert  []Action
 	Palette []Action
 	CM		ChordManager
+	RCM     ChordManager
 }
 
 type Action = struct {
@@ -41,8 +42,8 @@ const (
 )
 
 type ChordManager = struct {
-	Recording   bool
-	Recorded    []string
+	Recording bool
+	Recorded  []string
 }
 
 func NewChordManager() ChordManager {
@@ -56,6 +57,42 @@ func DefaultActionManager() ActionManager {
 	am := ActionManager{
 		CM:	     NewChordManager(),
 		Common:  []Action{
+			Action{
+				Commands: []string{"bsel"},
+				AskArgs:  true,
+				Callback: func(m *Model, args []string) {
+					if len(args) < 1 {
+						return
+					}
+
+					n, err := strconv.Atoi(args[0])
+					if err != nil || n < 1 {
+						return
+					}
+
+					targetTab := n - 1
+
+					ws, ok := m.LM.Workspaces[m.LM.ActiveIdx]
+					if !ok {
+						return
+					}
+
+					selected := false
+					ws.RootContainer.WalkAndMutateActive(func(cb *layout.ContainerBuffers) layout.ContainerNode {
+						if targetTab >= 0 && targetTab < len(cb.Buffers) {
+							cb.ActiveIdx = targetTab
+							m.BM.CurrentIdx = cb.Buffers[targetTab]
+							selected = true
+						}
+						return *cb
+					})
+
+					if selected {
+						m.LM.Workspaces[m.LM.ActiveIdx] = ws
+						m.Mode = ModeNormal
+					}
+				},
+			},
 			Action{
 				Commands: []string{"version"},
 				Callback: func(m *Model, args []string) {
@@ -257,109 +294,94 @@ func DefaultActionManager() ActionManager {
 					}
 				},
 			},
-		},
-		Normal:  []Action{
 			Action{
 				Bindings: []Binding{
 					Binding{
-						Type:   BindingSingle,
-						Single: "z",
+						Type:  BindingChord,
+						Chord: []string{"ctrl+l", "enter"},
 					},
 				},
-				Commands: []string{"u", "undo"},
-				AskArgs:  false,
+				Commands: []string{"lbuf"},
+				AskArgs: false,
 				Callback: func(m *Model, args []string) {
-					if m.Mode == ModePalette {
-						m.BM.PaletteBuffer.Undo()
-					} else {
-						m.BM.Current().Undo()
-					}
+					m.AddBuffer(true)
 				},
 			},
 			Action{
 				Bindings: []Binding{
 					Binding{
 						Type:   BindingSingle,
-						Single: "y",
+						Single: "ctrl+left",
 					},
 				},
-				Commands: []string{"r", "redo"},
-				AskArgs:  false,
 				Callback: func(m *Model, args []string) {
-					if m.Mode == ModePalette {
-						m.BM.PaletteBuffer.Redo()
-					} else {
-						m.BM.Current().Redo()
-					}
+					m.CycleActiveBuffer(-1.0, 0.0)
 				},
 			},
 			Action{
 				Bindings: []Binding{
 					Binding{
-						Type:  BindingChord,
-						Chord: []string{"d", "d"},
+						Type:   BindingSingle,
+						Single: "ctrl+v",
 					},
 				},
 				Callback: func(m *Model, args []string) {
-					m.BM.Current().DeleteLine()
+					if m.LM.CurrentSplit == layout.SplitHorizontal {
+						m.LM.CurrentSplit = layout.SplitVertical
+					} else {
+						m.LM.CurrentSplit = layout.SplitHorizontal
+					}
 				},
 			},
 			Action{
 				Bindings: []Binding{
 					Binding{
 						Type:   BindingSingle,
-						Single: "w",
+						Single: "ctrl+down",
 					},
 				},
 				Callback: func(m *Model, args []string) {
-					m.Mode = ModeWrite
+					m.CycleActiveBuffer(0.0, 1.0)
 				},
 			},
 			Action{
 				Bindings: []Binding{
 					Binding{
 						Type:   BindingSingle,
-						Single: "q",
+						Single: "ctrl+up",
 					},
 				},
 				Callback: func(m *Model, args []string) {
-					m.Mode = ModePalette
-					m.BM.PaletteBuffer.Clear()
-					m.BM.PaletteBuffer.Insert("/")
+					m.CycleActiveBuffer(0.0, -1.0)
 				},
 			},
 			Action{
 				Bindings: []Binding{
 					Binding{
 						Type:   BindingSingle,
-						Single: "f",
+						Single: "ctrl+right",
 					},
 				},
-				AskArgs: true,
 				Callback: func(m *Model, args []string) {
-					m.Mode = ModePalette
-					m.BM.PaletteBuffer.Clear()
-					m.BM.PaletteBuffer.Insert("?")
+					m.CycleActiveBuffer(1.0, 0.0)
 				},
 			},
+		},
+		Normal:  []Action{
 			Action{
 				Bindings: []Binding{
 					Binding{
 						Type:   BindingSingle,
-						Single: "v",
+						Single: "z",
 					},
 				},
-				Commands: []string{"p", "paste"},
-				AskArgs: false,
+				Commands: []string{"u", "undo"},
+				AskArgs:  false,
 				Callback: func(m *Model, args []string) {
-					text := clipboard.Read(clipboard.FmtText)
-
-					if string(text) != "" {
-						if m.Mode == ModePalette {
-							m.BM.PaletteBuffer.Insert(string(text))
-						} else {
-							m.BM.Current().Insert(string(text))
-						}
+					if m.Mode == ModePalette {
+						m.BM.PaletteBuffer.Undo()
+					} else {
+						m.BM.Current().Undo()
 					}
 				},
 			},
@@ -367,85 +389,100 @@ func DefaultActionManager() ActionManager {
 				Bindings: []Binding{
 					Binding{
 						Type:   BindingSingle,
-						Single: "enter",
+						Single: "y",
 					},
 				},
-				Commands: []string{"buf"},
-				AskArgs: false,
+				Commands: []string{"r", "redo"},
+				AskArgs:  false,
 				Callback: func(m *Model, args []string) {
-					m.AddBuffer(false)
+					if m.Mode == ModePalette {
+						m.BM.PaletteBuffer.Redo()
+					} else {
+						m.BM.Current().Redo()
+					}
 				},
 			},
 			Action{
 				Bindings: []Binding{
 					Binding{
 						Type:  BindingChord,
-						Chord: []string{"l", "enter"},
+						Chord: []string{"d", "d"},
 					},
 				},
-				Commands: []string{"lbuf"},
-				AskArgs: false,
 				Callback: func(m *Model, args []string) {
-					m.AddBuffer(true)
+					m.BM.Current().DeleteLine()
 				},
 			},
 			Action{
 				Bindings: []Binding{
 					Binding{
 						Type:   BindingSingle,
-						Single: "ctrl+left",
+						Single: "w",
 					},
 				},
 				Callback: func(m *Model, args []string) {
-					m.CycleActiveBuffer(-1.0, 0.0)
+					m.Mode = ModeWrite
 				},
 			},
 			Action{
 				Bindings: []Binding{
 					Binding{
 						Type:   BindingSingle,
-						Single: "ctrl+v",
+						Single: "q",
 					},
 				},
 				Callback: func(m *Model, args []string) {
-					if m.LM.CurrentSplit == layout.SplitHorizontal {
-						m.LM.CurrentSplit = layout.SplitVertical
-					} else {
-						m.LM.CurrentSplit = layout.SplitHorizontal
-					}
+					m.Mode = ModePalette
+					m.BM.PaletteBuffer.Clear()
+					m.BM.PaletteBuffer.Insert("/")
 				},
 			},
 			Action{
 				Bindings: []Binding{
 					Binding{
 						Type:   BindingSingle,
-						Single: "ctrl+down",
+						Single: "f",
 					},
 				},
+				AskArgs: true,
 				Callback: func(m *Model, args []string) {
-					m.CycleActiveBuffer(0.0, 1.0)
+					m.Mode = ModePalette
+					m.BM.PaletteBuffer.Clear()
+					m.BM.PaletteBuffer.Insert("?")
 				},
 			},
 			Action{
 				Bindings: []Binding{
 					Binding{
 						Type:   BindingSingle,
-						Single: "ctrl+up",
+						Single: "v",
 					},
 				},
+				Commands: []string{"p", "paste"},
+				AskArgs: false,
 				Callback: func(m *Model, args []string) {
-					m.CycleActiveBuffer(0.0, -1.0)
+					text := clipboard.Read(clipboard.FmtText)
+
+					if string(text) != "" {
+						if m.Mode == ModePalette {
+							m.BM.PaletteBuffer.Insert(string(text))
+						} else {
+							m.BM.Current().Insert(string(text))
+						}
+					}
 				},
 			},
 			Action{
 				Bindings: []Binding{
 					Binding{
 						Type:   BindingSingle,
-						Single: "ctrl+right",
+						Single: "enter",
 					},
 				},
+				Commands: []string{"buf"},
+				AskArgs: false,
 				Callback: func(m *Model, args []string) {
-					m.CycleActiveBuffer(1.0, 0.0)
+					m.AddBuffer(false)
 				},
 			},
 			Action{

+ 24 - 6
internal/editor/draw.go

@@ -31,6 +31,20 @@ func (m *Model) Draw() {
 	m.DrawPalette(palette)	
 }
 
+func (m *Model) generateChordStr() string {
+	chordStr := ""
+	
+	if len(m.AM.RCM.Recorded) > 0 {
+		chordStr += strings.Join(m.AM.RCM.Recorded, "") + " + "
+	}
+
+	if len(m.AM.CM.Recorded) > 0 {
+		chordStr += strings.Join(m.AM.CM.Recorded, "+") + " +"
+	}
+
+	return chordStr
+}
+
 func (m *Model) DrawPalette(rect layout.Rect) {
 	for col := 0; col < rect.Width; col++ {
 		m.Screen.SetContent(rect.X + col, rect.Y, ' ', nil, m.Style.Background(color.Black))
@@ -68,10 +82,11 @@ func (m *Model) DrawPalette(rect layout.Rect) {
 	}
 	slices.Sort(populatedWorkspaces)
 	workspacesStr := strings.Join(populatedWorkspaces, " ")
-	m.Screen.PutStrStyled(1,  rect.Y, workspacesStr, m.Style.Background(color.Black))
-	
-	//logStr := m.DebugLog + ", " + strings.Join(m.AM.CM.Recorded, "+") + ", " + strconv.FormatBool(m.AM.CM.Recording)
-	//m.Screen.PutStrStyled(1, rect.Y, logStr, m.Style.Background(color.Black))
+	m.Screen.PutStrStyled(1, rect.Y, workspacesStr, m.Style.Background(color.Black))
+
+	chordStr := m.generateChordStr()
+	m.Screen.PutStrStyled(len(workspacesStr) + 2, rect.Y, chordStr, m.Style.Background(color.Black))
+	m.Screen.PutStrStyled(len(chordStr) + 1, rect.Y, m.DebugLog, m.Style.Background(color.Black))
 
 	if m.Mode == ModePalette {
 		m.Screen.PutStrStyled(0, rect.Y + 1, m.BM.PaletteBuffer.String(), m.Style)
@@ -170,8 +185,11 @@ func (m *Model) DrawContainerTabs(c *layout.ContainerBuffers, rect layout.Rect)
 		if i == activeTabIdx {
 			style = style.Foreground(color.White)
 		}
-		m.Screen.PutStrStyled(rect.X + length, rect.Y, tab, style)
-		length += len(tab) + 1
+
+		tabStr := strconv.Itoa((activeTabIdx - i) * -1) + ": " + tab
+
+		m.Screen.PutStrStyled(rect.X + length, rect.Y, tabStr, style)
+		length += len(tabStr) + 1
 	}
 }
 

+ 52 - 7
internal/editor/keyinput.go

@@ -3,6 +3,8 @@ package editor
 import (
 	"github.com/gdamore/tcell/v3"
 	"moose/internal/util"
+	"strconv"
+	"strings"
 )
 
 func (m *Model) HandleKeyInput(ev *tcell.EventKey) {
@@ -11,6 +13,20 @@ func (m *Model) HandleKeyInput(ev *tcell.EventKey) {
 	// m.AM.NumericCM.Recording = true, .... along these lines
 	//}
 
+	if m.AM.CM.Recording == false {
+		num, err := strconv.Atoi(util.StandardizeBinding(ev.Name()))
+		if err != nil {
+			goto Out
+		}
+
+		if m.Mode == ModeNormal {
+			m.AM.RCM.Recording = true
+			m.AM.RCM.Recorded = append(m.AM.RCM.Recorded, strconv.Itoa(num))
+			return
+		}
+	}
+
+Out:
 	for _, action := range append(m.CurrentActionSet(), m.AM.Common...) {
 		for _, binding := range action.Bindings {
 			switch binding.Type {
@@ -29,8 +45,24 @@ func (m *Model) HandleKeyInput(ev *tcell.EventKey) {
 						return
 					}
 
-					action.Callback(m, []string{})
-					return
+					if m.AM.RCM.Recording == true {
+						times, err := strconv.Atoi(strings.Join(m.AM.RCM.Recorded, ""))
+						if err != nil {
+							action.Callback(m, []string{})
+							m.AM.RCM = NewChordManager()
+							return
+						}
+
+						for range times {
+							action.Callback(m, []string{})
+						}
+
+						m.AM.RCM = NewChordManager()
+						return
+					} else {
+						action.Callback(m, []string{})
+						return
+					}
 				}
 			case BindingChord:
 				if m.AM.CM.Recording {
@@ -39,10 +71,6 @@ func (m *Model) HandleKeyInput(ev *tcell.EventKey) {
 						for i := range m.AM.CM.Recorded {
 							if m.AM.CM.Recorded[i] == binding.Chord[i] {
 								matching = true
-							//} else {
-							//	matching = false
-							//	m.AM.CM = NewChordManager()
-							//	return
 							}
 						}
 
@@ -51,7 +79,23 @@ func (m *Model) HandleKeyInput(ev *tcell.EventKey) {
 								m.AM.CM.Recorded = append(m.AM.CM.Recorded, util.StandardizeBinding(ev.Name()))
 
 								if len(m.AM.CM.Recorded) == len(binding.Chord) {
-									action.Callback(m, []string{})
+									if m.AM.RCM.Recording == true {
+										times, err := strconv.Atoi(strings.Join(m.AM.RCM.Recorded, ""))
+										if err != nil {
+											action.Callback(m, []string{})
+											m.AM.RCM = NewChordManager()
+											m.AM.CM = NewChordManager()
+											return
+										}
+
+										for range times {
+											action.Callback(m, []string{})
+										}
+									} else {
+										action.Callback(m, []string{})
+									}
+
+									m.AM.RCM = NewChordManager()
 									m.AM.CM = NewChordManager()
 								}
 
@@ -65,6 +109,7 @@ func (m *Model) HandleKeyInput(ev *tcell.EventKey) {
 
 						if len(m.AM.CM.Recorded) == len(binding.Chord) {
 							action.Callback(m, []string{})
+							m.AM.RCM = NewChordManager()
 							m.AM.CM = NewChordManager()
 						} else {
 							m.AM.CM.Recording = true

+ 15 - 7
internal/layout/layout.go

@@ -41,6 +41,17 @@ type ContainerBuffers struct {
 
 func (ContainerBuffers) isContainerNode() {}
 
+func (cb *ContainerBuffers) SelectBufferNumber(bufferNumber int) bool {
+    for idx, bufferIdx := range cb.Buffers {
+        if bufferIdx == bufferNumber {
+            cb.ActiveIdx = idx
+            return true
+        }
+    }
+
+    return false
+}
+
 type Container struct {
 	Children       [2]ContainerNode
 	Split          SplitType
@@ -274,13 +285,10 @@ func (c *Container) ActivateBufferIdx(target int) bool {
     for i, child := range c.Children {
         switch n := child.(type) {
         case ContainerBuffers:
-            for j, idx := range n.Buffers {
-                if idx == target {
-                    c.ActiveChildIdx = i
-                    n.ActiveIdx = j
-                    c.Children[i] = n
-                    return true
-                }
+            if n.SelectBufferNumber(target) {
+                c.ActiveChildIdx = i
+                c.Children[i] = n
+                return true
             }
         case Container:
             if n.ActivateBufferIdx(target) {