Prechádzať zdrojové kódy

more work on layout sysatem

Johan Rong 1 mesiac pred
rodič
commit
18c9c090e3

+ 2 - 2
Makefile

@@ -3,7 +3,7 @@ BUILD_DIR=build
 MODULE_PATH=./cmd/moose/
 
 VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
-LDFLAGS=-s -w -X main.Version=$(VERSION) -buildid=
+LDFLAGS=-s -w -X moose/internal/about.Version=$(VERSION) -buildid=
 
 .PHONY: build release run clean
 
@@ -16,7 +16,7 @@ release:
 	CGO_ENABLED=0 go build -trimpath -buildvcs=false -ldflags="$(LDFLAGS)" -o "$(BUILD_DIR)/$(BINARY_NAME)" $(MODULE_PATH)
 
 run:
-	go run $(MODULE_PATH) 
+	go run -ldflags="$(LDFLAGS)" $(MODULE_PATH)
 
 clean:
 	rm -rf $(BUILD_DIR)

+ 7 - 17
cmd/moose/main.go

@@ -9,11 +9,7 @@ import (
 	"golang.design/x/clipboard"
 )
 
-var Version = "dev"
-
 func main() {
-	fmt.Println("[moose] version " + Version)
-
 	s, err := tcell.NewScreen()
 	if err != nil {
 		fmt.Printf("[moose-error] %v", err)
@@ -26,7 +22,8 @@ func main() {
 
 	err = clipboard.Init()
 	if err != nil {
-		panic(err)
+		fmt.Printf("[moose-error] %v", err)
+		os.Exit(1)
 	}
 
 	style := tcell.StyleDefault.Background(color.Reset).Foreground(color.Reset)
@@ -49,10 +46,6 @@ func main() {
 
 	isPasting := false
 
-	s.Clear()
-	m.Render()
-	s.Show()
-
 	for {
 		if m.ShouldQuit {
 			return
@@ -63,9 +56,6 @@ func main() {
 		switch ev := ev.(type) {
 		case *tcell.EventResize:
 			s.Sync()
-			s.Clear()
-			m.Render()
-			s.Show()
 		case *tcell.EventPaste:
 			if ev.Start() {
 				isPasting = true
@@ -75,12 +65,12 @@ func main() {
 		case *tcell.EventKey:
 			if !isPasting {
 				m.HandleKeyInput(ev)
-				
-				s.Clear()
-				m.Render()
-				s.Show()
 			}
 		}
-	}
 
+		s.Clear()
+		//m.Render()
+		m.Draw()
+		s.Show()
+	}
 }

+ 3 - 0
internal/about/about.go

@@ -0,0 +1,3 @@
+package about
+
+var Version = "dev"

+ 8 - 0
internal/editor/action.go

@@ -9,6 +9,7 @@ import(
 	"golang.design/x/clipboard"
 	"moose/internal/buffer"
 	"moose/internal/util"
+	"moose/internal/about"
 )
 
 type ActionManager = struct {
@@ -54,6 +55,13 @@ func DefaultActionManager() ActionManager {
 	return ActionManager{
 		CM:	     NewChordManager(),
 		Common:  []Action{
+			Action{
+				Commands: []string{"version"},
+				Callback: func(m *Model, args []string) {
+					m.BM.PaletteBuffer.Clear()
+					m.BM.PaletteBuffer.Insert("moose.info:Moose version '" + about.Version + "'")
+				},
+			},
 			Action{
 				Bindings: []Binding{
 					Binding{

+ 71 - 4
internal/editor/draw.go

@@ -2,16 +2,83 @@ package editor
 
 import (
 	"moose/internal/layout"
+	"moose/internal/buffer"
+	"fmt"
+	"strings"
+	"github.com/gdamore/tcell/v3/color"
 )
 
-func (m *Model) DrawLayout(lm *layout.LayoutManager, rect layout.Rect) {
-
+func (m *Model) Draw() {
+	m.DrawWorkspace(&m.LM.Workspaces[m.LM.ActiveIdx], layout.RectFromScren(m.Screen))
 }
 
 func (m *Model) DrawWorkspace(w *layout.Workspace, rect layout.Rect) {
-
+	m.DrawContainer(&w.RootContainer, rect)
 }
 
-func (m *Model) DrawContainer(c *layout.Container[[]int], rect layout.Rect) {
+func (m *Model) DrawContainer(c *layout.Container[layout.ContainerBuffers], rect layout.Rect) {
+	length := len(c.Children)
+	rect = layout.RectDivide(rect, c.Split, length)
+
+	for i, child := range c.Children {
+		switch child.(type) {
+		case layout.ContainerBuffers: {
+			cb := child.(layout.ContainerBuffers)
+			m.DrawContainerBuffers(&cb, layout.RectDisplace(rect, c.Split, i))
+		}
+		case layout.Container[layout.ContainerBuffers]: {
+			c := child.(layout.Container[layout.ContainerBuffers])
+			m.DrawContainer(&c, layout.RectDisplace(rect, c.Split, i))
+		}
+		}
+	}
+}
 
+func (m *Model) DrawContainerBuffers(c *layout.ContainerBuffers, rect layout.Rect) {
+	m.DrawBuffer(&m.BM.Buffers[c.Buffers[c.ActiveIdx]], c.Buffers[c.ActiveIdx] == m.BM.CurrentIdx, rect)
 }
+
+func (m *Model) DrawBuffer(buf *buffer.Buffer, isActive bool, rect layout.Rect) {
+	primary := buf.CM.Cursors[buf.CM.PrimaryIdx]
+	curLine, _ := buffer.LineCol(buf, primary.Offset)
+	buf.ScrollToShow(curLine, rect.Height)
+
+	startOffset := buffer.OffsetForLine(buf, buf.TopLine)
+	endOffset := buf.Rope.Len()
+	if endLine := buf.TopLine + rect.Height; endLine < buffer.LineCount(buf) {
+		endOffset = buffer.OffsetForLine(buf, endLine)
+	}
+
+	visible := string(buf.Rope.Slice(startOffset, endOffset))
+	table := strings.SplitAfter(visible, "\n")
+	for j, line := range table {
+		if j + 1 > rect.Height { break }
+
+		nums := fmt.Sprintf("%4d ", j + buf.TopLine)
+		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.Style)
+	}
+
+	if isActive {
+		for _, cur := range buf.CM.Cursors {
+			line, col := buffer.LineCol(buf, cur.Offset)
+			screenLine := line - buf.TopLine
+			if screenLine < 0 || screenLine + 1 > rect.Height { continue }
+
+			visCol := visualCol(buffer.LineText(buf, line), col)
+			if visCol + 1 > rect.Width { continue }
+
+			ch := buffer.RuneAt(buf, cur.Offset)
+
+			if m.Mode == ModeWrite {
+				m.Screen.SetContent(rect.X + visCol + 5, rect.Y + screenLine, ch, nil, m.Style.Reverse(true))
+			} else {
+				m.Screen.SetContent(rect.X + visCol + 5, rect.Y + screenLine, ch, nil, m.Style.Reverse(true).Foreground(color.Gray))	
+			}
+		}
+	}
+}

+ 2 - 2
internal/editor/model.go

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

+ 78 - 14
internal/layout/layout.go

@@ -1,10 +1,60 @@
 package layout
 
+import (
+	"github.com/gdamore/tcell/v3"
+)
+
 type Rect struct {
-	x      int
-	y      int
-	width  int
-	height int
+	X      int
+	Y      int
+	Width  int
+	Height int
+}
+
+func RectDivide(rect Rect, split SplitType, num int) Rect {
+	switch split {
+	case SplitHorizontal: return Rect{
+		X: rect.X,
+		Y: rect.Y,
+		Width: rect.Width / num,
+		Height: rect.Height,
+	}
+	case SplitVertical: return Rect{
+		X: rect.X,
+		Y: rect.Y,
+		Width: rect.Width,
+		Height: rect.Height / num,
+	}
+	default: panic("[moose-error] impossible split type")
+	}
+}
+
+func RectDisplace(rect Rect, split SplitType, idx int) Rect {
+	switch split {
+	case SplitHorizontal: return Rect{
+		X: rect.X + (rect.Width * idx),
+		Y: rect.Y,
+		Width: rect.Width,
+		Height: rect.Height,
+	}
+	case SplitVertical: return Rect{
+		X: rect.X,
+		Y: rect.Y + (rect.Height * idx),
+		Width: rect.Width,
+		Height: rect.Height,
+	}
+	default: panic("[moose-error] impossible split type")
+	}
+}
+
+func RectFromScren(s tcell.Screen) Rect {
+	sWidth, sHeight := s.Size()
+	return Rect{
+		X: 0,
+		Y: 0,
+		Width: sWidth,
+		Height: sHeight,
+	}
 }
 
 type LayoutManager struct {
@@ -13,7 +63,7 @@ type LayoutManager struct {
 }
 
 type Workspace struct {
-	RootContainer Container[[]int]
+	RootContainer Container[ContainerBuffers]
 }
 
 type SplitType int
@@ -23,13 +73,18 @@ const (
 )
 
 type ContainerNode interface {
-	[]int | Container[[]int]
+	ContainerBuffers | Container[ContainerBuffers]
+}
+
+type ContainerBuffers struct {
+	Buffers   []int
+	ActiveIdx int
 }
 
 type Container[T ContainerNode] struct {
-	Children 	 [2]any
-	Split  		 SplitType
-	ActiveBuffer *int
+	Children 	   [2]any
+	Split  		   SplitType
+	ActiveChildIdx int
 }
 
 func NewLayoutManager() LayoutManager {
@@ -44,10 +99,19 @@ func NewWorkspace() Workspace {
 	}
 }
 
-func NewContainerEmpty() Container[[]int] {
-	return Container[[]int]{
-		Children: 	  [2]any{},
-		Split:	  	  SplitHorizontal,
-		ActiveBuffer: nil,
+func NewContainerEmpty() Container[ContainerBuffers] {
+	return Container[ContainerBuffers]{
+		Children: 	    [2]any{
+			ContainerBuffers{
+				Buffers: []int{0},
+				ActiveIdx: 0,
+			},
+			ContainerBuffers{
+				Buffers: []int{1},
+				ActiveIdx: 0,
+			},
+		},
+		Split:	  	    SplitVertical,
+		ActiveChildIdx: 0,
 	}
 }