Skip to content

[FEATURE] - ADD LIST/TEXTEDIT FOR LISTS/ARRAYS #10

@patrick-hermann-sva

Description

@patrick-hermann-sva
package main

import (
	"fmt"
	"strings"

	"github.com/charmbracelet/bubbles/textinput"
	tea "github.com/charmbracelet/bubbletea"
	"github.com/charmbracelet/lipgloss"
)

type model struct {
	variables []variable
	index     int
	editing   bool
	input     textinput.Model
	addingNew bool
}

type variable struct {
	key   string
	value string
}

func initialModel() model {
	// Initialize with default variables
	defaultVars := []variable{
		{"manage_filesystem", "true"},
		{"update_packages", "true"},
		{"install_requirements", "true"},
		{"install_motd", "true"},
		{"username", "sthings"},
		{"lvm_home_sizing", "'15%'"},
		{"lvm_root_sizing", "'35%'"},
		{"lvm_var_sizing", "'50%'"},
		{"send_to_msteams", "true"},
		{"reboot_all", "false"},
	}

	input := textinput.New()
	input.Prompt = "> "
	input.Width = 50

	return model{
		variables: defaultVars,
		input:     input,
	}
}

func (m model) Init() tea.Cmd {
	return nil
}

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	var cmd tea.Cmd

	switch msg := msg.(type) {
	case tea.KeyMsg:
		switch msg.String() {
		case "ctrl+c", "esc":
			return m, tea.Quit
		case "enter":
			if m.editing {
				// Save edited value
				if m.addingNew {
					// Split input into key+-value
					parts := strings.Split(m.input.Value(), "+-")
					if len(parts) == 2 {
						m.variables = append(m.variables, variable{
							key:   parts[0],
							value: parts[1],
						})
					}
					m.addingNew = false
				} else {
					// Update existing value
					m.variables[m.index].value = m.input.Value()
				}
				m.editing = false
				m.input.Blur()
			} else {
				// Start editing
				m.editing = true
				if m.addingNew {
					m.input.SetValue("")
				} else {
					m.input.SetValue(m.variables[m.index].value)
				}
				m.input.Focus()
			}
		case "n":
			if !m.editing {
				m.addingNew = true
				m.editing = true
				m.input.SetValue("")
				m.input.Focus()
			}
		case "up":
			if m.index > 0 && !m.editing {
				m.index--
			}
		case "down":
			if m.index < len(m.variables)-1 && !m.editing {
				m.index++
			}
		case "backspace":
			if !m.editing && len(m.variables) > 0 {
				// Delete current line
				m.variables = append(m.variables[:m.index], m.variables[m.index+1:]...)
				if m.index >= len(m.variables) {
					m.index = len(m.variables) - 1
				}
			}
		}
	}

	if m.editing {
		m.input, cmd = m.input.Update(msg)
	}

	return m, cmd
}

func (m model) View() string {
	var sb strings.Builder

	// Title
	title := lipgloss.NewStyle().
		Bold(true).
		Foreground(lipgloss.Color("#FAFAFA")).
		Background(lipgloss.Color("#7D56F4")).
		Padding(0, 1).
		Render("Edit Ansible Variables (key+-value)")
	sb.WriteString(title + "\n\n")

	// Variables list
	for i, v := range m.variables {
		line := fmt.Sprintf("%s+-%s", v.key, v.value)

		if i == m.index {
			if m.editing && !m.addingNew {
				// Show input field for editing
				line = fmt.Sprintf("%s+-%s",
					lipgloss.NewStyle().Foreground(lipgloss.Color("#04B575")).Render(v.key),
					m.input.View(),
				)
			} else {
				// Highlight selected line
				line = lipgloss.NewStyle().
					Background(lipgloss.Color("#04B575")).
					Render(line)
			}
		}

		sb.WriteString(line + "\n")
	}

	// Adding new line
	if m.addingNew && m.editing {
		sb.WriteString("\nNew variable:\n")
		sb.WriteString(m.input.View() + "+-")
	}

	// Help text
	help := lipgloss.NewStyle().Faint(true).Render(`
↑/↓: Navigate  •  Enter: Edit/Save  •  n: Add New
Backspace: Delete  •  Esc: Exit
`)
	sb.WriteString("\n" + help)

	return sb.String()
}

func main() {
	p := tea.NewProgram(initialModel())
	if _, err := p.Run(); err != nil {
		fmt.Printf("Error: %v", err)
		return
	}
}

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions