Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(v2) Generic model #1298

Open
wants to merge 27 commits into
base: v2-exp
Choose a base branch
from
Open

(v2) Generic model #1298

wants to merge 27 commits into from

Conversation

aymanbagabas
Copy link
Member

@aymanbagabas aymanbagabas commented Jan 27, 2025

This proposal removes all program options and, instead, define them directly on the Program struct. This also changes the API and implement this proposal #1136

type Program[T any] struct {
	Input  io.Reader
	Output io.Writer
	Env    []string
	Init   func() (T, Cmd)
	Filter func(T, Msg) Msg
	Update func(T, Msg) (T, Cmd)
	View   func(T) Frame
	Model T

	// DontCatchPanics is a flag that determines whether or not the program should
	// catch panics.
	DontCatchPanics bool

	// IgnoreSignals is a flag that determines whether or not the program should
	// ignore signals.
	IgnoreSignals bool

	// FPS is the frames per second we should set on the renderer, if
	// applicable,
	FPS int

	// Profile is the color profile of the terminal. Use [Profile] to set it.
	Profile colorprofile.Profile // the terminal color profile
}

@aymanbagabas aymanbagabas force-pushed the v2-generics branch 2 times, most recently from e9aea7c to 95b0498 Compare January 27, 2025 17:48
@aymanbagabas aymanbagabas marked this pull request as ready for review January 27, 2025 20:02
@aymanbagabas aymanbagabas force-pushed the v2-generics branch 3 times, most recently from 1deae97 to a69f856 Compare January 28, 2025 21:47
aymanbagabas added a commit to charmbracelet/bubbles that referenced this pull request Jan 29, 2025
@aymanbagabas
Copy link
Member Author

Here's an example of rewriting the cursor-style example using this API

package main

import (
	"fmt"
	"os"

	tea "github.com/charmbracelet/bubbletea/v2"
)

type model struct {
	shape tea.CursorShape
	blink bool
}

func (m model) describeCursor() string {
	var adj, noun string

	if m.blink {
		adj = "blinking"
	} else {
		adj = "steady"
	}

	switch m.shape {
	case tea.CursorBlock:
		noun = "block"
	case tea.CursorUnderline:
		noun = "underline"
	case tea.CursorBar:
		noun = "bar"
	}

	return fmt.Sprintf("%s %s", adj, noun)
}

func initialModel() (model, tea.Cmd) {
	m := model{blink: true}
	return m, nil
}

func updateModel(m model, msg tea.Msg) (model, tea.Cmd) {
	switch msg := msg.(type) {
	case tea.KeyPressMsg:
		switch msg.String() {
		case "ctrl+q", "q":
			return m, tea.Quit
		case "h", "left":
			if m.shape == tea.CursorBlock && m.blink {
				break
			}
			if m.blink {
				m.shape--
			}
			m.blink = !m.blink
		case "l", "right":
			if m.shape == tea.CursorBar && !m.blink {
				break
			}
			if !m.blink {
				m.shape++
			}
			m.blink = !m.blink
		}
	}
	return m, nil
}

func viewModel(m model) fmt.Stringer {
	f := tea.NewFrame("Press left/right to change the cursor style, q or ctrl+c to quit." +
		"\n\n" +
		"  <- This is the cursor (a " + m.describeCursor() + ")")
	f.Cursor = tea.NewCursor(0, 2)
	f.Cursor.Shape = m.shape
	f.Cursor.Blink = m.blink
	return f
}

func main() {
	p := tea.Program[model]{
		Init:   initialModel,
		Update: updateModel,
		View:   viewModel,
	}
	if err := p.Run(); err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v", err)
		os.Exit(1)
	}
}

aymanbagabas added a commit to charmbracelet/bubbles that referenced this pull request Jan 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants