simpleinput

package
v0.0.0-...-6c7df26 Latest Latest
Warning

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

Go to latest
Published: Feb 19, 2025 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package simpleinput provides an implementation of the input.Input interface. It should be used for basic cases without the need for structured or cli-style input

Example
package main

import (
	"fmt"
	"os"
	"strconv"

	prompt "github.com/aschey/bubbleprompt"
	"github.com/aschey/bubbleprompt/completer"
	"github.com/aschey/bubbleprompt/executor"
	"github.com/aschey/bubbleprompt/input/simpleinput"
	"github.com/aschey/bubbleprompt/suggestion"
	tea "github.com/charmbracelet/bubbletea"
	"github.com/charmbracelet/lipgloss"
)

type model struct {
	suggestions []suggestion.Suggestion[any]
	textInput   *simpleinput.Model[any]
	outputStyle lipgloss.Style
	numChoices  int64
	filterer    completer.Filterer[any]
}

func (m model) Complete(promptModel prompt.Model[any]) ([]suggestion.Suggestion[any], error) {
	if len(m.textInput.Tokens()) > 1 {
		return nil, nil
	}

	return m.filterer.Filter(m.textInput.CurrentTokenBeforeCursor(), m.suggestions), nil
}

func (m model) Execute(input string, promptModel *prompt.Model[any]) (tea.Model, error) {
	tokens := m.textInput.WordTokenValues()
	if len(tokens) == 0 {
		return nil, fmt.Errorf("No selection")
	}
	return executor.NewStringModel(m.formatOutput(tokens[0])), nil
}

func (m model) formatOutput(choice string) string {
	return fmt.Sprintf("You picked: %s\nYou've entered %s submissions(s)\n\n",
		m.outputStyle.Render(choice),
		m.outputStyle.Render(strconv.FormatInt(m.numChoices, 10)))
}

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

func (m model) Update(msg tea.Msg) (prompt.InputHandler[any], tea.Cmd) {
	if msg, ok := msg.(tea.KeyMsg); ok && msg.Type == tea.KeyEnter {
		m.numChoices++
	}
	return m, nil
}

func main() {
	// Initialize the input
	textInput := simpleinput.New[any]()

	// Define our suggestions
	suggestions := []suggestion.Suggestion[any]{
		{Text: "banana", Description: "good with peanut butter"},
		{Text: "\"sugar apple\"", SuggestionText: "sugar apple", Description: "spherical...ish"},
		{Text: "jackfruit", Description: "the jack of all fruits"},
		{Text: "snozzberry", Description: "tastes like snozzberries"},
		{Text: "lychee", Description: "better than leeches"},
		{Text: "mangosteen", Description: "it's not a mango"},
		{Text: "durian", Description: "stinky"},
	}

	// Combine everything into our model
	model := model{
		suggestions: suggestions,
		textInput:   textInput,
		// Add some coloring to the foreground of our output to make it look pretty
		outputStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("13")),
		filterer:    completer.NewPrefixFilter[any](),
	}

	// Create the Bubbleprompt model
	// This struct fulfills the tea.Model interface so it can be passed directly to tea.NewProgram
	promptModel := prompt.New[any](model, textInput)

	fmt.Println(lipgloss.NewStyle().Foreground(lipgloss.Color("6")).Render("Pick a fruit!"))
	fmt.Println()

	if _, err := tea.NewProgram(promptModel, tea.WithFilter(prompt.MsgFilter)).Run(); err != nil {
		fmt.Printf("Could not start program\n%v\n", err)
		os.Exit(1)
	}
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Model

type Model[T any] struct {
	// contains filtered or unexported fields
}

A Model is an input for handling simple token-based inputs without any special parsing required.

func New

func New[T any](options ...Option[T]) *Model[T]

New creates new a model.

func (*Model[T]) Blur

func (m *Model[T]) Blur()

Blur removes the focus from the input.

func (*Model[T]) CurrentToken

func (m *Model[T]) CurrentToken() input.Token

CurrentToken returns the token under the cursor.

func (*Model[T]) CurrentTokenBeforeCursor

func (m *Model[T]) CurrentTokenBeforeCursor() string

CurrentTokenBeforeCursor returns the portion of the token under the cursor that comes before the cursor position.

func (*Model[T]) CurrentTokenRoundDown

func (m *Model[T]) CurrentTokenRoundDown() input.Token

func (*Model[T]) CursorIndex

func (m *Model[T]) CursorIndex() int

CursorIndex returns the cursor index in terms of number of unicode characters. Use this to calculate input lengths in terms of number of characters entered.

func (*Model[T]) CursorOffset

func (m *Model[T]) CursorOffset() int

CursorOffset returns the visual offset of the cursor in terms of number of terminal cells. Use this for calculating visual dimensions such as input width/height.

func (*Model[T]) Focus

func (m *Model[T]) Focus() tea.Cmd

Focus sets the keyboard focus on the editor so the user can enter text.

func (*Model[T]) Focused

func (m *Model[T]) Focused() bool

Focused returns whether the keyboard is focused on the input.

func (*Model[T]) OnExecutorFinished

func (m *Model[T]) OnExecutorFinished()

OnExecutorFinished is part of the input.Input interface. It should not be invoked by users of this library.

func (*Model[T]) OnSuggestionChanged

func (m *Model[T]) OnSuggestionChanged(suggestion suggestion.Suggestion[T])

OnSuggestionChanged is part of the input.Input interface. It should not be invoked by users of this library.

func (*Model[T]) OnSuggestionUnselected

func (m *Model[T]) OnSuggestionUnselected()

OnSuggestionUnselected is part of the input.Input interface. It should not be invoked by users of this library.

func (*Model[T]) OnUpdateFinish

func (m *Model[T]) OnUpdateFinish(
	msg tea.Msg,
	suggestion *suggestion.Suggestion[T],
	isSelected bool,
) tea.Cmd

OnUpdateFinish is part of the input.Input interface. It should not be invoked by users of this library.

func (*Model[T]) OnUpdateStart

func (m *Model[T]) OnUpdateStart(msg tea.Msg) tea.Cmd

OnUpdateStart is part of the input.Input interface. It should not be invoked by end users.

func (*Model[T]) Prompt

func (m *Model[T]) Prompt() string

Prompt returns the terminal prompt.

func (*Model[T]) ResetValue

func (m *Model[T]) ResetValue()

ResetValue clears the input.

func (*Model[T]) Runes

func (m *Model[T]) Runes() []rune

Runes returns the raw text entered by the user as a list of runes. This is useful for indexing and length checks because doing these operations on strings does not work well with some unicode characters.

func (*Model[T]) SetCursor

func (m *Model[T]) SetCursor(cursor int)

SetCursor sets the cursor position.

func (*Model[T]) SetCursorMode

func (m *Model[T]) SetCursorMode(cursorMode cursor.Mode) tea.Cmd

SetCursorMode sets the mode of the cursor.

func (*Model[T]) SetPrompt

func (m *Model[T]) SetPrompt(prompt string)

SetPrompt sets the terminal prompt.

func (*Model[T]) SetValue

func (m *Model[T]) SetValue(value string)

SetValue sets the text of the input.

func (*Model[T]) ShouldClearSuggestions

func (m *Model[T]) ShouldClearSuggestions(prevText []rune, msg tea.KeyMsg) bool

ShouldClearSuggestions is part of the input.Input interface. It should not be invoked by users of this library.

func (*Model[T]) ShouldSelectSuggestion

func (m *Model[T]) ShouldSelectSuggestion(suggestion suggestion.Suggestion[T]) bool

ShouldSelectSuggestion is part of the input.Input interface. It should not be invoked by users of this library.

func (*Model[T]) ShouldUnselectSuggestion

func (m *Model[T]) ShouldUnselectSuggestion(prevText []rune, msg tea.KeyMsg) bool

ShouldUnselectSuggestion is part of the input.Input interface. It should not be invoked by users of this library.

func (*Model[T]) SuggestionRunes

func (m *Model[T]) SuggestionRunes(runes []rune) []rune

SuggestionRunes is part of the input.Input interface. It should not be invoked by users of this library.

func (*Model[T]) Tokens

func (m *Model[T]) Tokens() []input.Token

Tokens returns the tokenized input. This includes delimiter tokens.

func (*Model[T]) TokensBeforeCursor

func (m *Model[T]) TokensBeforeCursor() []input.Token

TokensBeforeCursor returns the tokenized input up to the cursor position. This includes delimiter tokens.

func (*Model[T]) Value

func (m *Model[T]) Value() string

Value returns the raw text entered by the user.

func (*Model[T]) View

func (m *Model[T]) View(viewMode input.ViewMode) string

View is part of the input.Input interface. It should not be invoked by users of this library.

func (*Model[T]) WordTokenValues

func (m *Model[T]) WordTokenValues() []string

WordTokenValues returns the tokenized input text. This does not include delimiter tokens.

func (*Model[T]) WordTokens

func (m *Model[T]) WordTokens() []input.Token

WordTokens returns the tokenized input. This does not include delimiter tokens.

func (*Model[T]) WordTokensBeforeCursor

func (m *Model[T]) WordTokensBeforeCursor() []input.Token

WordTokensBeforeCursor returns the tokenized input up to the cursor position. This does not include delimiter tokens.

type Option

type Option[T any] func(settings *settings[T])

func WithCursorMode

func WithCursorMode[T any](cursorMode cursor.Mode) Option[T]
Example
package main

import (
	"github.com/aschey/bubbleprompt/input/simpleinput"
	"github.com/charmbracelet/bubbles/cursor"
)

func main() {
	simpleinput.New(simpleinput.WithCursorMode[any](cursor.CursorStatic))
}

func WithDelimiterRegex

func WithDelimiterRegex[T any](delimiterRegex string) Option[T]
Example
package main

import (
	"github.com/aschey/bubbleprompt/input/simpleinput"
)

func main() {
	// Use period-delimited tokens instead of whitespace-delimited tokens
	// If you change the delimiter regex, you'll probably also need to change the token regex
	simpleinput.New(
		simpleinput.WithTokenRegex[any](`[^\s\.]+`),
		simpleinput.WithDelimiterRegex[any](`\s*\.\s*`),
	)
}

func WithFormatter

func WithFormatter[T any](formatterFunc func(lexer parser.Lexer) parser.Formatter) Option[T]
Example
package main

import (
	"github.com/aschey/bubbleprompt/input"
	"github.com/aschey/bubbleprompt/input/simpleinput"
	"github.com/aschey/bubbleprompt/parser"
	"github.com/charmbracelet/lipgloss"
)

type alternatingFormatter struct {
	lexer         parser.Lexer
	evenTextStyle lipgloss.Style
	oddTextStyle  lipgloss.Style
}

func (f alternatingFormatter) Lex(
	input string,
	_selectedToken *input.Token,
) ([]parser.FormatterToken, error) {
	tokens, err := f.lexer.Lex(input)
	if err != nil {
		return nil, err
	}

	formatterTokens := []parser.FormatterToken{}
	for i, token := range tokens {
		formatterToken := parser.FormatterToken{Value: token.Value}
		if i%2 == 0 {
			formatterToken.Style = f.evenTextStyle
		} else {
			formatterToken.Style = f.oddTextStyle
		}
		formatterTokens = append(formatterTokens, formatterToken)
	}

	return formatterTokens, nil
}

func main() {
	simpleinput.New(simpleinput.WithFormatter[any](func(lexer parser.Lexer) parser.Formatter {
		return alternatingFormatter{
			lexer:         lexer,
			evenTextStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("1")),
			oddTextStyle:  lipgloss.NewStyle().Foreground(lipgloss.Color("2")),
		}
	}))
}

func WithPrompt

func WithPrompt[T any](prompt string) Option[T]

func WithSelectedTextStyle

func WithSelectedTextStyle[T any](style lipgloss.Style) Option[T]
Example
package main

import (
	"github.com/aschey/bubbleprompt/input/simpleinput"
	"github.com/charmbracelet/lipgloss"
)

func main() {
	style := lipgloss.NewStyle().Foreground(lipgloss.Color("1")).Bold(true)
	simpleinput.New(simpleinput.WithSelectedTextStyle[any](style))
}

func WithTokenRegex

func WithTokenRegex[T any](tokenRegex string) Option[T]
Example
package main

import (
	"github.com/aschey/bubbleprompt/input/simpleinput"
)

func main() {
	// Use period-delimited tokens instead of whitespace-delimited tokens
	// If you change the token regex, you'll probably also need to change the delimiter regex
	simpleinput.New(
		simpleinput.WithTokenRegex[any](`[^\s\.]+`),
		simpleinput.WithDelimiterRegex[any](`\s*\.\s*`),
	)
}

Jump to

Keyboard shortcuts

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