diff --git a/cmd/gim/main.go b/cmd/gim/main.go index 770f00e..49763c8 100644 --- a/cmd/gim/main.go +++ b/cmd/gim/main.go @@ -17,10 +17,8 @@ func generateLines(n int) []string { } func main() { - - // lines := []string{"Hello world testing main.go", "line 2", "line 3", "line 4", "line 5"} tea.NewProgram( - editor.NewModel(generateLines(32), action.Position{Line: 0, Col: 0}), + editor.NewModel(generateLines(64), action.Position{Line: 0, Col: 0}), tea.WithAltScreen(), ).Run() } diff --git a/internal/action/action.go b/internal/action/action.go index 829652c..d431c97 100644 --- a/internal/action/action.go +++ b/internal/action/action.go @@ -16,6 +16,31 @@ const ( VisualBlockMode ) +func (m Mode) ToString() string { + switch m { + case NormalMode: + return "NORMAL" + case InsertMode: + return "INSERT" + case CommandMode: + return "COMMAND" + case VisualMode: + return "VISUAL" + case VisualLineMode: + return "V-LINE" + case VisualBlockMode: + return "V-BLOCK" + default: + return "-----" + } +} + +func (m Mode) IsVisualMode() bool { + return m == VisualMode || + m == VisualLineMode || + m == VisualBlockMode +} + // Model defines the interface for editor state that actions can modify type Model interface { // Text buffer @@ -53,7 +78,6 @@ type Model interface { // Mode Mode() Mode SetMode(mode Mode) - IsVisualMode() bool // Insert recording (for count replay) SetInsertRecording(count int, action Action) diff --git a/internal/editor/model.go b/internal/editor/model.go index 36eb7c9..6d2089e 100644 --- a/internal/editor/model.go +++ b/internal/editor/model.go @@ -190,12 +190,6 @@ func (m *Model) SetMode(mode action.Mode) { m.mode = mode } -func (m *Model) IsVisualMode() bool { - return m.mode == action.VisualMode || - m.mode == action.VisualLineMode || - m.mode == action.VisualBlockMode -} - func (m *Model) SetInsertRecording(count int, act action.Action) { m.insertCount = count m.insertKeys = []string{} diff --git a/internal/editor/view.go b/internal/editor/view.go index 9a1be5b..8bfc756 100644 --- a/internal/editor/view.go +++ b/internal/editor/view.go @@ -110,15 +110,15 @@ func (m Model) View() string { view.WriteString(m.cursorStyle().Render(" ")) } } else if x < len(runes) { - if m.IsVisualMode() && posIsAnchor(m, x, i) { + if m.Mode().IsVisualMode() && posIsAnchor(m, x, i) { view.WriteString(m.visualAnchorStyle().Render(string(runes[x]))) - } else if m.IsVisualMode() && posInsideSelection(m, x, i) { + } else if m.Mode().IsVisualMode() && posInsideSelection(m, x, i) { view.WriteString(m.visualHighlightStyle().Render(string(runes[x]))) } else { view.WriteRune(runes[x]) } // To highlight blank lines when in visual mode - } else if m.IsVisualMode() && posInsideSelection(m, x, i) { + } else if m.Mode().IsVisualMode() && posInsideSelection(m, x, i) { view.WriteString(m.visualHighlightStyle().Render(" ")) } } @@ -135,34 +135,42 @@ func (m Model) View() string { view.WriteString("\n") } - // Draw status bar - var modeString string - switch m.Mode() { - case action.NormalMode: - modeString = "NORMAL" - case action.InsertMode: - modeString = "INSERT" - case action.CommandMode: - modeString = "COMMAND" - case action.VisualMode: - modeString = "VISUAL" - case action.VisualLineMode: - modeString = "V-LINE" - case action.VisualBlockMode: - modeString = "V-BLOCK" - } - - // DEBUG BAR! Def not the final bar - var bar string - if m.Mode() == action.CommandMode { - bar = fmt.Sprintf(" %6s | %d:%d (%d:%d) :%s ", modeString, m.cursor.x, m.cursor.y, m.win_w, m.win_h, m.command) - } else if m.IsVisualMode() { - bar = fmt.Sprintf(" %6s | %d:%d (%d:%d) <%d, %d> ", modeString, m.cursor.x, m.cursor.y, m.win_w, m.win_h, m.AnchorX(), m.AnchorY()) - } else { - bar = fmt.Sprintf(" %6s | %d:%d (%d:%d) | %s | %+v | %d", modeString, m.cursor.x, m.cursor.y, m.win_w, m.win_h, m.input.Pending(), m.insertKeys, m.insertCount) - } - + bar := drawStatusBar(m) view.WriteString(bar) return view.String() } + +func drawStatusBar(m Model) string { + left := leftBar(m) + right := rightBar(m) + + diff := m.win_w - (len(left) + len(right)) + + // This happens when the terminal spawns + if diff <= 0 { + return "" + } + + middle := strings.Repeat(" ", diff) + return left + middle + right +} + +func leftBar(m Model) (bar string) { + if m.Mode() == action.CommandMode { + bar = fmt.Sprintf(":%s", m.command) + } else { + bar = fmt.Sprintf(" %s", m.Mode().ToString()) + } + return +} + +func rightBar(m Model) (bar string) { + if m.Mode().IsVisualMode() { + lineCount := max(m.AnchorY(), m.CursorY()) - min(m.AnchorY(), m.CursorY()) + 1 + bar = fmt.Sprintf("%d:%d <%d>", m.CursorY(), m.CursorX(), lineCount) + } else { + bar = fmt.Sprintf("%d:%d ", m.CursorY(), m.CursorX()) + } + return +} diff --git a/internal/input/handler.go b/internal/input/handler.go index d223e93..7c436c7 100644 --- a/internal/input/handler.go +++ b/internal/input/handler.go @@ -139,7 +139,7 @@ func (h *Handler) handleInitial(m action.Model, kind string, binding any, key st case "operator": op := binding.(action.Operator) // In visual mode, the selection is already defined — operate immediately - if m.IsVisualMode() { + if m.Mode().IsVisualMode() { start, end := normalizeVisualSelection(m) // Visual line mode is linewise, others are charwise mtype := action.Charwise