devtui

package module
v0.0.81 Latest Latest
Warning

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

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

README

DevTUI

Project Badges

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

Features

  • Tab-based interface organization
  • Editable and non-editable fields
  • Keyboard navigation (Tab, Shift+Tab, Left/Right arrows)
  • Field validation and callbacks
  • Customizable styles and colors

devtui

Basic Usage

package main

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

func main() {
	// Configuration
	config := &devtui.TuiConfig{
		AppName:  "MyApp", 
		ExitChan: make(chan bool),
		Config: devtui.Config{
			ForeGround:"#F4F4F4",
			Background:"#000000",
			Highlight: "#FF6600",
			Lowlight:  "#666666",
		},
		LogToFile: func(messageErr any) {
			// Implement your logging logic here
		},
	}

	// Create new TUI instance
	tui := devtui.NewTUI(config)

	// Create and add custom tabs (recommended way)
	mainTab := tui.NewTabSection("Main", "")
	mainTab.AddFields(
		*devtui.NewField(
			"Username",
			"",
			true,
			func(newValue any) (string, error) {
				strValue := newValue.(string)
				if len(strValue) < 5 {
					return "", fmt.Errorf("username must be at least 5 characters")
				}
				return "Username updated to " + strValue, nil
			},
		),
	)
	tui.AddTabSections(mainTab)

	// Start the TUI
	if err := tui.Start(); err != nil {
		panic(err)
	}
}

Keyboard Shortcuts

Key Action
Tab Switch to next tab
Shift+Tab Switch to previous tab
Left/Right Navigate between fields in current tab
Enter Edit field or execute action
Esc Cancel editing
Ctrl+C Quit application

NewTabSection Method

// NewTabSection creates a new TabSection with the given title and footer
// Example:

	tab := tui.NewTabSection("BUILD", "Press 't' to compile")
	// Preferred way to add fields (variadic parameters)
	tab.AddFields(
		*NewField(
			"Username",
			"",
			true,
			func(newValue any) (string, error) {
				strValue := newValue.(string)
				if len(strValue) < 5 {
					return "", fmt.Errorf("username must be at least 5 characters")
				}
				return "Username updated to " + strValue, nil
			},
		),
		*NewField(
			"Password",
			"",
			true,
			func(newValue any) (string, error) {
				strValue := newValue.(string)
				if len(strValue) < 8 {
					return "", fmt.Errorf("password must be at least 8 characters")
				}
				return "Password updated", nil
			},
		),
	)


//	 Get/Set title and footer
	currentTitle := tab.Title()
	tab.SetTitle("New Title")

	currentFooter := tab.Footer() 
	tab.SetFooter("New Footer")

Field Types

Editable Fields with Different Data Types
String Field
*NewField(
	"Username", 
	"defaultUser", 
	true, 
	func(value any) (string, error) {
		strValue := value.(string)
		if len(strValue) < 3 {
			return "", fmt.Errorf("username must be at least 3 characters")
		}
		return "Username updated to " + strValue, nil
	},
)
Numeric Field (Port)
*NewField(
	"Server Port", 
	"8080", 
	true, 
	func(value any) (string, error) {
		switch v := value.(type) {
		case string:
			if port, err := strconv.Atoi(v); err == nil && port > 0 && port < 65536 {
				return fmt.Sprintf("Port changed to %d", port), nil
			}
			return "", fmt.Errorf("invalid port number: %s", v)
		case int:
			if v > 0 && v < 65536 {
				return fmt.Sprintf("Port changed to %d", v), nil
			}
			return "", fmt.Errorf("port out of range: %d", v)
		default:
			return "", fmt.Errorf("unsupported type for port: %T", v)
		}
	},
)
Boolean Field
*NewField(
	"Debug Mode", 
	"false", 
	true, 
	func(value any) (string, error) {
		switch v := value.(type) {
		case bool:
			return fmt.Sprintf("Debug mode set to %t", v), nil
		case string:
			if b, err := strconv.ParseBool(v); err == nil {
				return fmt.Sprintf("Debug mode set to %t", b), nil
			}
			return "", fmt.Errorf("invalid boolean value: %s", v)
		default:
			return "", fmt.Errorf("unsupported type for boolean: %T", v)
		}
	},
)
Non-Editable Fields (Action Buttons)
*NewField(
	"Action Button", 
	"Click me", 
	false, 
	func(value any) (string, error) {
		// Execute action - value parameter is ignored for non-editable fields
		return "Action executed successfully", nil
	},
)

errors

  • al borrar todo un campo editable, al comenzar a escribir se copia el valor anterior al lado del cursor

Dependencies

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 DefaultTUIForTest added in v0.0.10

func DefaultTUIForTest(LogToFile func(messageErr any)) *DevTUI

NewDefaultTUI creates a DevTUI instance with basic default configuration useful for unit tests and for quick initialization in real applications

func NewTUI

func NewTUI(c *TuiConfig) *DevTUI

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) InitTUI added in v0.0.5

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

InitTUI initializes and runs the terminal UI application.

It accepts optional variadic arguments of any type. If a *sync.WaitGroup is provided among these arguments, InitTUI 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) 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 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) 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 Field added in v0.0.44

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

use NewField to create a new field in the tab section Field represents a field in the TUI with a name, value, and editable state.

func NewField added in v0.0.44

func NewField(name, value string, editable bool, changeFunc func(newValue any) (string, error)) *Field

NewField creates and returns a new Field instance.

Parameters:

  • name: The name of the field.
  • value: The initial value of the field.
  • editable: A boolean indicating whether the field is editable.
  • changeFunc: A callback function that is invoked when the field's value changes. It receives the new value as any type and returns an execution message and an error, if any.

Returns: - A pointer to the newly created Field instance.

Example usage:

// String field
field := NewField("username", "defaultUser", true, func(newValue any) (string, error) {
    strValue := newValue.(string)
    if len(strValue) == 0 {
        return "", errors.New("value cannot be empty")
    }
    return "Username updated to " + strValue, nil
})

// Numeric field
portField := NewField("port", "8080", true, func(newValue any) (string, error) {
    switch v := newValue.(type) {
    case string:
        if port, err := strconv.Atoi(v); err == nil && port > 0 && port < 65536 {
            return fmt.Sprintf("Port changed to %d", port), nil
        }
        return "", errors.New("invalid port number")
    case int:
        if v > 0 && v < 65536 {
            return fmt.Sprintf("Port changed to %d", v), nil
        }
        return "", errors.New("port out of range")
    default:
        return "", errors.New("unsupported type")
    }
})

// Boolean field
enabledField := NewField("enabled", "false", true, func(newValue any) (string, error) {
    switch v := newValue.(type) {
    case bool:
        return fmt.Sprintf("Enabled set to %t", v), nil
    case string:
        if b, err := strconv.ParseBool(v); err == nil {
            return fmt.Sprintf("Enabled set to %t", b), nil
        }
        return "", errors.New("invalid boolean value")
    default:
        return "", errors.New("unsupported type")
    }
})

func (*Field) Editable added in v0.0.44

func (f *Field) Editable() bool

func (*Field) Name added in v0.0.44

func (f *Field) Name() string

func (*Field) SetCursorAtEnd added in v0.0.44

func (f *Field) SetCursorAtEnd()

func (*Field) SetEditable added in v0.0.44

func (f *Field) SetEditable(editable bool)

func (*Field) SetName added in v0.0.44

func (f *Field) SetName(name string)

func (*Field) SetValue added in v0.0.44

func (f *Field) SetValue(value string)

func (*Field) Value added in v0.0.44

func (f *Field) Value() string

type TabSection

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

TabSection represents a tab section in the TUI with configurable fields and content

func (*TabSection) AddFields added in v0.0.44

func (ts *TabSection) AddFields(fields ...Field)

AddFields adds one or more Field handlers to the section This is the preferred method for adding fields in normal usage

func (*TabSection) FieldHandlers added in v0.0.7

func (ts *TabSection) FieldHandlers() []Field

FieldHandlers returns the field handlers slice

func (*TabSection) Footer added in v0.0.44

func (ts *TabSection) Footer() string

Footer returns the tab section footer text

func (*TabSection) SetFieldHandlers added in v0.0.44

func (ts *TabSection) SetFieldHandlers(handlers []Field)

SetFieldHandlers sets the field handlers slice (mainly for testing)

func (*TabSection) SetFooter added in v0.0.44

func (ts *TabSection) SetFooter(footer string)

SetFooter sets the tab section footer text

func (*TabSection) SetTitle added in v0.0.44

func (ts *TabSection) SetTitle(title string)

SetTitle sets the tab section title

func (*TabSection) Title

func (ts *TabSection) Title() string

Title returns the tab section title

func (*TabSection) Write added in v0.0.4

func (ts *TabSection) Write(p []byte) (n int, err error)

Write implementa io.Writer para capturar la salida de otros procesos

type TuiConfig

type TuiConfig struct {
	AppName       string    // app name eg: "MyApp"
	TabIndexStart int       // is the index of the tab section to start
	ExitChan      chan bool //  global chan to close app
	Color         *ColorStyle

	LogToFile func(messageErr any) // function to write log error
}

Directories

Path Synopsis
cmd
test-timestamps command

Jump to

Keyboard shortcuts

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