TwiN / go-choice

A very simple library for interactively selecting an option on a terminal

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Too many screen refreshes

TwiN opened this issue · comments

commented

screen.Clear() is pretty laggy on Windows, the following hack should be considered:

Instead of always clearing before printing text, the text could be filled with empty spaces (this is what tcell.Clear() does in the background anyways)

Here's an example:

func render(screen tcell.Screen, question string, options []*Choice, config *Config, selectedChoice *Choice) {
	//screen.Clear()
	_, maximumThatCanBeDisplayed := screen.Size()
	lineNumber := 0
	questionLines := strings.Split(question, "\n")
	for _, line := range questionLines {
		printText(screen, 1, lineNumber, line, config.TextColor, config.BackgroundColor, config.SelectedTextBold)
		lineNumber += 1
	}
	min := selectedChoice.Id + len(questionLines)
	max := maximumThatCanBeDisplayed
	if selectedChoice.Id > max {
		min += 1
		max += 1
	}
	for _, option := range options {
		if option.Id <= (min+1)-maximumThatCanBeDisplayed && !(option.Id > (min+1)-maximumThatCanBeDisplayed) {
			continue
		}
		if option.Selected {
			printText(screen, 1, lineNumber, fmt.Sprintf("> %s", option.Value), config.SelectedTextColor, config.BackgroundColor, config.SelectedTextBold)
		} else {
			printText(screen, 1, lineNumber, fmt.Sprintf("  %s", option.Value), config.TextColor, config.BackgroundColor, config.SelectedTextBold)
		}
		lineNumber += 1
	}
	screen.Show()
}

func printText(screen tcell.Screen, x, y int, text string, fg, bg tcell.Color, bold bool) {
	for _, character := range text {
		screen.SetCell(x, y, tcell.StyleDefault.Background(bg).Foreground(fg).Bold(bold), character)
		x += runewidth.RuneWidth(character)
	}
	// instead of using screen.Clear(), we'll just update the ENTIRE line with empty spaces
	width, _ := screen.Size()
	for i := len(text); i < width; i++ {
		screen.SetCell(x, y, tcell.StyleDefault.Background(bg).Foreground(fg), ' ')
		x += runewidth.RuneWidth(' ')
	}
}

Note that when the list of choices doesn't fit in the screen, this will cause some issues (e.g. bottom lines aren't updated), so something need to be done about that