charmbracelet / bubbletea

A powerful little TUI framework 🏗

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

List Model is not full screen

gitpubber opened this issue · comments

Hello, thanks for bubbletea. It's really good. I am developing TUI using bubbletea. It's search program which takes input from user and displays list. I was experimenting with prototype. I wanted to have perspective of "Pages" in bubbletea(for ex. Main Page, Search Page , List Page)

Here is the code:

main.go

package main

import (
	"fmt"
	"os"

	"github.com/charmbracelet/bubbles/list"
	"github.com/charmbracelet/bubbles/textinput"
	tea "github.com/charmbracelet/bubbletea"
	"github.com/charmbracelet/lipgloss"
)

func main() {
	if err := tea.NewProgram(mainModel(), tea.WithAltScreen()).Start(); err != nil {
		fmt.Println("Error running program:", err)
		os.Exit(1)
	}
}

type item struct {
	title, desc string
}

func (i item) Title() string       { return i.title }
func (i item) Description() string { return i.desc }
func (i item) FilterValue() string { return i.title }

var docStyle = lipgloss.NewStyle().Margin(1, 2)

type uiState int

const (
	uiMainPage uiState = iota
	uiListPage
)

type model struct {
	uiState   uiState
	textInput textinput.Model
	myList    list.Model
	err       error
}

func mainModel() model {
	ti := textinput.New()
	ti.Focus()
	//ti.CharLimit = 156
	//ti.Width = 20

	return model{
		uiState:   uiMainPage,
		textInput: ti,
		err:       nil,
	}
}

func (m model) Init() tea.Cmd {
	switch m.uiState {
	case uiMainPage:
		return textinput.Blink
	case uiListPage:
		return nil
	}
	return nil
}

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	switch m.uiState {
	case uiMainPage:
		switch msg := msg.(type) {
		case tea.KeyMsg:
			switch msg.Type {
			case tea.KeyCtrlC, tea.KeyEsc:
				return m, tea.Quit
			case tea.KeyEnter:
				items := []list.Item{
					item{title: "Raspberry Pi’s", desc: "I have ’em all over my house"},
					item{title: "Nutella", desc: "It's good on toast"},
					item{title: "Bitter melon", desc: "It cools you down"},
					item{title: "Nice socks", desc: "And by that I mean socks without holes"},
					item{title: "Eight hours of sleep", desc: "I had this once"},
					item{title: "Cats", desc: "Usually"},
					item{title: "Plantasia, the album", desc: "My plants love it too"},
					item{title: "Pour over coffee", desc: "It takes forever to make though"},
					item{title: "VR", desc: "Virtual reality...what is there to say?"},
					item{title: "Noguchi Lamps", desc: "Such pleasing organic forms"},
					item{title: "Linux", desc: "Pretty much the best OS"},
					item{title: "Business school", desc: "Just kidding"},
					item{title: "Pottery", desc: "Wet clay is a great feeling"},
					item{title: "Shampoo", desc: "Nothing like clean hair"},
					item{title: "Table tennis", desc: "It’s surprisingly exhausting"},
					item{title: "Milk crates", desc: "Great for packing in your extra stuff"},
					item{title: "Afternoon tea", desc: "Especially the tea sandwich part"},
					item{title: "Stickers", desc: "The thicker the vinyl the better"},
					item{title: "20° Weather", desc: "Celsius, not Fahrenheit"},
					item{title: "Warm light", desc: "Like around 2700 Kelvin"},
					item{title: "The vernal equinox", desc: "The autumnal equinox is pretty good too"},
					item{title: "Gaffer’s tape", desc: "Basically sticky fabric"},
					item{title: "Terrycloth", desc: "In other words, towel fabric"},
				}

				m.myList = list.New(items, list.NewDefaultDelegate(), 0, 0)
				m.myList.Title = "My Fave Things"
				m.uiState = uiListPage
				var cmd tea.Cmd
				m.myList, cmd = m.myList.Update(msg)
				return m, cmd
			}
		}

		var cmd tea.Cmd
		m.textInput, cmd = m.textInput.Update(msg)
		return m, cmd
	case uiListPage:
		switch msg := msg.(type) {
		case tea.KeyMsg:
			if msg.String() == "ctrl+c" {
				return m, tea.Quit
			}
		case tea.WindowSizeMsg:
			top, right, bottom, left := docStyle.GetMargin()
			m.myList.SetSize(msg.Width-left-right, msg.Height-top-bottom)
		}

		var cmd tea.Cmd
		m.myList, cmd = m.myList.Update(msg)
		return m, cmd

	default:
		return m, nil
	}
}

func (m model) View() string {
	switch m.uiState {
	case uiMainPage:
		return fmt.Sprintf(
			"Search: \n\n%s\n\n%s",
			m.textInput.View(),
			"(esc to quit)",
		) + "\n"
	case uiListPage:
		return docStyle.Render(m.myList.View())
	default:
		return ""
	}
}

Problem is that list only shows one element(unless terminal is resized) whereas i wanted it to be fullscreen.

This is what I wanted:
image

This is what I get:
image

Only one element is displayed.

Please help me.

At first glance it looks like your list simply doesn't have the right dimensions because it never receives an initial tea.WindowSizeMsg. I assume resizing your terminal would make the list snap back to an appropriate size?

If you want to dynamically initialize the list you would have to remember the last tea.WindowSizeMsg in your model and call m.myList.SetSize after creating the list.

@muesli , Yeah. That was the problem. I saved WindowSizeMsg as state in model. while switching to listview,I set it. Now,it's properly working.

But,it would be nicer if listview automatically does this though.