gum

package module
v0.0.0-...-3d605fc Latest Latest
Warning

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

Go to latest
Published: May 10, 2025 License: MIT Imports: 21 Imported by: 1

README

🎨 gum - Starlark Module for Terminal User Interfaces

A powerful Starlark module for building Terminal User Interfaces (TUI), inspired by charmbracelet/gum, huh, and bubbletea. Create beautiful, interactive command-line interfaces in your Starlark scripts.

Features

  • Text Input: Single and multi-line text inputs with validation
  • Selection: Single and multi-option selection components
  • Confirmation: Yes/No prompts with customizable text
  • File Picking: Navigate and select files and directories
  • Visual Elements: Spinners, notes, and colorized text output
  • Theming Support: Multiple built-in themes (Charm, Dracula, Catppuccin, etc.)
  • Customization: Configure width, height, timeouts, and more

Installation

go get github.com/starpkg/gum

Quick Start

package main

import (
    "fmt"
    "github.com/1set/starlet"
    "github.com/starpkg/gum"
)

func main() {
    // Create a new gum module with default settings
    gumModule := gum.NewModule()
    
    // Create a Starlet interpreter with the module
    interpreter := starlet.New(
        starlet.WithModuleLoader("gum", gumModule.LoadModule()),
    )
    
    // Run a Starlark script with TUI components
    script := `
load("gum", "input", "select", "confirm")

# Get user input
name = input(
    title = "What's your name?",
    placeholder = "Enter your name"
)

# Select a favorite color
color = select(
    options = ["Red", "Green", "Blue", "Yellow"],
    title = "Choose your favorite color:"
)

# Confirm the choices
confirmed = confirm(
    title = "Is this information correct?",
    description = "Name: " + name + "\nColor: " + color
)

print("Confirmed:", confirmed)
`
    
    // Execute the script
    if err := interpreter.ExecScript("example.star", script); err != nil {
        fmt.Println("Error:", err)
    }
}

Configuration

The gum module has the following configuration options:

  • width: Default width for TUI components (default: 50)
  • height: Default height for components (default: 0 - automatic)
  • theme: Theme name to use (default: "charm")

Available themes:

  • base: Minimal, monochrome theme
  • base16: Simple 16-color theme
  • charm: Default Charm theme
  • dracula: Dracula color scheme
  • catppuccin: Catppuccin color scheme
Module Configuration
// Method 1: With default settings
module := gum.NewModule()

// Method 2: With custom settings
module := gum.NewModuleWithConfig(
    80,               // Width
    10,               // Height
    "dracula",        // Theme
)

Starlark API

Text Input Functions
input(value?, prompt?, placeholder?, title?, description?, char_limit?, suggestions?, password?, validate?, width?, inline?, show_help?, timeout?)

Creates a single-line text input field.

Parameters:

  • value: Initial value (default: "")
  • prompt: Input prompt (default: "> ")
  • placeholder: Placeholder text (default: "Type something...")
  • title: Title text (default: "")
  • description: Description text (default: "")
  • char_limit: Maximum character limit (default: 0 - no limit)
  • suggestions: List of autocomplete suggestions (default: [])
  • password: Boolean for password input or None for no echo (default: False)
  • validate: Validation function (default: None)
  • width: Component width (default: configured width)
  • inline: Display in inline mode (default: False)
  • show_help: Show help text (default: True)
  • timeout: Timeout in seconds (default: 0 - no timeout)

Returns the entered text as a string.

write(value?, placeholder?, title?, description?, char_limit?, validate?, editor?, width?, height?, show_line?, show_help?, timeout?)

Creates a multi-line text area.

Parameters:

  • value: Initial value (default: "")
  • placeholder: Placeholder text (default: "Write something...")
  • title: Title text (default: "")
  • description: Description text (default: "")
  • char_limit: Maximum character limit (default: 0 - no limit)
  • validate: Validation function (default: None)
  • editor: External editor command string (e.g., "vim") or list (e.g., ["code", "--wait"]) (default: uses $EDITOR or "nano")
  • width: Component width (default: configured width)
  • height: Component height (default: 5)
  • show_line: Show line numbers (default: False)
  • show_help: Show help text (default: True)
  • timeout: Timeout in seconds (default: 0 - no timeout)

Returns the entered text as a string.

Selection Functions
select(options, value?, title?, description?, validate?, width?, height?, inline?, show_filter?, show_help?, timeout?)

Creates a single-selection component.

Parameters:

  • options: List or dictionary of options
  • value: Initial selected value (default: "")
  • title: Title text (default: "Choose:")
  • description: Description text (default: "")
  • validate: Validation function (default: None)
  • width: Component width (default: configured width)
  • height: Maximum visible items (default: 0 - all)
  • inline: Display in inline mode (default: False)
  • show_filter: Enable filtering (default: False)
  • show_help: Show help text (default: True)
  • timeout: Timeout in seconds (default: 0 - no timeout)

Returns the selected value as a string.

multi_select(options, value?, title?, description?, validate?, limit?, width?, height?, show_filter?, show_help?, timeout?)

Creates a multi-selection component.

Parameters:

  • options: List or dictionary of options
  • value: List of initially selected values (default: [])
  • title: Title text (default: "Choose:")
  • description: Description text (default: "")
  • validate: Validation function (default: None)
  • limit: Maximum number of selections (default: 0 - no limit)
  • width: Component width (default: configured width)
  • height: Maximum visible items (default: 0 - all)
  • show_filter: Enable filtering (default: False)
  • show_help: Show help text (default: True)
  • timeout: Timeout in seconds (default: 0 - no timeout)

Returns a list of selected values.

confirm(value?, title?, description?, yes?, no?, inline?, show_help?, timeout?)

Creates a yes/no confirmation dialog.

Parameters:

  • value: Initial value (default: False)
  • title: Title text (default: "Are you sure?")
  • description: Description text (default: "")
  • yes: Text for affirmative option (default: "Yes")
  • no: Text for negative option (default: "No")
  • inline: Display in inline mode (default: False)
  • show_help: Show help text (default: True)
  • timeout: Timeout in seconds (default: 0 - no timeout)

Returns a boolean value if the user makes a selection, or None if the operation is cancelled or times out.

File Picker
file_pick(path?, title?, description?, validate?, allow_ext?, allow_dir?, allow_file?, show_hidden?, show_perm?, show_size?, height?, show_help?, timeout?)

Creates a file picker component.

Parameters:

  • path: Initial path to start in (default: ".")
  • title: Title text (default: "")
  • description: Description text (default: "")
  • validate: Validation function (default: None)
  • allow_ext: Allowed file extensions as string or list of strings (default: [])
  • allow_dir: Allow directory selection (default: False)
  • allow_file: Allow file selection (default: True)
  • show_hidden: Show hidden files (default: False)
  • show_perm: Show file permissions (default: True)
  • show_size: Show file size (default: False)
  • height: Maximum visible items (default: 10)
  • show_help: Show help text (default: True)
  • timeout: Timeout in seconds (default: 0 - no timeout)

Returns the selected file path as a string.

Visual Elements
note(title, description?, height?, next?, show_help?, timeout?)

Displays a note with a title and description.

Parameters:

  • title: Title text (required)
  • description: Description text (default: "")
  • height: Component height (default: 0 - automatic)
  • next: Text for next button (default: "" - no button)
  • show_help: Show help text (default: True)
  • timeout: Timeout in seconds (default: 0 - no timeout)

Returns None.

md(text, style?, width?, emoji?, word_wrap?)

Renders Markdown content into beautifully formatted terminal text.

Parameters:

  • text: Markdown text to render (required)
  • style: Style to use for rendering (default: "auto")
    • Available styles from glamour package:
      • "auto": Automatically detect terminal background
      • "ascii": Plain ASCII style
      • "dark": Dark theme
      • "dracula": Dracula theme
      • "light": Light theme
      • "notty": No TTY style
      • "pink": Pink theme
      • Custom style file path (path to a JSON file)
  • width: Width to wrap the text at (default: 0 - uses module configuration)
  • emoji: Enable emoji support (default: True)
  • word_wrap: Enable word wrapping (default: True)

Returns the rendered markdown as a string with ANSI escape codes for formatting.

Example:

load("gum", "md", "note")

md_text = """
# Hello World

This is **bold** and *italic* text.

* List item 1
* List item 2

> A blockquote
"""
# Render markdown to a string
rendered_md = md(
    text = md_text,
    style = "dark"
)

# Use the rendered markdown in a note
note(
    title = "Documentation Example",
    description = rendered_md,
    next = "Continue"
)

# Or print it directly
print(rendered_md)
md_note(text, title?, style?, width?, height?, emoji?, word_wrap?, show_help?, next?, timeout?)

Renders Markdown content and displays it in a TUI note.

Parameters:

  • text: Markdown text to render (required)
  • title: Title for the markdown display (default: "")
  • style: Style to use for rendering (default: "auto")
    • Available styles: "auto", "dark", "light", "notty", or path to a custom style JSON file
    • "auto" will detect the terminal's background color
  • width: Width to wrap the text at (default: 0 - uses module configuration)
  • height: Height of the note component (default: 0 - uses module configuration)
  • emoji: Enable emoji support (default: True)
  • word_wrap: Enable word wrapping (default: True)
  • show_help: Show help text (default: False)
  • next: Text for next button (default: "" - no next button)
  • timeout: Timeout in seconds (default: 0 - no timeout)

Displays rendered markdown as a note and returns None.

Example:

load("gum", "md_note")

md_text = """
# Hello World

This is **bold** and *italic* text.

* List item 1
* List item 2

> A blockquote
"""
# Display markdown with a title
md_note(
    text = md_text,
    title = "Documentation Example",
    style = "dark",
    show_help = True,
    next = "Continue"
)
spin(title?, style?, action?, timeout?)

Displays a spinner with optional action function.

Parameters:

  • title: Spinner title (default: "Loading...")
  • style: Spinner style (default: "dots")
  • action: Function to execute while spinner is active (default: None)
  • timeout: Timeout in seconds when no action is provided (default: 1)

Returns the result of the action function or None.

Available spinner styles: "line", "dots", "mini_dot", "jump", "points", "pulse", "globe", "moon", "monkey", "meter", "hamburger", "ellipsis"

colorize(text, color?, pattern?, render?, from_color?, to_color?)

Colorizes text with gradients or solid colors.

Parameters:

  • text: Text to colorize (required)
  • color: Solid color name or hex code (default: "" - use pattern)
  • pattern: Color pattern for gradient (default: "CherryBlossoms")
  • render: Render type ("Column" or "Line") (default: "Column")
  • from_color: Custom gradient start color as hex code (e.g., "#FF5733") (default: "" - use pattern)
  • to_color: Custom gradient end color as hex code (e.g., "#33FF57") (default: "" - use pattern)

Returns the colorized text.

Available patterns: "Almost", "Anamnisar", "AnimalCrossing", "BrokenHearts", "CherryBlossoms", "EveningNight", "IbizaSunset", "MiWatch", "Nelson", "OceanSand", "PurpleLove", "RainbowBlue", "RoseWater"

Example with custom gradient:

load("gum", "colorize")

# Colorize text with a custom gradient
custom_gradient = colorize(
    text = "Hello, Starlark!",
    from_color = "#FF5733",  # Orange-red
    to_color = "#33FF57",    # Green
    render = "Column"        # Gradient direction
)
print(custom_gradient)

Examples

Basic Input and Confirmation
load("gum", "input", "confirm", "colorize")

# Get user input with validation
def validate_name(name):
    if len(name) < 3:
        return "Name must be at least 3 characters long"
    return None

name = input(
    title = "Welcome!",
    description = "Please enter your name",
    placeholder = "John Doe",
    validate = validate_name,
)

if name != None:
    # Colorize output
    welcome_text = colorize("Hello, " + name + "!", pattern="RainbowBlue")
    print(welcome_text)
    
    # Confirm action
    if confirm(
        title = "Would you like to continue?",
        description = "This will start the process",
        yes = "Let's go!",
        no = "Not now",
    ):
        print("Starting process...")
    else:
        print("Maybe next time!")
External Editor Usage
load("gum", "write", "set_editor")

# Set the editor to Vim
set_editor(["vim"])

# Using default editor of the module
notes = write(
    title = "Meeting Notes",
    description = "Press Ctrl+E to open in your default editor",
)

# Specifying a specific editor - VSCode
vscode_notes = write(
    title = "VSCode Notes",
    description = "Press Ctrl+E to open in VSCode",
    editor = ["code", "--wait"]
)

# Simple vim editor
vim_notes = write(
    title = "Vim Notes",
    description = "Press Ctrl+E to open in Vim",
    editor = "vim"
)

print("Notes recorded:", len(notes) if notes else 0, "characters")
Selection and Multi-selection
load("gum", "select", "multi_select", "note")

# Single selection from a list
color = select(
    options = ["Red", "Green", "Blue", "Yellow", "Purple"],
    title = "Choose your favorite color:",
    description = "This will be used for your profile",
    show_filter = True,
)

# Multi-selection from a dictionary
selected_fruits = multi_select(
    options = {
        "apple": "Apple 🍎",
        "banana": "Banana 🍌",
        "orange": "Orange 🍊", 
        "grape": "Grape 🍇",
        "watermelon": "Watermelon 🍉"
    },
    value=["Grape 🍇", "Orange 🍊"],
    title = "Select your favorite fruits:",
    limit = 3,
)

# Display results
if color and selected_fruits:
    fruits_str = ", ".join(selected_fruits)
    note(
        title = "Your Selections",
        description = "Color: " + color + "\nFruits: " + fruits_str,
        next = "Continue",
    )
File Picker and Spinner
load("gum", "file_pick", "spin")

# Pick a file
selected_file = file_pick(
    title = "Select a configuration file:",
    allow_ext = ["json"],
    show_hidden = False,
)

if selected_file:
    # Function to process the file
    def process_file():
        # Simulate processing
        sleep(2)
        return "File processed successfully!"
    
    # Show spinner while processing
    result = spin(
        title = "Processing " + selected_file,
        style = "dots",
        action = process_file,
    )
    
    print(result)

License

This package is licensed under the MIT License - see the LICENSE file for details.

Documentation

Overview

Package gum provides a Starlark module for TUI, inspired charmbracelet/gum, huh and bubbletea. The module supports various configuration options including: - width: Default width for components (0 for terminal width) - height: Default height for components - theme: Theme name to use (base, base16, charm, dracula, catppuccin) - editor: Default editor command for multi-line input (e.g. ["vim", "-f"])

Package gum provides a Starlark module for TUI, inspired charmbracelet/gum, huh and bubbletea.

Index

Constants

View Source
const (
	// ModuleName defines the module name.
	ModuleName = "gum"
)

Variables

View Source
var (
	// ColorApricot is a predefined color, it's a light orange color similar to the color of an apricot fruit, having the RGB values #FBCEB1
	ColorApricot = color.RGBA{R: 0xFB, G: 0xCE, B: 0xB1, A: 0xFF}
	// ColorBeige is a predefined color, which is a very pale yellowish-brown color, having the RGB values #F5F5DC
	ColorBeige = color.RGBA{R: 0xF5, G: 0xF5, B: 0xDC, A: 0xFF}
	// ColorBlack is a predefined color, which absorbs all light in the visible wavelengths, having the RGB values #000000
	ColorBlack = color.RGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xFF}
	// ColorBlue is a predefined color, which is one of the primary additive colors, having the RGB values #0000FF
	ColorBlue = color.RGBA{R: 0x00, G: 0x00, B: 0xFF, A: 0xFF}
	// ColorBronze is a predefined color, it resembles the color of the metal bronze, having the RGB values #CD7F32
	ColorBronze = color.RGBA{R: 0xCD, G: 0x7F, B: 0x32, A: 0xFF}
	// ColorBrown is a predefined color, which is a composite color produced by mixing red, yellow, and black, having the RGB values #A52A2A
	ColorBrown = color.RGBA{R: 0xA5, G: 0x2A, B: 0x2A, A: 0xFF}
	// ColorCyan is a predefined color (a.k.a. Aqua), which is a greenish-blue color, having the RGB values #00FFFF
	ColorCyan = color.RGBA{R: 0x00, G: 0xFF, B: 0xFF, A: 0xFF}
	// ColorGold is a predefined color, which resembles the metal gold, having the RGB values #FFD700
	ColorGold = color.RGBA{R: 0xFF, G: 0xD7, B: 0x00, A: 0xFF}
	// ColorGray is a predefined color (a.k.a. Grey), which is an intermediate color between black and white, having the RGB values #808080
	ColorGray = color.RGBA{R: 0x80, G: 0x80, B: 0x80, A: 0xFF}
	// ColorGreen is a predefined color, which is one of the primary additive colors, having the RGB values #00FF00
	ColorGreen = color.RGBA{R: 0x00, G: 0xFF, B: 0x00, A: 0xFF}
	// ColorIndigo is a predefined color, which is a mix of blue and violet, having the RGB values #4B0082
	ColorIndigo = color.RGBA{R: 0x4B, G: 0x00, B: 0x82, A: 0xFF}
	// ColorLavender is a predefined color, it's a light purple color similar to lavender flowers, having the RGB values #E6E6FA
	ColorLavender = color.RGBA{R: 0xE6, G: 0xE6, B: 0xFA, A: 0xFF}
	// ColorLime is a predefined color, which is a fluorescent green, having the RGB values #00FF00
	ColorLime = color.RGBA{R: 0x00, G: 0x80, B: 0x00, A: 0xFF}
	// ColorMagenta is a predefined color (a.k.a. Fuchsia), which is a mix of red and blue, having the RGB values #FF00FF
	ColorMagenta = color.RGBA{R: 0xFF, G: 0x00, B: 0xFF, A: 0xFF}
	// ColorMaroon is a predefined color, which is a dark brownish red color, having the RGB values #800000
	ColorMaroon = color.RGBA{R: 0x80, G: 0x00, B: 0x00, A: 0xFF}
	// ColorMint is a predefined color, which is a pale greenish-blue color, having the RGB values #16982B
	ColorMint = color.RGBA{R: 0x16, G: 0x98, B: 0x2B, A: 0xFF}
	// ColorNavy is a predefined color, which is a very dark shade of blue, having the RGB values #000080
	ColorNavy = color.RGBA{R: 0x00, G: 0x00, B: 0x80, A: 0xFF}
	// ColorOlive is a predefined color, which resembles unripe green olives, having the RGB values #808000
	ColorOlive = color.RGBA{R: 0x80, G: 0x80, B: 0x00, A: 0xFF}
	// ColorOrange is a predefined color, which is between red and yellow, having the RGB values #FFA500
	ColorOrange = color.RGBA{R: 0xFF, G: 0xA5, B: 0x00, A: 0xFF}
	// ColorPeach is a predefined color, it's similar to the color of a peach fruit, having the RGB values #FFE5B4
	ColorPeach = color.RGBA{R: 0xFF, G: 0xE5, B: 0xB4, A: 0xFF}
	// ColorPink is a predefined color, which is a pale red color, having the RGB values #FFC0CB
	ColorPink = color.RGBA{R: 0xFF, G: 0xC0, B: 0xCB, A: 0xFF}
	// ColorPlum is a predefined color, it's a dark purple color similar to the color of a plum fruit, having the RGB values #8E4585
	ColorPlum = color.RGBA{R: 0x8E, G: 0x45, B: 0x85, A: 0xFF}
	// ColorPurple is a predefined color, which is a mix of red and blue, having the RGB values #800080
	ColorPurple = color.RGBA{R: 0x80, G: 0x00, B: 0x80, A: 0xFF}
	// ColorRed is a predefined color, which is one of the primary additive colors, having the RGB values #FF0000
	ColorRed = color.RGBA{R: 0xFF, G: 0x00, B: 0x00, A: 0xFF}
	// ColorScarlet is a predefined color, which is a bright red color with a slightly orange tinge, having the RGB values #FF2400
	ColorScarlet = color.RGBA{R: 0xFF, G: 0x24, B: 0x00, A: 0xFF}
	// ColorSilver is a predefined color, which resembles gray metallic silver, having the RGB values #C0C0C0
	ColorSilver = color.RGBA{R: 0xC0, G: 0xC0, B: 0xC0, A: 0xFF}
	// ColorTeal is a predefined color, which is a dark cyan color, having the RGB values #008080
	ColorTeal = color.RGBA{R: 0x00, G: 0x80, B: 0x80, A: 0xFF}
	// ColorViolet is a predefined color, which is a mix of blue and red, having the RGB values #8000FF
	ColorViolet = color.RGBA{R: 0x80, G: 0x00, B: 0xFF, A: 0xFF}
	// ColorWhite is a predefined color, which reflects all visible wavelengths of light, having the RGB values #FFFFFF
	ColorWhite = color.RGBA{R: 0xFF, G: 0xFF, B: 0xFF, A: 0xFF}
	// ColorYellow is a predefined color, which is one of the primary subtractive colors, having the RGB values #FFFF00
	ColorYellow = color.RGBA{R: 0xFF, G: 0xFF, B: 0x00, A: 0xFF}

	// RainbowColors is a predefined color palette, which contains the 7 colors of the rainbow.
	RainbowColors = []color.Color{ColorRed, ColorOrange, ColorYellow, ColorGreen, ColorCyan, ColorBlue, ColorViolet}
)

Functions

func ParseColor

func ParseColor(query string) (color.Color, error)

ParseColor parses the case-insensitive unstructured description of color and returns the corresponding color.Color.

Types

type Module

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

Module wraps the ConfigurableModule with specific functionality for TUI components.

func NewModule

func NewModule() *Module

NewModule creates a new instance of Module with default configurations. The default configurations include: - width: 50 (0 for terminal width) - height: 0 - theme: "charm" - editor: [] (empty list, no default editor)

func NewModuleWithConfig

func NewModuleWithConfig(width, height int, themeName string, editor []string) *Module

NewModuleWithConfig creates a new instance of Module with the given configuration values. Parameters: - width: Default width for components (0 for terminal width) - height: Default height for components - themeName: Theme name to use (base, base16, charm, dracula, catppuccin) - editor: Default editor command for multi-line input (e.g. ["vim", "-f"])

func (*Module) LoadModule

func (m *Module) LoadModule() starlet.ModuleLoader

LoadModule returns the Starlark module loader with the gum-specific functions.

Jump to

Keyboard shortcuts

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