devtui

package module
v0.0.116 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 23, 2025 License: MIT Imports: 17 Imported by: 0

README

DevTUI

Project Badges

Interactive Terminal User Interface library for Go applications development (principal tui in GoDEV App)

devtui

Quick Start

DevTUI uses specialized handler interfaces that require minimal implementation (1-3 methods vs 8 in previous versions). Choose the handler type that matches your use case:

package main

import (
    "fmt"
    "time"
    "sync"
    "github.com/cdvelop/devtui"
)

// EditHandler - For interactive input fields (3 methods)
type HostHandler struct {
    currentHost string
}

func (h *HostHandler) Label() string { return "Host Configuration" }
func (h *HostHandler) Value() string { return h.currentHost }
func (h *HostHandler) Change(newValue any, progress ...func(string)) error {
    h.currentHost = newValue.(string)
    
    // Success message via progress callback
    if len(progress) > 0 {
        progress[0]("Host configured successfully: " + h.currentHost)
    }
    return nil
}

// ExecutionHandler - For action buttons (2 methods)
type DeployHandler struct{}

func (d *DeployHandler) Label() string { return "Deploy to Production" }
func (d *DeployHandler) Execute(progress ...func(string)) error {
    if len(progress) > 0 {
        progress[0]("Starting deployment...")
        // Deployment logic here
        progress[0]("Deployment completed successfully")
    }
    return nil
}

// DisplayHandler - For read-only information (2 methods)
type HelpHandler struct{}

func (h *HelpHandler) Label() string { return "DevTUI Help" }
func (h *HelpHandler) Content() string { 
    return "Navigation:\n• Tab/Shift+Tab: Switch tabs\n• Left/Right: Navigate fields\n• Enter: Edit/Execute" 
}

// WriterBasic - For simple logging (1 method)
type LogWriter struct{}

func (w *LogWriter) Name() string { return "ApplicationLog" }

func main() {
    tui := devtui.NewTUI(&devtui.TuiConfig{
        AppName: "MyApp",
        ExitChan: make(chan bool),
    })
    
    // Method chaining with optional timeout configuration
    tab := tui.NewTabSection("Server", "Configuration")
    tab.NewEditHandler(&HostHandler{currentHost: "localhost"}).WithTimeout(5*time.Second)
    tab.NewRunHandler(&DeployHandler{}).WithTimeout(30*time.Second)
    tab.NewDisplayHandler(&HelpHandler{}).Register()
    
    // Writer registration
    writer := tab.NewWriterHandler(&LogWriter{}).Register()
    writer.Write([]byte("Application started"))

    var wg sync.WaitGroup
    wg.Add(1)
    go tui.Start(&wg)
    wg.Wait()
}

New Specialized Interfaces

EditHandler - Interactive Input Fields
type EditHandler interface {
    Label() string // Field label (e.g., "Server Port", "Host Configuration") 
    Value() string // Current/initial value (e.g., "8080", "localhost")
    Change(newValue any, progress ...func(string)) error
}
ExecutionHandler - Action Buttons
type ExecutionHandler interface {
    Label() string // Button label (e.g., "Deploy to Production", "Build Project")
    Execute(progress ...func(string)) error
}
DisplayHandler - Read-only Information
type DisplayHandler interface {
    Label() string   // Display label (e.g., "Help", "Status")
    Content() string // Display content (e.g., "help\n1-..\n2-...", "executing deploy wait...")
}
WriterBasic - Simple Logging
type WriterBasic interface {
    Name() string // Writer identifier (e.g., "webBuilder", "ApplicationLog")
}
WriterTracker - Advanced Logging with Message Updates
type WriterTracker interface {
    Name() string
    MessageTracker
}

type MessageTracker interface {
    GetLastOperationID() string
    SetLastOperationID(id string)
}

Method Chaining API

Timeout Configuration
// Synchronous execution (default)
tab.NewEditHandler(handler).Register()           // timeout = 0
tab.NewEditHandler(handler)                      // Auto-register, timeout = 0

// Asynchronous execution with timeout
tab.NewEditHandler(handler).WithTimeout(5*time.Second)        // 5 seconds
tab.NewEditHandler(handler).WithTimeout(100*time.Millisecond) // 100ms (ideal for tests)
tab.NewRunHandler(deployHandler).WithTimeout(30*time.Second)  // 30 seconds for deployment
Writer Registration
// Basic writer (always creates new lines)
writer := tab.NewWriterHandler(&LogWriter{}).Register()
writer.Write([]byte("Log message"))

// Advanced writer with message tracking
writer := tab.NewWriterHandler(&BuildLogWriter{}).Register()
writer.Write([]byte("Build started"))      // Creates new message
writer.Write([]byte("Build completed"))    // Updates existing message

Key Improvements Over Previous Version

Feature Old API New API Improvement
Methods Required 8 methods (FieldHandler + WritingHandler) 1-3 methods 60-85% reduction
Interface Complexity Single complex interface Specialized interfaces Much more intuitive
Boilerplate Code High (7-8 methods for simple use cases) Minimal (1-3 methods) ~75% less code
API Clarity Mixed responsibilities Clear separation by purpose Self-documenting
Timeout Config Manual in each handler Method chaining Cleaner configuration

Usage Examples

Complete Server Management Example
// Edit handlers for configuration
type PortHandler struct{ port string }
func (p *PortHandler) Label() string { return "Server Port" }
func (p *PortHandler) Value() string { return p.port }
func (p *PortHandler) Change(newValue any, progress ...func(string)) error {
    p.port = newValue.(string)
    if len(progress) > 0 {
        progress[0]("Port updated: " + p.port)
    }
    return nil
}

// Action handlers
type StartServerHandler struct{}
func (s *StartServerHandler) Label() string { return "Start Server" }
func (s *StartServerHandler) Execute(progress ...func(string)) error {
    if len(progress) > 0 {
        progress[0]("Starting server...")
        time.Sleep(2*time.Second)
        progress[0]("Server started successfully")
    }
    return nil
}

// Display handlers for status
type StatusHandler struct{}
func (s *StatusHandler) Label() string { return "Server Status" }
func (s *StatusHandler) Content() string { return "Status: Running\nPID: 12345\nUptime: 2h 30m" }

// Usage
tui := devtui.NewTUI(&devtui.TuiConfig{AppName: "ServerManager", ExitChan: make(chan bool)})
tab := tui.NewTabSection("Server", "Management")

tab.NewEditHandler(&PortHandler{port: "8080"}).WithTimeout(2*time.Second)
tab.NewRunHandler(&StartServerHandler{}).WithTimeout(10*time.Second) 
tab.NewDisplayHandler(&StatusHandler{}).Register()

// Writer for logs
logWriter := tab.NewWriterHandler(&ServerLogWriter{}).Register()
logWriter.Write([]byte("Server management initialized"))

Progress Callback Usage

All handlers receive optional progress callbacks for real-time feedback:

func (h *DeployHandler) Execute(progress ...func(string)) error {
    if len(progress) > 0 {
        progressCallback := progress[0]
        
        progressCallback("Initiating deployment...")
        time.Sleep(500 * time.Millisecond)
        
        progressCallback("Uploading files...")
        time.Sleep(1 * time.Second)
        
        progressCallback("Restarting services...")
        time.Sleep(500 * time.Millisecond)
        
        progressCallback("Deployment completed successfully")
    }
    
    return nil
}

Each progress call updates the same message line, providing smooth real-time feedback.

Navigation

  • Tab/Shift+Tab: Switch between tabs
  • Left/Right: Navigate fields within tab
  • Enter: Edit/Execute
  • Esc: Cancel edit
  • Ctrl+C: Exit

Migration from v1.x

The new API is a complete redesign. See Migration Guide for upgrading existing code.

Documentation

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ColorStyle

type ColorStyle struct {
	Foreground string // eg: #F4F4F4
	Background string // eg: #000000
	Highlight  string // eg: #FF6600
	Lowlight   string // eg: #666666
}

type DevTUI

type DevTUI struct {
	*TuiConfig
	// contains filtered or unexported fields
}

DevTUI mantiene el estado de la aplicación

func NewTUI

func NewTUI(c *TuiConfig) *DevTUI

NewTUI creates a new DevTUI instance and initializes it.

Usage Example:

config := &TuiConfig{
    AppName: "MyApp",
    TabIndexStart: 0,
    ExitChan: make(chan bool),
    Color: nil, // or your *ColorStyle
    LogToFile: func(err any) { fmt.Println(err) },
}
tui := NewTUI(config)

// Configure your sections and fields:
tui.NewTabSection("My Section", "Description").
	NewField("Field1", "value", true, nil)

// Start the TUI:
var wg sync.WaitGroup
wg.Add(1)
go tui.Run(&wg)
wg.Wait()

func (*DevTUI) AddTabSections added in v0.0.9

func (t *DevTUI) AddTabSections(sections ...*tabSection) *DevTUI

AddTabSections adds one or more tabSections to the DevTUI If a tab with title "DEFAULT" exists, it will be replaced by the first tab section Deprecated: Use NewTabSection and append to tabSections directly

func (*DevTUI) ContentView

func (h *DevTUI) ContentView() string

ContentView renderiza los mensajes para una sección de contenido

func (*DevTUI) GetTotalTabSections added in v0.0.9

func (t *DevTUI) GetTotalTabSections() int

GetTotalTabSections returns the total number of tab sections

func (*DevTUI) HandleKeyboard added in v0.0.10

func (h *DevTUI) HandleKeyboard(msg tea.KeyMsg) (bool, tea.Cmd)

HandleKeyboard processes keyboard input and updates the model state returns whether the update function should continue processing or return early

func (*DevTUI) Init

func (h *DevTUI) Init() tea.Cmd

Init initializes the terminal UI application.

func (*DevTUI) NewTabSection added in v0.0.43

func (t *DevTUI) NewTabSection(title, footer string) *tabSection

NewTabSection creates and initializes a new tabSection with the given title and footer NewTabSection creates a new tab section and automatically adds it to the TUI

Example:

tab := tui.NewTabSection("BUILD", "Press enter to compile")

func (*DevTUI) Print

func (h *DevTUI) Print(messages ...any)

Print sends a normal Label or error to the tui in current tab

func (*DevTUI) ReturnFocus

func (t *DevTUI) ReturnFocus() error

func (*DevTUI) Start added in v0.0.93

func (h *DevTUI) Start(args ...any)

Start initializes and runs the terminal UI application.

It accepts optional variadic arguments of any type. If a *sync.WaitGroup is provided among these arguments, Start will call its Done() method before returning.

The method runs the UI using the internal tea engine, and handles any errors that may occur during execution. If an error occurs, it will be displayed on the console and the application will wait for user input before exiting.

Parameters:

  • args ...any: Optional arguments. Can include a *sync.WaitGroup for synchronization.

func (*DevTUI) Update

func (h *DevTUI) Update(msg tea.Msg) (tea.Model, tea.Cmd)

Update maneja las actualizaciones del estado

func (*DevTUI) View

func (h *DevTUI) View() string

type DisplayHandler added in v0.0.116

type DisplayHandler interface {
	Label() string   // Display label (e.g., "Help", "Status")
	Content() string // Display content (e.g., "help\n1-..\n2-...", "executing deploy wait...")
}

DisplayHandler defines the interface for read-only information display handlers. These handlers show static or dynamic content without user interaction.

type EditHandler added in v0.0.116

type EditHandler interface {
	Label() string // Field label (e.g., "Server Port", "Host Configuration")
	Value() string // Current/initial value (e.g., "8080", "localhost")
	Change(newValue any, progress ...func(string)) error
}

EditHandler defines the interface for interactive fields that accept user input. These handlers allow users to modify values through text input.

type EditHandlerTracker added in v0.0.116

type EditHandlerTracker interface {
	EditHandler
	MessageTracker
}

EditHandlerTracker combines EditHandler with MessageTracker for advanced edit handlers that need message tracking capabilities.

type ExecutionHandler added in v0.0.116

type ExecutionHandler interface {
	Label() string // Button label (e.g., "Deploy to Production", "Build Project")
	Execute(progress ...func(string)) error
}

ExecutionHandler defines the interface for action buttons that execute operations. These handlers trigger business logic when activated by the user.

type FieldHandler added in v0.0.7

type FieldHandler interface {
	Label() string                                                 // Field label (e.g., "Server Port")
	Value() string                                                 // Current field value (e.g., "8080")
	Editable() bool                                                // Whether field is editable or action button
	Change(newValue any, progress ...func(string)) (string, error) // Handler with optional progress callback
	Timeout() time.Duration                                        // Return 0 for no timeout, or specific duration

	// NEW: WritingHandler methods (REQUIRED for all handlers)
	WritingHandler
}

FieldHandler interface defines the contract for field handlers This replaces the individual parameters approach with a unified interface Internal fieldHandler interface for backward compatibility (DEPRECATED - Use specialized handlers) Users should use DisplayHandler, EditHandler, ExecutionHandler instead

type MessageTracker added in v0.0.116

type MessageTracker interface {
	GetLastOperationID() string
	SetLastOperationID(id string)
}

MessageTracker provides optional interface for message tracking control. Handlers can implement this to control message updates and operation tracking.

type ShortcutsHandler added in v0.0.96

type ShortcutsHandler struct {
	// contains filtered or unexported fields
}

ShortcutsHandler - Shows keyboard navigation instructions

func NewShortcutsHandler added in v0.0.96

func NewShortcutsHandler() *ShortcutsHandler

func (*ShortcutsHandler) Change added in v0.0.96

func (h *ShortcutsHandler) Change(newValue any, progress ...func(string)) (string, error)

func (*ShortcutsHandler) Editable added in v0.0.96

func (h *ShortcutsHandler) Editable() bool

func (*ShortcutsHandler) GetLastOperationID added in v0.0.103

func (h *ShortcutsHandler) GetLastOperationID() string

func (*ShortcutsHandler) Label added in v0.0.96

func (h *ShortcutsHandler) Label() string

func (*ShortcutsHandler) Name added in v0.0.103

func (h *ShortcutsHandler) Name() string

WritingHandler methods

func (*ShortcutsHandler) SetLastOperationID added in v0.0.103

func (h *ShortcutsHandler) SetLastOperationID(lastOpID string)

func (*ShortcutsHandler) Timeout added in v0.0.96

func (h *ShortcutsHandler) Timeout() time.Duration

func (*ShortcutsHandler) Value added in v0.0.96

func (h *ShortcutsHandler) Value() string

type TuiConfig

type TuiConfig struct {
	AppName       string    // app name eg: "MyApp"
	TabIndexStart int       // is the index of the tab section to start default 0
	ExitChan      chan bool //  global chan to close app eg: make(chan bool)
	/*// *ColorStyle style for the TUI
	  // if nil it will use default style:
	type ColorStyle struct {
	 Foreground string // eg: #F4F4F4
	 Background string // eg: #000000
	 Highlight  string // eg: #FF6600
	 Lowlight   string // eg: #666666
	}*/
	Color *ColorStyle

	LogToFile func(messages ...any) // function to write log error
	TestMode  bool                  // only used in tests to enable synchronous behavior
}

type WriterBasic added in v0.0.116

type WriterBasic interface {
	Name() string // Writer identifier (e.g., "webBuilder", "ApplicationLog")
}

WriterBasic defines the interface for basic writers that create new lines for each write. These writers are suitable for simple logging or output display.

type WriterTracker added in v0.0.116

type WriterTracker interface {
	Name() string
	MessageTracker
}

WriterTracker defines the interface for advanced writers that can update existing lines. These writers support message tracking and can modify previously written content.

type WritingHandler added in v0.0.103

type WritingHandler interface {
	Name() string                       // Handler identifier (e.g., "TinyWasm", "MainServer")
	SetLastOperationID(lastOpID string) // DevTUI calls this after processing each message
	GetLastOperationID() string         // Handler returns ID for message updates, "" for new messages
}

Internal writingHandler interface for message tracking (DEPRECATED) Users should use WriterBasic, WriterTracker instead

Directories

Path Synopsis
example
demo command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL