Bläddra i källkod

add binding and command aliases

Johan Rong 1 månad sedan
förälder
incheckning
214b0372d3
6 ändrade filer med 209 tillägg och 85 borttagningar
  1. 65 7
      internal/buffer/buffer.go
  2. 108 70
      internal/editor/action.go
  3. 5 6
      internal/editor/keyinput.go
  4. 1 1
      internal/editor/model.go
  5. 30 0
      internal/util/util.go
  6. 0 1
      main.go

+ 65 - 7
internal/buffer/buffer.go

@@ -2,6 +2,7 @@ package buffer
 
 import (
 	"slices"
+	"unicode"
 	"unicode/utf8"
 	"github.com/zyedidia/rope"
 )
@@ -137,6 +138,69 @@ func (buf *Buffer) Clear() {
 	buf.LI = NewLineIndex()
 }
 
+func isWordRune(r rune) bool {
+	return unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_'
+}
+
+func (buf *Buffer) MoveWordHoriz(dir int) {
+	buf.ensureRope()
+
+	for i := range buf.CM.Cursors {
+		cur := &buf.CM.Cursors[i]
+		pos := normalizeOffset(buf.Rope, cur.Offset)
+
+		switch {
+		case dir > 0:
+			for pos < buf.Rope.Len() {
+				r, size := utf8.DecodeRune(buf.Rope.Slice(pos, buf.Rope.Len()))
+				if size <= 0 {
+					size = 1
+				}
+				if !isWordRune(r) {
+					break
+				}
+				pos += size
+			}
+
+			for pos < buf.Rope.Len() {
+				r, size := utf8.DecodeRune(buf.Rope.Slice(pos, buf.Rope.Len()))
+				if size <= 0 {
+					size = 1
+				}
+				if isWordRune(r) {
+					break
+				}
+				pos += size
+			}
+
+		case dir < 0:
+			for pos > 0 {
+				start := prevRuneStart(buf.Rope, pos)
+				r, _ := utf8.DecodeRune(buf.Rope.Slice(start, pos))
+				if isWordRune(r) {
+					break
+				}
+				pos = start
+			}
+
+			for pos > 0 {
+				start := prevRuneStart(buf.Rope, pos)
+				r, _ := utf8.DecodeRune(buf.Rope.Slice(start, pos))
+				if !isWordRune(r) {
+					break
+				}
+				pos = start
+			}
+		}
+
+		cur.Offset = pos
+		_, goal := LineCol(buf, cur.Offset)
+		cur.Goal = goal
+	}
+
+	buf.CM.DeduplicateAndSort()
+}
+
 func (buf *Buffer) MoveHoriz(dir int) {
 	buf.ensureRope()
 
@@ -197,14 +261,8 @@ func (buf *Buffer) AddCursorVert(dir int) {
 			continue
 		}
 
-		lineStart := OffsetForLine(buf, targetLine)
-		lineEnd := lineContentEnd(buf, targetLine)
-		lineLen := runeCount(buf.Rope, lineStart, lineEnd)
 
-		goal := cur.Goal
-		if goal > lineLen {
-			goal = lineLen
-		}
+		goal := buf.CM.Cursors[buf.CM.PrimaryIdx].Goal
 
 		newCursors = append(newCursors, Cursor{
 			Offset: OffsetForLineCol(buf, targetLine, goal),

+ 108 - 70
internal/editor/action.go

@@ -3,9 +3,11 @@ package editor
 import(
 	"strings"
 	"strconv"
+	"slices"
 	"os"
 	"github.com/zyedidia/rope"
 	"golang.design/x/clipboard"
+	"moose/internal/util"
 )
 
 type ActionManager = struct {
@@ -16,9 +18,9 @@ type ActionManager = struct {
 }
 
 type Action = struct {
-	Binding   string
-	Command   string
-	AskArgs bool
+	Binding  []string
+	Command   []string
+	AskArgs   bool
 	Callback  func(*Model, []string)
 }
 
@@ -26,58 +28,22 @@ func DefaultActionManager() ActionManager {
 	return ActionManager{
 		Common:  []Action{
 			Action{
-				Binding: "f12",
+				Binding: []string{"f12"},
 				Callback: func(m *Model, args []string) {
 					m.Mode = ModeNormal
 				},
 			},
 			Action{
-				Binding: "left",
-				Callback: func(m *Model, args []string) {
-					if m.Mode == ModePalette {
-						m.BM.PaletteBuffer.MoveHoriz(-1)
-					} else {
-						m.BM.Current().MoveHoriz(-1)
-					}
-				},
-			},
-			Action{
-				Binding: "right",
-				Callback: func(m *Model, args []string) {
-					if m.Mode == ModePalette {
-						m.BM.PaletteBuffer.MoveHoriz(1)					
-					} else {
-						m.BM.Current().MoveHoriz(1)
-					}
-				},
-			},
-			Action{
-				Binding: "up",
-				Callback: func(m *Model, args []string) {
-					if m.Mode != ModePalette {
-						m.BM.Current().MoveVert(-1)
-					}
-				},
-			},
-			Action{
-				Binding: "down",
-				Callback: func(m *Model, args []string) {
-					if m.Mode != ModePalette {
-						m.BM.Current().MoveVert(1)
-					}
-				},
-			},
-			Action{
-				Binding: "ctrl+q",
-				Command: "q",
+				Binding: []string{"ctrl+q"},
+				Command: []string{"q", "quit"},
 				AskArgs: true,
 				Callback: func(m *Model, args []string) {
 					m.Quit()
 				},
 			},
 			Action{
-				Binding: "ctrl+s",
-				Command: "s",
+				Binding: []string{"ctrl+s"},
+				Command: []string{"s", "save"},
 				AskArgs: false,
 				Callback: func(m *Model, args []string) {
 					path := ""
@@ -111,13 +77,13 @@ func DefaultActionManager() ActionManager {
 				},
 			},
 			Action{
-				Binding: "shift+ctrl+Rune[s]",
-				Command: "s",
+				Binding: []string{"shift+ctrl+Rune[s]"},
+				Command: []string{"s", "save"},
 				AskArgs: true,
 			},
 			Action{
-				Binding: "ctrl+e",
-				Command: "e",
+				Binding: []string{"ctrl+e"},
+				Command: []string{"e", "edit"},
 				AskArgs: true,
 				Callback: func(m *Model, args []string) {
 					if len(args) < 1 {
@@ -141,16 +107,74 @@ func DefaultActionManager() ActionManager {
 					m.BM.Current().Path = args[0]
 				},
 			},
+			Action{
+				Binding: []string{"left"},
+				Callback: func(m *Model, args []string) {
+					if m.Mode == ModePalette {
+						m.BM.PaletteBuffer.MoveHoriz(-1)
+					} else {
+						m.BM.Current().MoveHoriz(-1)
+					}
+				},
+			},
+			Action{
+				Binding: []string{"right"},
+				Callback: func(m *Model, args []string) {
+					if m.Mode == ModePalette {
+						m.BM.PaletteBuffer.MoveHoriz(1)					
+					} else {
+						m.BM.Current().MoveHoriz(1)
+					}
+				},
+			},
+			Action{
+				Binding: []string{"up"},
+				Callback: func(m *Model, args []string) {
+					if m.Mode != ModePalette {
+						m.BM.Current().MoveVert(-1)
+					}
+				},
+			},
+			Action{
+				Binding: []string{"down"},
+				Callback: func(m *Model, args []string) {
+					if m.Mode != ModePalette {
+						m.BM.Current().MoveVert(1)
+					}
+				},
+			},
+			Action{
+				Binding: []string{"shift+left"},
+				AskArgs: false,
+				Callback: func(m *Model, args []string) {
+					if m.Mode == ModePalette {
+						m.BM.PaletteBuffer.MoveWordHoriz(-1)
+					} else {
+						m.BM.Current().MoveWordHoriz(-1)
+					}
+				},
+			},
+			Action{
+				Binding: []string{"shift+right"},
+				AskArgs: false,
+				Callback: func(m *Model, args []string) {
+					if m.Mode == ModePalette {
+						m.BM.PaletteBuffer.MoveWordHoriz(1)
+					} else {
+						m.BM.Current().MoveWordHoriz(1)
+					}
+				},
+			},
 		},
 		Normal:  []Action{
 			Action{
-				Binding: "Rune[w]",
+				Binding: []string{"Rune[w]"},
 				Callback: func(m *Model, args []string) {
 					m.Mode = ModeWrite
 				},
 			},
 			Action{
-				Binding: "Rune[q]",
+				Binding: []string{"Rune[q]"},
 				Callback: func(m *Model, args []string) {
 					m.Mode = ModePalette
 					m.BM.PaletteBuffer.Clear()
@@ -158,7 +182,7 @@ func DefaultActionManager() ActionManager {
 				},
 			},
 			Action{
-				Binding: "Rune[f]",
+				Binding: []string{"Rune[f]"},
 				AskArgs: true,
 				Callback: func(m *Model, args []string) {
 					m.Mode = ModePalette
@@ -167,46 +191,60 @@ func DefaultActionManager() ActionManager {
 				},
 			},
 			Action{
-				Binding: "Rune[v]",
-				Command: "paste",
+				Binding: []string{"Rune[v]"},
+				Command: []string{"p", "paste"},
 				AskArgs: false,
 				Callback: func(m *Model, args []string) {
 					text := clipboard.Read(clipboard.FmtText)
 
 					if string(text) != "" {
-						m.BM.Current().Insert(string(text))
+						if m.Mode == ModePalette {
+							m.BM.PaletteBuffer.Insert(string(text))
+						} else {
+							m.BM.Current().Insert(string(text))
+						}
+					}
+				},
+			},
+			Action{
+				Binding: []string{"Rune[j]"},
+				Callback: func(m *Model, args []string) {
+					if m.Mode == ModePalette {
+						m.BM.PaletteBuffer.MoveHoriz(-1)
+					} else {
+						m.BM.Current().MoveHoriz(-1)
 					}
 				},
 			},
 		},
 		Insert:  []Action{
 			Action{
-				Binding: "shift+up",
-				Command: "TODO:",
+				Binding: []string{"shift+up"},
+				Command: []string{"TODO:"},
 				AskArgs: false,
 				Callback: func(m *Model, args []string) {
 					m.BM.Current().AddCursorVert(-1)
 				},
 			},
 			Action{
-				Binding: "shift+down",
-				Command: "TODO:",
+				Binding: []string{"shift+down"},
+				Command: []string{"TODO:"},
 				AskArgs: false,
 				Callback: func(m *Model, args []string) {
 					m.BM.Current().AddCursorVert(1)
 				},
 			},
 			Action{
-				Binding: "esc",
-				Command: "TODO:",
+				Binding: []string{"esc"},
+				Command: []string{"clrc", "clearcursors"},
 				AskArgs: false,
 				Callback: func(m *Model, args []string) {
-					m.BM.Current().Insert("test")
+					m.BM.Current().ClearCursors()
 				},
 			},
 			Action{
-				Binding: "tab",
-				Command: "TODO:",
+				Binding: []string{"tab"},
+				Command: []string{"TODO:"},
 				AskArgs: false,
 				Callback: func(m *Model, args []string) {
 					for _ = range 4 {
@@ -215,8 +253,8 @@ func DefaultActionManager() ActionManager {
 				},
 			},
 			Action{
-				Binding: "shift+tab",
-				Command: "TODO:",
+				Binding: []string{"shift+tab"},
+				Command: []string{"TODO:"},
 				AskArgs: false,
 				Callback: func(m *Model, args []string) {
 					// TODO: implement m.BM.Current().remove...
@@ -224,13 +262,13 @@ func DefaultActionManager() ActionManager {
 				},
 			},
 			Action{
-				Binding: "backspace",
+				Binding: []string{"backspace"},
 				Callback: func(m *Model, args []string) {
 					m.BM.Current().Delete()
 				},
 			},
 			Action{
-				Binding: "enter",
+				Binding: []string{"enter"},
 				Callback: func(m *Model, args []string) {
 					m.BM.Current().Insert("\n")
 				},
@@ -238,13 +276,13 @@ func DefaultActionManager() ActionManager {
 		},
 		Palette: []Action{
 			Action{
-				Binding: "backspace",
+				Binding: []string{"backspace"},
 				Callback: func(m *Model, args []string) {
 					m.BM.PaletteBuffer.Delete()
 				},
 			},
 			Action{
-				Binding: "enter",
+				Binding: []string{"enter"},
 				Callback: func(m *Model, _ []string) {
 					input := m.BM.PaletteBuffer.String()
 					args := strings.Split(input, " ")
@@ -259,7 +297,7 @@ func DefaultActionManager() ActionManager {
 						for _, action := range append(m.AM.Common, append(m.AM.Normal, m.AM.Insert...)...) {
 							if action.Callback == nil { continue }
 
-							if action.Command != "" && cmd == action.Command {
+							if len(action.Command) > 0 &&  slices.Contains(util.StandardizeBindingsArray(action.Command), util.StandardizeBinding(cmd)) {
 								m.Mode = ModeNormal
 								action.Callback(m, args[1:])
 								return

+ 5 - 6
internal/editor/keyinput.go

@@ -1,20 +1,19 @@
 package editor
 
 import (
-	"strings"
+	"slices"
 	"github.com/gdamore/tcell/v3"
+	"moose/internal/util"
 )
 
 func (m *Model) HandleKeyInput(ev *tcell.EventKey) {
 	for _, action := range append(m.CurrentActionSet(), m.AM.Common...) {
-		if action.Binding != "" && strings.ToLower(ev.Name()) == strings.ToLower(action.Binding) {
-			if action.Command != "" && action.AskArgs == true {
+		if len(action.Binding) > 0 && slices.Contains(util.StandardizeBindingsArray(action.Binding), util.StandardizeBinding(ev.Name())) {
+			if action.AskArgs == true {
 				m.Mode = ModePalette
 				m.BM.PaletteBuffer.Clear()
-				m.BM.PaletteBuffer.Insert("/" + action.Command + " ")
+				m.BM.PaletteBuffer.Insert("/" + action.Command[0] + " ")
 				return
-			} else if action.Command == "" && action.AskArgs == true {
-				m.Mode = ModePalette
 			}
 
 			action.Callback(m, []string{})

+ 1 - 1
internal/editor/model.go

@@ -20,7 +20,7 @@ func NewModel(screen tcell.Screen, style tcell.Style) Model {
 		Style:		   style,
 		Mode:		   ModeNormal,
 		BM:            buffer.BufferManager{
-			Buffers:       []buffer.Buffer{buffer.NewBuffer(), buffer.NewBuffer()},
+			Buffers:       []buffer.Buffer{buffer.NewBuffer()},
 			CurrentIdx:    0,
 			PaletteBuffer: buffer.NewBuffer(),
 		},

+ 30 - 0
internal/util/util.go

@@ -0,0 +1,30 @@
+package util
+
+import (
+	"strings"
+	"slices"
+)
+
+func StandardizeBindingsArray(arr []string) []string {
+	new := []string{}
+	for _, s := range arr {
+		new = append(new, StandardizeBinding(s))
+	}
+	return new
+}
+
+func StandardizeBinding(binding string) string {
+	arr := strings.Split(binding, "+")
+
+	for i, s := range arr {
+		lower := strings.ToLower(s)
+		arr[i] = lower
+		
+		if strings.HasPrefix(lower, "rune[") && strings.HasSuffix(lower, "]") {
+			arr[i] = lower[5 : len(s)-1]
+		}
+	}
+
+	slices.Sort(arr)
+	return strings.ToLower(strings.Join(arr, "+"))
+}

+ 0 - 1
main.go

@@ -65,7 +65,6 @@ func main() {
 			} else if ev.End() {
 				isPasting = false
 			}
-
 		case *tcell.EventKey:
 			if !isPasting {
 				m.HandleKeyInput(ev)