浏览代码

Configuration stuff

Johan Rong 6 天之前
父节点
当前提交
1e82d06272
共有 5 个文件被更改,包括 258 次插入38 次删除
  1. 6 2
      internal/editor/action.go
  2. 11 4
      internal/editor/config.go
  3. 35 21
      internal/editor/draw.go
  4. 173 11
      internal/extension/config.go
  5. 33 0
      internal/extension/lua/init.lua

+ 6 - 2
internal/editor/action.go

@@ -597,8 +597,12 @@ func DefaultActionManager() ActionManager {
 					},
 				},
 				Callback: func(m *Model, args []string) {
-					for _ = range 4 {
-						m.BM.Current().Insert(" ")
+					if m.Config.Properties.TabSpaces == true {
+						for _ = range m.Config.Properties.TabWidthSpaces {
+							m.BM.Current().Insert(" ")
+						}
+					} else {
+						m.BM.Current().Insert("\t")
 					}
 				},
 			},

+ 11 - 4
internal/editor/config.go

@@ -7,10 +7,17 @@ import (
 
 type Config struct {
 	StyleDefault tcell.Style
-	Style        Style
+	Colors       Colors
+	Properties   Properties
 }
 
-type Style struct {
+type Properties struct {
+	GutterWidth int    `default:"4"`
+	TabSpaces 	bool   `default:"false"`
+	TabWidthSpaces int `default:"4"`
+}
+
+type Colors struct {
 	MainBackground            string `default:"#090603"`
 	MainForeground            string `default:"#dddddd"`
 	LineNumberBackground      string `default:"#090603"`
@@ -43,12 +50,12 @@ func DefaultConfig() Config {
 		panic(err)
 	}
 
-	config.StyleDefault = tcell.StyleDefault.Background(tcell.GetColor(config.Style.MainBackground)).Foreground(tcell.GetColor(config.Style.MainForeground))
+	config.StyleDefault = tcell.StyleDefault.Background(tcell.GetColor(config.Colors.MainBackground)).Foreground(tcell.GetColor(config.Colors.MainForeground))
 
 	return config
 }
 
 func (m *Model) ReloadConfig() {
-	m.Config.StyleDefault = m.Config.StyleDefault.Background(tcell.GetColor(m.Config.Style.MainBackground)).Foreground(tcell.GetColor(m.Config.Style.MainForeground))
+	m.Config.StyleDefault = m.Config.StyleDefault.Background(tcell.GetColor(m.Config.Colors.MainBackground)).Foreground(tcell.GetColor(m.Config.Colors.MainForeground))
 	m.Screen.SetStyle(m.Config.StyleDefault)
 }

+ 35 - 21
internal/editor/draw.go

@@ -49,7 +49,7 @@ func (m *Model) generateChordStr() string {
 
 func (m *Model) DrawPalette(rect layout.Rect) {
 	for col := 0; col < rect.Width; col++ {
-		m.Screen.SetContent(rect.X+col, rect.Y, ' ', nil, m.Config.StyleDefault.Background(tcell.GetColor(m.Config.Style.PaletteBarBackground)).Foreground(tcell.GetColor(m.Config.Style.PaletteBarForeground)))
+		m.Screen.SetContent(rect.X+col, rect.Y, ' ', nil, m.Config.StyleDefault.Background(tcell.GetColor(m.Config.Colors.PaletteBarBackground)).Foreground(tcell.GetColor(m.Config.Colors.PaletteBarForeground)))
 	}
 
 	modeStr := m.Mode.String()
@@ -62,7 +62,7 @@ func (m *Model) DrawPalette(rect layout.Rect) {
 			modeStr += " (replace)"
 		}
 	}
-	m.Screen.PutStrStyled(rect.Width-(len(modeStr)+1), rect.Y, strings.ToUpper(modeStr), m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Style.PaletteBarForeground)).Background(tcell.GetColor(m.Config.Style.PaletteBarBackground)))
+	m.Screen.PutStrStyled(rect.Width-(len(modeStr)+1), rect.Y, strings.ToUpper(modeStr), m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Colors.PaletteBarForeground)).Background(tcell.GetColor(m.Config.Colors.PaletteBarBackground)))
 
 	splitStr := ""
 	if m.LM.CurrentSplit == layout.SplitHorizontal {
@@ -70,28 +70,42 @@ func (m *Model) DrawPalette(rect layout.Rect) {
 	} else {
 		splitStr = "V"
 	}
-	m.Screen.PutStrStyled(rect.Width-(len(modeStr)+1)-5, rect.Y, splitStr, m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Style.PaletteBarForeground)).Background(tcell.GetColor(m.Config.Style.PaletteBarBackground)))
+	m.Screen.PutStrStyled(rect.Width-(len(modeStr)+1)-(m.Config.Properties.GutterWidth+1), rect.Y, splitStr, m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Colors.PaletteBarForeground)).Background(tcell.GetColor(m.Config.Colors.PaletteBarBackground)))
 
-	populatedWorkspaces := []string{strconv.Itoa(m.LM.ActiveIdx + 1)}
+	populatedWorkspaces := []int{m.LM.ActiveIdx + 1}
 	for workspaceIdx, workspace := range m.LM.Workspaces {
 		if workspaceIdx == m.LM.ActiveIdx {
 			continue
 		}
 
 		if !workspace.IsEmpty() {
-			populatedWorkspaces = append(populatedWorkspaces, strconv.Itoa(workspaceIdx+1))
+			populatedWorkspaces = append(populatedWorkspaces, workspaceIdx+1)
 		}
 	}
+
 	slices.Sort(populatedWorkspaces)
-	workspacesStr := strings.Join(populatedWorkspaces, " ")
-	m.Screen.PutStrStyled(1, rect.Y, workspacesStr, m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Style.WorkspaceForeground)).Background(tcell.GetColor(m.Config.Style.WorkspaceBackground)))
+	strWorkspaces := make([]string, len(populatedWorkspaces))
+
+	for i, v := range populatedWorkspaces {
+	    strWorkspaces[i] = strconv.Itoa(v)
+	}
+
+	workspacesStr := strings.Join(strWorkspaces, " ")
+
+	m.Screen.PutStrStyled(1, rect.Y, workspacesStr, m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Colors.WorkspaceForeground)).Background(tcell.GetColor(m.Config.Colors.WorkspaceBackground)))
+
+	for idx, workspace := range populatedWorkspaces {
+		if workspace == m.LM.ActiveIdx + 1 {
+			m.Screen.SetContent(idx * 2 + 1, rect.Y, '0' + rune(m.LM.ActiveIdx + 1), nil, m.Config.StyleDefault.Background(tcell.GetColor(m.Config.Colors.WorkspaceBackgroundActive)).Foreground(tcell.GetColor(m.Config.Colors.WorkspaceForegroundActive)))
+		}
+	}
 
 	chordStr := m.generateChordStr()
-	m.Screen.PutStrStyled(len(workspacesStr)+2, rect.Y, chordStr, m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Style.PaletteBarForeground)).Background(tcell.GetColor(m.Config.Style.PaletteBarBackground)))
-	m.Screen.PutStrStyled(len(chordStr)+1, rect.Y, m.DebugLog, m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Style.PaletteBarForeground)).Background(tcell.GetColor(m.Config.Style.PaletteInputBackground)))
+	m.Screen.PutStrStyled(len(workspacesStr)+2, rect.Y, chordStr, m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Colors.PaletteBarForeground)).Background(tcell.GetColor(m.Config.Colors.PaletteBarBackground)))
+	m.Screen.PutStrStyled(len(workspacesStr)+2+len(chordStr)+1, rect.Y, m.DebugLog, m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Colors.PaletteBarForeground)).Background(tcell.GetColor(m.Config.Colors.PaletteBarBackground)))
 
 	if m.Mode == ModePalette {
-		m.Screen.PutStrStyled(0, rect.Y+1, m.BM.PaletteBuffer.String(), m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Style.PaletteInputForeground)).Background(tcell.GetColor(m.Config.Style.PaletteInputBackground)))
+		m.Screen.PutStrStyled(0, rect.Y+1, m.BM.PaletteBuffer.String(), m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Colors.PaletteInputForeground)).Background(tcell.GetColor(m.Config.Colors.PaletteInputBackground)))
 
 		for _, cur := range m.BM.PaletteBuffer.CM.Cursors {
 			line, col := buffer.LineCol(&m.BM.PaletteBuffer, cur.Offset)
@@ -104,14 +118,14 @@ func (m *Model) DrawPalette(rect layout.Rect) {
 
 			ch := buffer.RuneAt(&m.BM.PaletteBuffer, cur.Offset)
 
-			m.Screen.SetContent(col, rect.Y+1, ch, nil, m.Config.StyleDefault.Background(tcell.GetColor(m.Config.Style.CursorColorWrite)))
+			m.Screen.SetContent(col, rect.Y+1, ch, nil, m.Config.StyleDefault.Background(tcell.GetColor(m.Config.Colors.CursorColorWrite)))
 		}
 	} else if strings.HasPrefix(m.BM.PaletteBuffer.String(), "moose.info:") {
-		m.Screen.PutStrStyled(0, rect.Y+1, string([]rune(m.BM.PaletteBuffer.String())[11:]), m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Style.InfoMsgForeground)).Background(tcell.GetColor(m.Config.Style.InfoMsgBackground)))
+		m.Screen.PutStrStyled(0, rect.Y+1, string([]rune(m.BM.PaletteBuffer.String())[11:]), m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Colors.InfoMsgForeground)).Background(tcell.GetColor(m.Config.Colors.InfoMsgBackground)))
 	} else if strings.HasPrefix(m.BM.PaletteBuffer.String(), "moose.warn:") {
-		m.Screen.PutStrStyled(0, rect.Y+1, string([]rune(m.BM.PaletteBuffer.String())[11:]), m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Style.WarnMsgForeground)).Background(tcell.GetColor(m.Config.Style.WarnMsgBackground)))
+		m.Screen.PutStrStyled(0, rect.Y+1, string([]rune(m.BM.PaletteBuffer.String())[11:]), m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Colors.WarnMsgForeground)).Background(tcell.GetColor(m.Config.Colors.WarnMsgBackground)))
 	} else if strings.HasPrefix(m.BM.PaletteBuffer.String(), "moose.error:") {
-		m.Screen.PutStrStyled(0, rect.Y+1, string([]rune(m.BM.PaletteBuffer.String())[12:]), m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Style.ErrorMsgForeground)).Background(tcell.GetColor(m.Config.Style.ErrorMsgBackground)))
+		m.Screen.PutStrStyled(0, rect.Y+1, string([]rune(m.BM.PaletteBuffer.String())[12:]), m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Colors.ErrorMsgForeground)).Background(tcell.GetColor(m.Config.Colors.ErrorMsgBackground)))
 	}
 }
 
@@ -185,13 +199,13 @@ func (m *Model) DrawContainerTabs(c *layout.ContainerBuffers, rect layout.Rect)
 	length := 0
 	for i, tab := range tabs {
 		if length+len(tab)+2 > rect.Width {
-			m.Screen.PutStrStyled(rect.X+length, rect.Y, ">", m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Style.TabForeground)).Background(tcell.GetColor(m.Config.Style.TabBackground)))
+			m.Screen.PutStrStyled(rect.X+length, rect.Y, ">", m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Colors.TabForeground)).Background(tcell.GetColor(m.Config.Colors.TabBackground)))
 			return
 		}
 
-		style := m.Config.StyleDefault.Background(tcell.GetColor(m.Config.Style.TabBackground)).Foreground(tcell.GetColor(m.Config.Style.TabForeground))
+		style := m.Config.StyleDefault.Background(tcell.GetColor(m.Config.Colors.TabBackground)).Foreground(tcell.GetColor(m.Config.Colors.TabForeground))
 		if i == activeTabIdx {
-			style = style.Foreground(tcell.GetColor(m.Config.Style.TabForegroundActive)).Background(tcell.GetColor(m.Config.Style.TabBackgroundActive))
+			style = style.Foreground(tcell.GetColor(m.Config.Colors.TabForegroundActive)).Background(tcell.GetColor(m.Config.Colors.TabBackgroundActive))
 		}
 
 		tabStr := strconv.Itoa(int(math.Abs(float64((activeTabIdx - i))))) + ": " + tab
@@ -232,13 +246,13 @@ func (m *Model) DrawBuffer(buf *buffer.Buffer, isActive bool, rect layout.Rect)
 
 		lineNum := j + buf.TopLine
 		relLine := lineNum - curLine
-		nums := fmt.Sprintf("%4d ", int(math.Abs(float64(relLine))))
+		nums := fmt.Sprintf("%*d ", m.Config.Properties.GutterWidth, int(math.Abs(float64(relLine))))
 		r := []rune(nums + expandTabs(line))
 		if len(r)+1 > rect.Width {
 			r = r[:rect.Width]
 		}
 
-		m.Screen.PutStrStyled(rect.X, rect.Y+j, string(r), m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Style.MainForeground)).Background(tcell.GetColor(m.Config.Style.MainBackground)))
+		m.Screen.PutStrStyled(rect.X, rect.Y+j, string(r), m.Config.StyleDefault.Foreground(tcell.GetColor(m.Config.Colors.MainForeground)).Background(tcell.GetColor(m.Config.Colors.MainBackground)))
 	}
 
 	if isActive {
@@ -257,9 +271,9 @@ func (m *Model) DrawBuffer(buf *buffer.Buffer, isActive bool, rect layout.Rect)
 			ch := buffer.RuneAt(buf, cur.Offset)
 
 			if m.Mode == ModeWrite {
-				m.Screen.SetContent(rect.X+visCol+5, rect.Y+screenLine, ch, nil, m.Config.StyleDefault.Background(tcell.GetColor(m.Config.Style.CursorColorWrite)))
+				m.Screen.SetContent(rect.X+visCol+m.Config.Properties.GutterWidth+1, rect.Y+screenLine, ch, nil, m.Config.StyleDefault.Background(tcell.GetColor(m.Config.Colors.CursorColorWrite)))
 			} else {
-				m.Screen.SetContent(rect.X+visCol+5, rect.Y+screenLine, ch, nil, m.Config.StyleDefault.Background(tcell.GetColor(m.Config.Style.CursorColor)))
+				m.Screen.SetContent(rect.X+visCol+m.Config.Properties.GutterWidth+1, rect.Y+screenLine, ch, nil, m.Config.StyleDefault.Background(tcell.GetColor(m.Config.Colors.CursorColor)))
 			}
 		}
 	}

+ 173 - 11
internal/extension/config.go

@@ -1,17 +1,179 @@
 package extension
 
 import (
-	lua "github.com/yuin/gopher-lua"
+    "fmt"
+    "reflect"
+    "strings"
+
+    "moose/internal/editor"
+
+    "github.com/creasty/defaults"
+    lua "github.com/yuin/gopher-lua"
 )
 
-func GetConfigTable(em *ExtensionManager) *lua.LTable {
-	config := em.L.NewTable()
-	em.L.SetFuncs(config, map[string]lua.LGFunction{
-		"set": func(L *lua.LState) int {
-			em.M.DebugLog += "hi from lua"
-			return 1
-		},
-	})
-
-	return config
+func snakeToCamel(s string) string {
+    parts := strings.Split(strings.ToLower(s), "_")
+    for i, part := range parts {
+        if part == "" {
+            continue
+        }
+        parts[i] = strings.ToUpper(part[:1]) + part[1:]
+    }
+    return strings.Join(parts, "")
+}
+
+func parseStructTable(dst any, table *lua.LTable) error {
+    if err := defaults.Set(dst); err != nil {
+        return err
+    }
+
+    val := reflect.ValueOf(dst)
+    if val.Kind() != reflect.Ptr || val.Elem().Kind() != reflect.Struct {
+        return fmt.Errorf("dst must be a pointer to struct")
+    }
+
+    val = val.Elem()
+    typ := val.Type()
+
+    for i := 0; i < val.NumField(); i++ {
+        fieldVal := val.Field(i)
+        fieldType := typ.Field(i)
+
+        luaValue := table.RawGetString(fieldType.Name)
+        if luaValue == lua.LNil {
+            continue
+        }
+
+        switch fieldVal.Kind() {
+        case reflect.String:
+            if v, ok := luaValue.(lua.LString); ok {
+                fieldVal.SetString(string(v))
+            }
+
+        case reflect.Bool:
+            if v, ok := luaValue.(lua.LBool); ok {
+                fieldVal.SetBool(bool(v))
+            }
+
+        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+            if v, ok := luaValue.(lua.LNumber); ok {
+                fieldVal.SetInt(int64(v))
+            }
+
+        case reflect.Float32, reflect.Float64:
+            if v, ok := luaValue.(lua.LNumber); ok {
+                fieldVal.SetFloat(float64(v))
+            }
+
+        case reflect.Struct:
+            if tbl, ok := luaValue.(*lua.LTable); ok {
+                nested := fieldVal.Addr().Interface()
+                if err := parseStructTable(nested, tbl); err != nil {
+                    return err
+                }
+            }
+        }
+    }
+
+    return nil
+}
+
+func parseColors(table *lua.LTable) (editor.Colors, error) {
+    var colors editor.Colors
+    err := parseStructTable(&colors, table)
+    return colors, err
 }
+
+func parseProperties(table *lua.LTable) (editor.Properties, error) {
+    var properties editor.Properties
+    err := parseStructTable(&properties, table)
+    return properties, err
+}
+
+func HandleSet(em *ExtensionManager, L *lua.LState) int {
+    key := L.CheckString(1)
+
+    switch key {
+    case "colors":
+        luaTable := L.CheckTable(2)
+        colors, err := parseColors(luaTable)
+        if err != nil {
+            L.RaiseError(err.Error())
+            return 0
+        }
+        em.M.Config.Colors = colors
+        em.M.ReloadConfig()
+        return 0
+
+    case "properties":
+        luaTable := L.CheckTable(2)
+        properties, err := parseProperties(luaTable)
+        if err != nil {
+            L.RaiseError(err.Error())
+            return 0
+        }
+        em.M.Config.Properties = properties
+        em.M.ReloadConfig()
+        return 0
+
+    default:
+        fieldName := snakeToCamel(key)
+        cfgVal := reflect.ValueOf(&em.M.Config).Elem()
+
+        propsVal := cfgVal.FieldByName("Properties")
+        if propsVal.IsValid() {
+            field := propsVal.FieldByName(fieldName)
+            if field.IsValid() && field.CanSet() {
+                value := L.CheckAny(2)
+
+                switch field.Kind() {
+                case reflect.String:
+                    if v, ok := value.(lua.LString); ok {
+                        field.SetString(string(v))
+                        em.M.ReloadConfig()
+                        return 0
+                    }
+
+                case reflect.Bool:
+                    if v, ok := value.(lua.LBool); ok {
+                        field.SetBool(bool(v))
+                        em.M.ReloadConfig()
+                        return 0
+                    }
+
+                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+                    if v, ok := value.(lua.LNumber); ok {
+                        field.SetInt(int64(v))
+                        em.M.ReloadConfig()
+                        return 0
+                    }
+
+                case reflect.Float32, reflect.Float64:
+                    if v, ok := value.(lua.LNumber); ok {
+                        field.SetFloat(float64(v))
+                        em.M.ReloadConfig()
+                        return 0
+                    }
+                }
+            }
+        }
+
+        L.RaiseError("unknown config key: %s", key)
+        return 0
+    }
+}
+
+func GetConfigTable(em *ExtensionManager) *lua.LTable {
+    config := em.L.NewTable()
+    em.L.SetFuncs(config, map[string]lua.LGFunction{
+        "set": func(L *lua.LState) int {
+            return HandleSet(em, L)
+        },
+        "reload": func(L *lua.LState) int {
+            em.M.ReloadConfig()
+            return 0
+        },
+    })
+
+    return config
+}

+ 33 - 0
internal/extension/lua/init.lua

@@ -1,4 +1,37 @@
 test = require("test")
 test.run()
 
+colors = {
+	MainBackground = "#0E142E",
+	MainForeground = "#dddddd",
+	LineNumberBackground = "#090603",
+	LineNumberForeground = "#dddddd",
+	CursorColor = "#777777",
+	CursorColorWrite = "#dddddd",
+	PaletteBarBackground = "#3b3b3b",
+	PaletteBarForeground = "#dddddd",
+	PaletteInputBackground = "#090603",
+	PaletteInputForeground = "#dddddd",
+	InfoMsgBackground = "#090603",
+	InfoMsgForeground = "#dddddd",
+	WarnMsgBackground = "#090603",
+	WarnMsgForeground = "#efc541",
+	ErrorMsgBackground = "#090603",
+	ErrorMsgForeground = "#ff5e56",
+	WorkspaceBackground = "#3b3b3b",
+	WorkspaceForeground = "#b9b9b9",
+	WorkspaceBackgroundActive = "#dddddd",
+	WorkspaceForegroundActive = "#3b3b3b",
+	TabBackground = "#3b3b3b",
+	TabForeground = "#b9b9b9",
+	TabBackgroundActive = "#3b3b3b",
+	TabForegroundActive = "#dddddd",
+}
+
+ms.config.set("properties", {
+    GutterWidth = 4,
+    TabSpaces = false,
+})
+ms.config.set("colors", colors)
+
 -- ms.config.set()