Showing preview only (741K chars total). Download the full file or copy to clipboard to get everything.
Repository: rivo/tview
Branch: master
Commit: 63ee97f9e014
Files: 92
Total size: 710.3 KB
Directory structure:
gitextract_rl0cd57v/
├── .github/
│ └── FUNDING.yml
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── ansi.go
├── application.go
├── borders.go
├── box.go
├── button.go
├── checkbox.go
├── demos/
│ ├── box/
│ │ ├── README.md
│ │ └── main.go
│ ├── button/
│ │ ├── README.md
│ │ └── main.go
│ ├── checkbox/
│ │ ├── README.md
│ │ └── main.go
│ ├── dropdown/
│ │ ├── README.md
│ │ └── main.go
│ ├── flex/
│ │ ├── README.md
│ │ └── main.go
│ ├── form/
│ │ ├── README.md
│ │ └── main.go
│ ├── frame/
│ │ ├── README.md
│ │ └── main.go
│ ├── grid/
│ │ ├── README.md
│ │ └── main.go
│ ├── image/
│ │ ├── README.md
│ │ └── main.go
│ ├── inputfield/
│ │ ├── README.md
│ │ ├── autocomplete/
│ │ │ └── main.go
│ │ ├── autocompleteasync/
│ │ │ └── main.go
│ │ └── main.go
│ ├── list/
│ │ ├── README.md
│ │ └── main.go
│ ├── modal/
│ │ ├── README.md
│ │ └── main.go
│ ├── pages/
│ │ ├── README.md
│ │ └── main.go
│ ├── presentation/
│ │ ├── center.go
│ │ ├── code.go
│ │ ├── colors.go
│ │ ├── cover.go
│ │ ├── end.go
│ │ ├── flex.go
│ │ ├── form.go
│ │ ├── grid.go
│ │ ├── helloworld.go
│ │ ├── inputfield.go
│ │ ├── introduction.go
│ │ ├── main.go
│ │ ├── table.go
│ │ ├── textview.go
│ │ └── treeview.go
│ ├── primitive/
│ │ ├── README.md
│ │ └── main.go
│ ├── table/
│ │ ├── README.md
│ │ ├── main.go
│ │ └── virtualtable/
│ │ ├── README.md
│ │ └── main.go
│ ├── textarea/
│ │ ├── README.md
│ │ └── main.go
│ ├── textview/
│ │ ├── README.md
│ │ ├── chat/
│ │ │ ├── README.md
│ │ │ ├── chain.txt
│ │ │ └── main.go
│ │ └── main.go
│ ├── treeview/
│ │ ├── README.md
│ │ └── main.go
│ └── unicode/
│ ├── README.md
│ └── main.go
├── doc.go
├── dropdown.go
├── flex.go
├── form.go
├── frame.go
├── go.mod
├── go.sum
├── grid.go
├── image.go
├── inputfield.go
├── list.go
├── modal.go
├── pages.go
├── primitive.go
├── semigraphics.go
├── strings.go
├── styles.go
├── table.go
├── textarea.go
├── textview.go
├── treeview.go
└── util.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
github: rivo
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to tview
First of all, thank you for taking the time to contribute.
The following provides you with some guidance on how to contribute to this project. Mainly, it is meant to save us all some time so please read it, it's not long.
Please note that this document is work in progress so I might add to it in the future.
## Issues
- Please include enough information so everybody understands your request.
- Screenshots or code that illustrates your point always helps.
- It's fine to ask for help. But you should have checked out the [documentation](https://godoc.org/github.com/rivo/tview) first in any case.
- If you request a new feature, state your motivation and share a use case that you faced where you needed that new feature. It should be something that others will also need.
## Pull Requests
In my limited time I can spend on this project, I will always go through issues first before looking at pull requests. It takes a _lot_ of time to look at code that you submitted and I may not have that time. So be prepared to have your pull requests lying around for a long time.
Therefore, if you have a feature request, open an issue first before sending me a pull request, and allow for some discussion. It may save you from writing code that will get rejected. If your case is strong, there is a good chance that I will add the feature for you.
I'm very picky about the code that goes into this repo. So if you violate any of the following guidelines, there is a good chance I won't merge your pull request.
- There must be a strong case for your additions/changes, such as:
- Bug fixes
- Features that are needed (see "Issues" above; state your motivation)
- Improvements in stability or performance (if readability does not suffer)
- Your code must follow the structure of the existing code. Don't just patch something on. Try to understand how `tview` is currently designed and follow that design. Your code needs to be consistent with existing code.
- If you're adding code that increases the work required to maintain the project, you must be willing to take responsibility for that extra work. I will ask you to maintain your part of the code in the long run.
- Function/type/variable/constant names must be as descriptive as they are right now. Follow the conventions of the package.
- All functions/types/variables/constants, even private ones, must have comments in good English. These comments must be elaborate enough so that new users of the package understand them and can follow them. Provide examples if you have to. Start all sentences upper-case, as is common in English, and end them with a period. Comments in their own lines must not exceed the 80 character border. Break over if necessary.
- A new function should be located close to related functions in the file. For example, `GetColor()` should come after (or before) `SetColor()`.
- Your changes must not decrease the project's [Go Report](https://goreportcard.com/report/github.com/rivo/tview) rating.
- No breaking changes unless there is absolutely no other way.
- If an issue accompanies your pull request, reference it in the PR's comments, e.g. "Fixes #123", so it is closed automatically when the PR is closed.
================================================
FILE: LICENSE.txt
================================================
MIT License
Copyright (c) 2018 Oliver Kuederle
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Rich Interactive Widgets for Terminal UIs
[](https://pkg.go.dev/github.com/rivo/tview)
[](https://goreportcard.com/report/github.com/rivo/tview)
This Go package provides commonly used components for terminal based user interfaces.

Among these components are:
- __Input forms__ (including __text input__, __selections__, __checkboxes__, and __buttons__)
- Navigable multi-color __text views__
- Editable multi-line __text areas__
- Sophisticated navigable __table views__
- Flexible __tree views__
- Selectable __lists__
- __Images__
- __Grid__, __Flexbox__ and __page layouts__
- Modal __message windows__
- An __application__ wrapper
They come with lots of customization options and can be easily extended to fit your needs.
## Usage
To add this package to your project:
```bash
go get github.com/rivo/tview@master
```
## Hello World
This basic example creates a box titled "Hello, World!" and displays it in your terminal:
```go
package main
import (
"github.com/rivo/tview"
)
func main() {
box := tview.NewBox().SetBorder(true).SetTitle("Hello, world!")
if err := tview.NewApplication().SetRoot(box, true).Run(); err != nil {
panic(err)
}
}
```
Check out the [GitHub Wiki](https://github.com/rivo/tview/wiki) for more examples along with screenshots. Or try the examples in the "demos" subdirectory.
For a presentation highlighting this package, compile and run the program found in the "demos/presentation" subdirectory.
## Projects using `tview`
- [K9s - Kubernetes CLI](https://github.com/derailed/k9s)
- [IRCCloud Terminal Client](https://github.com/termoose/irccloud)
- [Window manager for `tview`](https://github.com/epiclabs-io/winman)
- [CLI bookmark manager](https://github.com/Endi1/drawer)
- [A caving database interface written in Go](https://github.com/IdlePhysicist/cave-logger)
- [Interactive file browse and exec any command.](https://github.com/bannzai/itree)
- [A complete TUI for LDAP](https://github.com/Macmod/godap)
- [A simple CRM](https://github.com/broadcastle/crm)
- [Terminal UI for todist](https://github.com/cyberdummy/todoista)
- [Graphical kubectl wrapper](https://github.com/dcaiafa/kpick)
- [Decred Decentralized Exchange ](https://github.com/decred/dcrdex)
- [A CLI file browser for Raspberry PI](https://github.com/destinmoulton/pixi)
- [A tool to manage projects.](https://github.com/divramod/dp)
- [A simple app for BMI monitoring](https://github.com/erleene/go-bmi)
- [Stream TIDAL from command line](https://github.com/godsic/vibe)
- [Secure solution for fully decentralized password management](https://github.com/guillaumemichel/passtor/)
- [A growing collection of convenient little tools to work with systemd services](https://github.com/muesli/service-tools/)
- [A terminal based browser for Redis written in Go](https://github.com/nitishm/redis-terminal)
- [First project for the Computer Networks course.](https://github.com/pablogadhi/XMPPClient)
- [Test your typing speed in the terminal!](https://github.com/shilangyu/typer-go)
- [TUI Client for Docker](https://github.com/skanehira/docui)
- [SSH client using certificates signed by HashiCorp Vault](https://github.com/stephane-martin/vssh)
- [VMware vCenter Text UI](https://github.com/thebsdbox/vctui)
- [Bookmarks on terminal](https://github.com/tryffel/bookmarker)
- [A UDP testing utility](https://github.com/vaelen/udp-tester)
- [A simple Kanban board for your terminal](https://github.com/witchard/toukan)
- [The personal information dashboard for your terminal. ](https://github.com/wtfutil/wtf)
- [MySQL database to Golang struct](https://github.com/xxjwxc/gormt)
- [Discord, TUI and SIXEL.](https://gitlab.com/diamondburned/6cord)
- [A CLI Audio Player](https://www.github.com/dhulihan/grump)
- [GLab, a GitLab CLI tool](https://gitlab.com/profclems/glab)
- [Browse your AWS ECS Clusters in the Terminal](https://github.com/swartzrock/ecsview)
- [The CLI Task Manager for Geeks](https://github.com/ajaxray/geek-life)
- [Fast disk usage analyzer written in Go](https://github.com/dundee/gdu)
- [Multiplayer Chess On Terminal](https://github.com/qnkhuat/gochess)
- [Scriptable TUI music player](https://github.com/issadarkthing/gomu)
- [MangaDesk : TUI Client for downloading manga to your computer](https://github.com/darylhjd/mangadesk)
- [Go How Much? a Crypto coin price tracking from terminal](https://github.com/ledongthuc/gohowmuch)
- [dbui: Universal CLI for Database Connections](https://github.com/KenanBek/dbui)
- [ssmbrowse: Simple and elegant cli AWS SSM parameter browser](https://github.com/bnaydenov/ssmbrowse)
- [gobit: binance intelligence terminal](https://github.com/infl00p/gobit)
- [viddy: A modern watch command](https://github.com/sachaos/viddy)
- [s3surfer: CLI tool for browsing S3 bucket and download objects interactively](https://github.com/hirose31/s3surfer)
- [libgen-tui: A terminal UI for downloading books from Library Genesis](https://github.com/audstanley/libgen-tui)
- [kubectl-lazy: kubectl plugin to easy to view pod](https://github.com/togettoyou/kubectl-lazy)
- [podman-tui: podman user interface](https://github.com/containers/podman-tui)
- [tvxwidgets: tview extra widgets](https://github.com/navidys/tvxwidgets)
- [Domino card game on terminal](https://github.com/gusti-andika/card-domino.git)
- [goaround: Query stackoverflow API and get results on terminal](https://github.com/glendsoza/goaround)
- [resto: a CLI app can send pretty HTTP & API requests with TUI](https://github.com/abdfnx/resto)
- [twad: a WAD launcher for the terminal](https://github.com/zmnpl/twad)
- [pacseek: A TUI for searching and installing Arch Linux packages](https://github.com/moson-mo/pacseek)
- [7GUIs demo](https://github.com/letientai299/7guis/tree/master/tui)
- [tuihub: A utility hub/dashboard for personal use](https://github.com/ashis0013/tuihub)
- [l'oggo: A terminal app for structured log streaming (GCP stack driver, k8s, local streaming)](https://github.com/aurc/loggo)
- [reminder: Terminal based interactive app for organising tasks with minimal efforts.](https://github.com/goyalmunish/reminder)
- [tufw: A terminal UI for ufw.](https://github.com/peltho/tufw)
- [gh: the GitHub CLI](https://github.com/cli/cli)
- [piptui: Terminal UI to manage pip packages](https://github.com/glendsoza/piptui/)
- [cross-clipboard: A cross-platform clipboard sharing](https://github.com/ntsd/cross-clipboard)
- [tui-deck: nextcloud deck frontend](https://github.com/mebitek/tui-deck)
- [ktop: A top-like tool for your Kubernetes clusters](https://github.com/vladimirvivien/ktop)
- [blimp: UI for weather, network latency, application status, & more](https://github.com/merlinfuchs/blimp)
- [Curly - A simple TUI leveraging curl to test endpoints](https://github.com/migcaraballo/curly)
- [amtui: Alertmanager TUI](https://github.com/pehlicd/amtui)
- [A TUI CLI manager](https://github.com/costa86/cli-manager)
- [PrivateBTC](https://github.com/adrianbrad/privatebtc)
- [play: A TUI playground to experiment with your favorite programs, such as grep, sed, awk, jq and yq](https://github.com/paololazzari/play)
- [gorest: Enjoy making HTTP requests in your terminal, just like you do in Insomnia.](https://github.com/NathanFirmo/gorest)
- [Terminal-based application to listen Radio Stations around the world!](https://github.com/vergonha/garden-tui)
- [ntui: A TUI to manage Hashicorp Nomad clusters](https://github.com/SHAPPY0/ntui)
- [lazysql: A cross-platform TUI database management tool written in Go](https://github.com/jorgerojas26/lazysql)
- [redis-tui: A Redis Text-based UI client in CLI](https://github.com/mylxsw/redis-tui)
- [fen: File manager](https://github.com/kivattt/fen)
- [sqltui: A terminal UI to operate sql and nosql databases](https://github.com/LinPr/sqltui)
- [DBee: Simple database browser](https://github.com/murat-cileli/dbee)
- [oddshub: A TUI for sports betting odds](https://github.com/dos-2/oddshub)
- [envolve: Terminal based interactive app for manage enviroment variables](https://github.com/erdemkosk/envolve)
- [zfs-file-history: Terminal UI for inspecting and restoring file history on ZFS snapshots](https://github.com/markusressel/zfs-file-history)
- [fan2go-tui: Terminal UI for fan2go](https://github.com/markusressel/fan2go-tui)
- [NatsDash: Terminal UI for NATS Jetstream](https://nats-dash-gui.returnzero.win/)
- [tuissh: A terminal UI to manage ssh connections](https://github.com/linuxexam/tuissh)
- [chiko: Ultimate Beauty TUI gRPC Client](https://github.com/felangga/chiko)
- [kmip-explorer: Browse & manage your KMIP objects from the terminal](https://github.com/phsym/kmip-explorer)
- [stui: Slurm TUI for managing HPC clusters](https://github.com/antvirf/stui)
- [nerdlog: Fast, remote-first, multi-host log viewer with timeline histogram](https://github.com/dimonomid/nerdlog)
- [lxz: A powerful DevOps graphical command-line interface tool](https://github.com/liangzhaoliang95/lxz)
- [vaulty: Terminal UI for Azure Keyvault](https://github.com/declan-whiting/vaulty)
- [pago: Command-line password manager](https://github.com/dbohdan/pago)
## Documentation
Refer to https://pkg.go.dev/github.com/rivo/tview for the package's documentation. Also check out the [Wiki](https://github.com/rivo/tview/wiki).
## Dependencies
This package is based on [github.com/gdamore/tcell](https://github.com/gdamore/tcell) (and its dependencies) as well as on [github.com/rivo/uniseg](https://github.com/rivo/uniseg).
## Sponsor this Project
[Become a Sponsor on GitHub](https://github.com/sponsors/rivo?metadata_source=tview_readme) to further this project!
## Backwards-Compatibility
I try really hard to keep this project backwards compatible. Your software should not break when you upgrade `tview`. But this also means that some of its shortcomings that were present in the initial versions will remain. Having said that, backwards compatibility may still break when:
- a new version of an imported package (most likely [`tcell`](https://github.com/gdamore/tcell)) changes in such a way that forces me to make changes in `tview` as well,
- I fix something that I consider a bug, rather than a feature, something that does not work as originally intended,
- I make changes to "internal" interfaces such as [`Primitive`](https://pkg.go.dev/github.com/rivo/tview#Primitive). You shouldn't need these interfaces unless you're writing your own primitives for `tview`. (Yes, I realize these are public interfaces. This has advantages as well as disadvantages. For the time being, it is what it is.)
## Your Feedback
Add your issue here on GitHub. Feel free to get in touch if you have any questions.
## Code of Conduct
We follow Golang's Code of Conduct which you can find [here](https://golang.org/conduct).
================================================
FILE: ansi.go
================================================
package tview
import (
"bytes"
"fmt"
"io"
"strconv"
"strings"
)
// The states of the ANSI escape code parser.
const (
ansiText = iota
ansiEscape
ansiSubstring
ansiControlSequence
)
// ansi is a io.Writer which translates ANSI escape codes into tview color
// tags.
type ansi struct {
io.Writer
// Reusable buffers.
buffer *bytes.Buffer // The entire output text of one Write().
csiParameter, csiIntermediate *bytes.Buffer // Partial CSI strings.
attributes string // The buffer's current text attributes (a tview attribute string).
// The current state of the parser. One of the ansi constants.
state int
}
// ANSIWriter returns an io.Writer which translates any ANSI escape codes
// written to it into tview style tags. Other escape codes don't have an effect
// and are simply removed. The translated text is written to the provided
// writer.
func ANSIWriter(writer io.Writer) io.Writer {
return &ansi{
Writer: writer,
buffer: new(bytes.Buffer),
csiParameter: new(bytes.Buffer),
csiIntermediate: new(bytes.Buffer),
state: ansiText,
}
}
// Write parses the given text as a string of runes, translates ANSI escape
// codes to style tags and writes them to the output writer.
func (a *ansi) Write(text []byte) (int, error) {
defer func() {
a.buffer.Reset()
}()
for _, r := range string(text) {
switch a.state {
// We just entered an escape sequence.
case ansiEscape:
switch r {
case '[': // Control Sequence Introducer.
a.csiParameter.Reset()
a.csiIntermediate.Reset()
a.state = ansiControlSequence
case 'c': // Reset.
fmt.Fprint(a.buffer, "[-:-:-]")
a.state = ansiText
case 'P', ']', 'X', '^', '_': // Substrings and commands.
a.state = ansiSubstring
default: // Ignore.
a.state = ansiText
}
// CSI Sequences.
case ansiControlSequence:
switch {
case r >= 0x30 && r <= 0x3f: // Parameter bytes.
if _, err := a.csiParameter.WriteRune(r); err != nil {
return 0, err
}
case r >= 0x20 && r <= 0x2f: // Intermediate bytes.
if _, err := a.csiIntermediate.WriteRune(r); err != nil {
return 0, err
}
case r >= 0x40 && r <= 0x7e: // Final byte.
switch r {
case 'E': // Next line.
count, _ := strconv.Atoi(a.csiParameter.String())
if count == 0 {
count = 1
}
fmt.Fprint(a.buffer, strings.Repeat("\n", count))
case 'm': // Select Graphic Rendition.
var background, foreground string
params := a.csiParameter.String()
fields := strings.Split(params, ";")
if len(params) == 0 || fields[0] == "" || fields[0] == "0" {
// Reset.
foreground = "-"
background = "-"
a.attributes = "-"
}
lookupColor := func(colorNumber int) string {
if colorNumber < 0 || colorNumber > 15 {
return "black"
}
return []string{
"black",
"maroon",
"green",
"olive",
"navy",
"purple",
"teal",
"silver",
"gray",
"red",
"lime",
"yellow",
"blue",
"fuchsia",
"aqua",
"white",
}[colorNumber]
}
FieldLoop:
for index, field := range fields {
switch field {
case "1", "01":
if !strings.ContainsRune(a.attributes, 'b') {
a.attributes += "b"
}
case "2", "02":
if !strings.ContainsRune(a.attributes, 'd') {
a.attributes += "d"
}
case "3", "03":
if !strings.ContainsRune(a.attributes, 'i') {
a.attributes += "i"
}
case "4", "04":
if !strings.ContainsRune(a.attributes, 'u') {
a.attributes += "u"
}
case "5", "05":
if !strings.ContainsRune(a.attributes, 'l') {
a.attributes += "l"
}
case "7", "07":
if !strings.ContainsRune(a.attributes, 'r') {
a.attributes += "r"
}
case "9", "09":
if !strings.ContainsRune(a.attributes, 's') {
a.attributes += "s"
}
case "22":
if i := strings.IndexRune(a.attributes, 'b'); i >= 0 {
a.attributes = a.attributes[:i] + a.attributes[i+1:]
}
if i := strings.IndexRune(a.attributes, 'd'); i >= 0 {
a.attributes = a.attributes[:i] + a.attributes[i+1:]
}
case "23":
if i := strings.IndexRune(a.attributes, 'i'); i >= 0 {
a.attributes = a.attributes[:i] + a.attributes[i+1:]
}
case "24":
if i := strings.IndexRune(a.attributes, 'u'); i >= 0 {
a.attributes = a.attributes[:i] + a.attributes[i+1:]
}
case "25":
if i := strings.IndexRune(a.attributes, 'l'); i >= 0 {
a.attributes = a.attributes[:i] + a.attributes[i+1:]
}
case "27":
if i := strings.IndexRune(a.attributes, 'r'); i >= 0 {
a.attributes = a.attributes[:i] + a.attributes[i+1:]
}
case "29":
if i := strings.IndexRune(a.attributes, 's'); i >= 0 {
a.attributes = a.attributes[:i] + a.attributes[i+1:]
}
case "30", "31", "32", "33", "34", "35", "36", "37":
colorNumber, _ := strconv.Atoi(field)
foreground = lookupColor(colorNumber - 30)
case "39":
foreground = "-"
case "40", "41", "42", "43", "44", "45", "46", "47":
colorNumber, _ := strconv.Atoi(field)
background = lookupColor(colorNumber - 40)
case "49":
background = "-"
case "90", "91", "92", "93", "94", "95", "96", "97":
colorNumber, _ := strconv.Atoi(field)
foreground = lookupColor(colorNumber - 82)
case "100", "101", "102", "103", "104", "105", "106", "107":
colorNumber, _ := strconv.Atoi(field)
background = lookupColor(colorNumber - 92)
case "38", "48":
var color string
if len(fields) > index+1 {
if fields[index+1] == "5" && len(fields) > index+2 { // 8-bit colors.
colorNumber, _ := strconv.Atoi(fields[index+2])
if colorNumber <= 15 {
color = lookupColor(colorNumber)
} else if colorNumber <= 231 {
red := (colorNumber - 16) / 36
green := ((colorNumber - 16) / 6) % 6
blue := (colorNumber - 16) % 6
color = fmt.Sprintf("#%02x%02x%02x", 255*red/5, 255*green/5, 255*blue/5)
} else if colorNumber <= 255 {
grey := 255 * (colorNumber - 232) / 23
color = fmt.Sprintf("#%02x%02x%02x", grey, grey, grey)
}
} else if fields[index+1] == "2" && len(fields) > index+4 { // 24-bit colors.
red, _ := strconv.Atoi(fields[index+2])
green, _ := strconv.Atoi(fields[index+3])
blue, _ := strconv.Atoi(fields[index+4])
color = fmt.Sprintf("#%02x%02x%02x", red, green, blue)
}
}
if len(color) > 0 {
if field == "38" {
foreground = color
} else {
background = color
}
}
break FieldLoop
}
}
var colon string
if len(a.attributes) > 1 && a.attributes[0] == '-' {
a.attributes = a.attributes[1:]
}
if len(a.attributes) > 0 {
colon = ":"
}
if len(foreground) > 0 || len(background) > 0 || len(a.attributes) > 0 {
fmt.Fprintf(a.buffer, "[%s:%s%s%s]", foreground, background, colon, a.attributes)
}
}
a.state = ansiText
default: // Undefined byte.
a.state = ansiText // Abort CSI.
}
// We just entered a substring/command sequence.
case ansiSubstring:
if r == 27 { // Most likely the end of the substring.
a.state = ansiEscape
} // Ignore all other characters.
// "ansiText" and all others.
default:
if r == 27 {
// This is the start of an escape sequence.
a.state = ansiEscape
} else {
// Just a regular rune. Send to buffer.
if _, err := a.buffer.WriteRune(r); err != nil {
return 0, err
}
}
}
}
// Write buffer to target writer.
n, err := a.buffer.WriteTo(a.Writer)
if err != nil {
return int(n), err
}
return len(text), nil
}
// TranslateANSI replaces ANSI escape sequences found in the provided string
// with tview's style tags and returns the resulting string.
func TranslateANSI(text string) string {
var buffer bytes.Buffer
writer := ANSIWriter(&buffer)
writer.Write([]byte(text))
return buffer.String()
}
================================================
FILE: application.go
================================================
package tview
import (
"strings"
"sync"
"time"
"github.com/gdamore/tcell/v2"
)
const (
// The size of the event/update/redraw channels.
queueSize = 100
// The minimum time between two consecutive redraws.
redrawPause = 50 * time.Millisecond
)
// DoubleClickInterval specifies the maximum time between clicks to register a
// double click rather than click.
var DoubleClickInterval = 500 * time.Millisecond
// MouseAction indicates one of the actions the mouse is logically doing.
type MouseAction int16
// Available mouse actions.
const (
MouseMove MouseAction = iota
MouseLeftDown
MouseLeftUp
MouseLeftClick
MouseLeftDoubleClick
MouseMiddleDown
MouseMiddleUp
MouseMiddleClick
MouseMiddleDoubleClick
MouseRightDown
MouseRightUp
MouseRightClick
MouseRightDoubleClick
MouseScrollUp
MouseScrollDown
MouseScrollLeft
MouseScrollRight
// The following special value will not be provided as a mouse action but
// indicate that an overridden mouse event was consumed. See
// [Box.SetMouseCapture] for details.
MouseConsumed
)
// queuedUpdate represented the execution of f queued by
// Application.QueueUpdate(). If "done" is not nil, it receives exactly one
// element after f has executed.
type queuedUpdate struct {
f func()
done chan struct{}
}
// Application represents the top node of an application.
//
// It is not strictly required to use this class as none of the other classes
// depend on it. However, it provides useful tools to set up an application and
// plays nicely with all widgets.
//
// The following command displays a primitive p on the screen until Ctrl-C is
// pressed:
//
// if err := tview.NewApplication().SetRoot(p, true).Run(); err != nil {
// panic(err)
// }
type Application struct {
sync.RWMutex
// The application's screen. Apart from Run(), this variable should never be
// set directly. Always use the screenReplacement channel after calling
// Fini(), to set a new screen (or nil to stop the application).
screen tcell.Screen
// The application's title. If not empty, it will be set on every new screen
// that is added.
title string
// The root primitive to be seen on the screen.
root Primitive
// Whether or not the application resizes the root primitive.
rootFullscreen bool
// Set to true if mouse events are enabled.
enableMouse bool
// Set to true if paste events are enabled.
enablePaste bool
// An optional capture function which receives a key event and returns the
// event to be forwarded to the default input handler (nil if nothing should
// be forwarded).
inputCapture func(event *tcell.EventKey) *tcell.EventKey
// An optional callback function which is invoked just before the root
// primitive is drawn.
beforeDraw func(screen tcell.Screen) bool
// An optional callback function which is invoked after the root primitive
// was drawn.
afterDraw func(screen tcell.Screen)
// Used to send screen events from separate goroutine to main event loop
events chan tcell.Event
// Functions queued from goroutines, used to serialize updates to primitives.
updates chan queuedUpdate
// An object that the screen variable will be set to after Fini() was called.
// Use this channel to set a new screen object for the application
// (screen.Init() and draw() will be called implicitly). A value of nil will
// stop the application.
screenReplacement chan tcell.Screen
// An optional capture function which receives a mouse event and returns the
// event to be forwarded to the default mouse handler (nil if nothing should
// be forwarded).
mouseCapture func(event *tcell.EventMouse, action MouseAction) (*tcell.EventMouse, MouseAction)
mouseCapturingPrimitive Primitive // A Primitive returned by a MouseHandler which will capture future mouse events.
lastMouseX, lastMouseY int // The last position of the mouse.
mouseDownX, mouseDownY int // The position of the mouse when its button was last pressed.
lastMouseClick time.Time // The time when a mouse button was last clicked.
lastMouseButtons tcell.ButtonMask // The last mouse button state.
}
// NewApplication creates and returns a new application.
func NewApplication() *Application {
return &Application{
events: make(chan tcell.Event, queueSize),
updates: make(chan queuedUpdate, queueSize),
screenReplacement: make(chan tcell.Screen, 1),
}
}
// SetInputCapture sets a function which captures all key events before they are
// forwarded to the key event handler of the primitive which currently has
// focus. This function can then choose to forward that key event (or a
// different one) by returning it or stop the key event processing by returning
// nil.
//
// The only default global key event is Ctrl-C which stops the application. It
// requires special handling:
//
// - If you do not wish to change the default behavior, return the original
// event object passed to your input capture function.
// - If you wish to block Ctrl-C from any functionality, return nil.
// - If you do not wish Ctrl-C to stop the application but still want to
// forward the Ctrl-C event to primitives down the hierarchy, return a new
// key event with the same key and modifiers, e.g.
// tcell.NewEventKey(tcell.KeyCtrlC, 0, tcell.ModNone).
//
// Pasted key events are not forwarded to the input capture function if pasting
// is enabled (see [Application.EnablePaste]).
func (a *Application) SetInputCapture(capture func(event *tcell.EventKey) *tcell.EventKey) *Application {
a.inputCapture = capture
return a
}
// GetInputCapture returns the function installed with SetInputCapture() or nil
// if no such function has been installed.
func (a *Application) GetInputCapture() func(event *tcell.EventKey) *tcell.EventKey {
return a.inputCapture
}
// SetMouseCapture sets a function which captures mouse events (consisting of
// the original tcell mouse event and the semantic mouse action) before they are
// forwarded to the appropriate mouse event handler. This function can then
// choose to forward that event (or a different one) by returning it or stop
// the event processing by returning a nil mouse event. In such a case, the
// event is considered consumed and the screen will be redrawn.
func (a *Application) SetMouseCapture(capture func(event *tcell.EventMouse, action MouseAction) (*tcell.EventMouse, MouseAction)) *Application {
a.mouseCapture = capture
return a
}
// GetMouseCapture returns the function installed with SetMouseCapture() or nil
// if no such function has been installed.
func (a *Application) GetMouseCapture() func(event *tcell.EventMouse, action MouseAction) (*tcell.EventMouse, MouseAction) {
return a.mouseCapture
}
// SetScreen allows you to provide your own tcell.Screen object. For most
// applications, this is not needed and you should be familiar with
// tcell.Screen when using this function. As the tcell.Screen interface may
// change in the future, you may need to update your code when this package
// updates to a new tcell version.
//
// This function is typically called before the first call to Run(). Init() need
// not be called on the screen.
func (a *Application) SetScreen(screen tcell.Screen) *Application {
if screen == nil {
return a // Invalid input. Do nothing.
}
a.Lock()
if a.screen == nil {
// Run() has not been called yet.
a.screen = screen
a.Unlock()
screen.Init()
return a
}
// Run() is already in progress. Exchange screen.
oldScreen := a.screen
a.Unlock()
oldScreen.Fini()
a.screenReplacement <- screen
return a
}
// SetTitle sets the title of the terminal window, to the extent that the
// terminal supports it. A non-empty title will be set on every new tcell.Screen
// that is created by or added to this application.
func (a *Application) SetTitle(title string) *Application {
a.Lock()
defer a.Unlock()
a.title = title
if a.screen != nil {
a.screen.SetTitle(title)
}
return a
}
// EnableMouse enables mouse events or disables them (if "false" is provided).
func (a *Application) EnableMouse(enable bool) *Application {
a.Lock()
defer a.Unlock()
if enable != a.enableMouse && a.screen != nil {
if enable {
a.screen.EnableMouse()
} else {
a.screen.DisableMouse()
}
}
a.enableMouse = enable
return a
}
// EnablePaste enables the capturing of paste events or disables them (if
// "false" is provided). This must be supported by the terminal.
//
// Widgets won't interpret paste events for navigation or selection purposes.
// Paste events are typically only used to insert a block of text into an
// [InputField] or a [TextArea].
func (a *Application) EnablePaste(enable bool) *Application {
a.Lock()
defer a.Unlock()
if enable != a.enablePaste && a.screen != nil {
if enable {
a.screen.EnablePaste()
} else {
a.screen.DisablePaste()
}
}
a.enablePaste = enable
return a
}
// Run starts the application and thus the event loop. This function returns
// when [Application.Stop] was called.
//
// Note that while an application is running, it fully claims stdin, stdout, and
// stderr. If you use these standard streams, they may not work as expected.
// Consider stopping the application first or suspending it (using
// [Application.Suspend]) if you have to interact with the standard streams, for
// example when needing to print a call stack during a panic.
func (a *Application) Run() error {
var (
err, appErr error
lastRedraw time.Time // The time the screen was last redrawn.
redrawTimer *time.Timer // A timer to schedule the next redraw.
)
a.Lock()
// Make a screen if there is none yet.
if a.screen == nil {
a.screen, err = tcell.NewScreen()
if err != nil {
a.Unlock()
return err
}
if err = a.screen.Init(); err != nil {
a.Unlock()
return err
}
if a.enableMouse {
a.screen.EnableMouse()
} else {
a.screen.DisableMouse()
}
if a.enablePaste {
a.screen.EnablePaste()
} else {
a.screen.DisablePaste()
}
if a.title != "" {
a.screen.SetTitle(a.title)
}
}
// We catch panics to clean up because they mess up the terminal.
defer func() {
if p := recover(); p != nil {
if a.screen != nil {
a.screen.Fini()
}
panic(p)
}
}()
// Draw the screen for the first time.
a.Unlock()
a.draw()
// Separate loop to wait for screen events.
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
for {
a.RLock()
screen := a.screen
a.RUnlock()
if screen == nil {
// We have no screen. Let's stop.
a.QueueEvent(nil)
break
}
// Wait for next event and queue it.
event := screen.PollEvent()
if event != nil {
// Regular event. Queue.
a.QueueEvent(event)
continue
}
// A screen was finalized (event is nil). Wait for a new screen.
screen = <-a.screenReplacement
if screen == nil {
// No new screen. We're done.
a.QueueEvent(nil) // Stop the event loop.
return
}
// We have a new screen. Keep going.
a.Lock()
a.screen = screen
enableMouse := a.enableMouse
enablePaste := a.enablePaste
a.Unlock()
// Initialize and draw this screen.
if err := screen.Init(); err != nil {
panic(err)
}
if enableMouse {
screen.EnableMouse()
} else {
screen.DisableMouse()
}
if enablePaste {
screen.EnablePaste()
} else {
screen.DisablePaste()
}
if a.title != "" {
screen.SetTitle(a.title)
}
a.draw()
}
}()
// Start event loop.
var (
pasteBuffer strings.Builder
pasting bool // Set to true while we receive paste key events.
)
EventLoop:
for {
select {
// If we received an event, handle it.
case event := <-a.events:
if event == nil {
break EventLoop
}
switch event := event.(type) {
case *tcell.EventKey:
// If we are pasting, collect runes, nothing else.
if pasting {
switch event.Key() {
case tcell.KeyRune:
pasteBuffer.WriteRune(event.Rune())
case tcell.KeyEnter:
pasteBuffer.WriteRune('\n')
case tcell.KeyCtrlJ:
pasteBuffer.WriteRune('\n')
case tcell.KeyTab:
pasteBuffer.WriteRune('\t')
}
break
}
a.RLock()
root := a.root
inputCapture := a.inputCapture
a.RUnlock()
// Intercept keys.
var draw bool
originalEvent := event
if inputCapture != nil {
event = inputCapture(event)
if event == nil {
a.draw()
break // Don't forward event.
}
draw = true
}
// Ctrl-C closes the application.
if event == originalEvent && event.Key() == tcell.KeyCtrlC {
a.Stop()
break
}
// Pass other key events to the root primitive.
if root != nil && root.HasFocus() {
if handler := root.InputHandler(); handler != nil {
handler(event, func(p Primitive) {
a.SetFocus(p)
})
draw = true
}
}
// Redraw.
if draw {
a.draw()
}
case *tcell.EventPaste:
if !a.enablePaste {
break
}
if event.Start() {
pasting = true
pasteBuffer.Reset()
} else if event.End() {
pasting = false
a.RLock()
root := a.root
a.RUnlock()
if root != nil && root.HasFocus() && pasteBuffer.Len() > 0 {
// Pass paste event to the root primitive.
if handler := root.PasteHandler(); handler != nil {
handler(pasteBuffer.String(), func(p Primitive) {
a.SetFocus(p)
})
}
// Redraw.
a.draw()
}
}
case *tcell.EventResize:
if time.Since(lastRedraw) < redrawPause {
if redrawTimer != nil {
redrawTimer.Stop()
}
redrawTimer = time.AfterFunc(redrawPause, func() {
a.events <- event
})
}
a.RLock()
screen := a.screen
a.RUnlock()
if screen == nil {
break
}
lastRedraw = time.Now()
screen.Clear()
a.draw()
case *tcell.EventMouse:
consumed, isMouseDownAction := a.fireMouseActions(event)
if consumed {
a.draw()
}
a.lastMouseButtons = event.Buttons()
if isMouseDownAction {
a.mouseDownX, a.mouseDownY = event.Position()
}
case *tcell.EventError:
appErr = event
a.Stop()
}
// If we have updates, now is the time to execute them.
case update := <-a.updates:
update.f()
if update.done != nil {
update.done <- struct{}{}
}
}
}
// Wait for the event loop to finish.
wg.Wait()
a.screen = nil
return appErr
}
// fireMouseActions analyzes the provided mouse event, derives mouse actions
// from it and then forwards them to the corresponding primitives.
func (a *Application) fireMouseActions(event *tcell.EventMouse) (consumed, isMouseDownAction bool) {
// We want to relay follow-up events to the same target primitive.
var targetPrimitive Primitive
// Helper function to fire a mouse action.
fire := func(action MouseAction) {
switch action {
case MouseLeftDown, MouseMiddleDown, MouseRightDown:
isMouseDownAction = true
}
// Intercept event.
if a.mouseCapture != nil {
event, action = a.mouseCapture(event, action)
if event == nil {
consumed = true
return // Don't forward event.
}
}
// Determine the target primitive.
var primitive, capturingPrimitive Primitive
if a.mouseCapturingPrimitive != nil {
primitive = a.mouseCapturingPrimitive
targetPrimitive = a.mouseCapturingPrimitive
} else if targetPrimitive != nil {
primitive = targetPrimitive
} else {
primitive = a.root
}
if primitive != nil {
if handler := primitive.MouseHandler(); handler != nil {
var wasConsumed bool
wasConsumed, capturingPrimitive = handler(action, event, func(p Primitive) {
a.SetFocus(p)
})
if wasConsumed {
consumed = true
}
}
}
a.mouseCapturingPrimitive = capturingPrimitive
}
x, y := event.Position()
buttons := event.Buttons()
clickMoved := x != a.mouseDownX || y != a.mouseDownY
buttonChanges := buttons ^ a.lastMouseButtons
if x != a.lastMouseX || y != a.lastMouseY {
fire(MouseMove)
a.lastMouseX = x
a.lastMouseY = y
}
for _, buttonEvent := range []struct {
button tcell.ButtonMask
down, up, click, dclick MouseAction
}{
{tcell.ButtonPrimary, MouseLeftDown, MouseLeftUp, MouseLeftClick, MouseLeftDoubleClick},
{tcell.ButtonMiddle, MouseMiddleDown, MouseMiddleUp, MouseMiddleClick, MouseMiddleDoubleClick},
{tcell.ButtonSecondary, MouseRightDown, MouseRightUp, MouseRightClick, MouseRightDoubleClick},
} {
if buttonChanges&buttonEvent.button != 0 {
if buttons&buttonEvent.button != 0 {
fire(buttonEvent.down)
} else {
fire(buttonEvent.up) // A user override might set event to nil.
if !clickMoved && event != nil {
if a.lastMouseClick.Add(DoubleClickInterval).Before(time.Now()) {
fire(buttonEvent.click)
a.lastMouseClick = time.Now()
} else {
fire(buttonEvent.dclick)
a.lastMouseClick = time.Time{} // reset
}
}
}
}
}
for _, wheelEvent := range []struct {
button tcell.ButtonMask
action MouseAction
}{
{tcell.WheelUp, MouseScrollUp},
{tcell.WheelDown, MouseScrollDown},
{tcell.WheelLeft, MouseScrollLeft},
{tcell.WheelRight, MouseScrollRight}} {
if buttons&wheelEvent.button != 0 {
fire(wheelEvent.action)
}
}
return consumed, isMouseDownAction
}
// Stop stops the application, causing Run() to return.
func (a *Application) Stop() {
a.Lock()
defer a.Unlock()
screen := a.screen
if screen == nil {
return
}
a.screen = nil
screen.Fini()
a.screenReplacement <- nil
}
// Suspend temporarily suspends the application by exiting terminal UI mode and
// invoking the provided function "f". When "f" returns, terminal UI mode is
// entered again and the application resumes.
//
// A return value of true indicates that the application was suspended and "f"
// was called. If false is returned, the application was already suspended,
// terminal UI mode was not exited, and "f" was not called.
func (a *Application) Suspend(f func()) bool {
a.RLock()
screen := a.screen
a.RUnlock()
if screen == nil {
return false // Screen has not yet been initialized.
}
// Enter suspended mode.
if err := screen.Suspend(); err != nil {
return false // Suspension failed.
}
// Wait for "f" to return.
f()
// If the screen object has changed in the meantime, we need to do more.
a.RLock()
defer a.RUnlock()
if a.screen != screen {
// Calling Stop() while in suspend mode currently still leads to a
// panic, see https://github.com/gdamore/tcell/issues/440.
screen.Fini()
if a.screen == nil {
return true // If stop was called (a.screen is nil), we're done already.
}
} else {
// It hasn't changed. Resume.
screen.Resume() // Not much we can do in case of an error.
}
// Continue application loop.
return true
}
// Draw refreshes the screen (during the next update cycle). It calls the Draw()
// function of the application's root primitive and then syncs the screen
// buffer. It is almost never necessary to call this function. It can actually
// deadlock your application if you call it from the main thread (e.g. in a
// callback function of a widget). Please see
// https://github.com/rivo/tview/wiki/Concurrency for details.
func (a *Application) Draw() *Application {
a.QueueUpdate(func() {
a.draw()
})
return a
}
// ForceDraw refreshes the screen immediately. Use this function with caution as
// it may lead to race conditions with updates to primitives in other
// goroutines. It is always preferable to call [Application.Draw] instead.
// Never call this function from a goroutine.
//
// It is safe to call this function during queued updates and direct event
// handling.
func (a *Application) ForceDraw() *Application {
return a.draw()
}
// draw actually does what Draw() promises to do.
func (a *Application) draw() *Application {
a.Lock()
defer a.Unlock()
screen := a.screen
root := a.root
fullscreen := a.rootFullscreen
before := a.beforeDraw
after := a.afterDraw
// Maybe we're not ready yet or not anymore.
if screen == nil || root == nil {
return a
}
// Resize if requested.
if fullscreen { // root is not nil here.
width, height := screen.Size()
root.SetRect(0, 0, width, height)
}
// Clear screen to remove unwanted artifacts from the previous cycle.
screen.Clear()
// Call before handler if there is one.
if before != nil {
if before(screen) {
screen.Show()
return a
}
}
// Draw all primitives.
root.Draw(screen)
// Call after handler if there is one.
if after != nil {
after(screen)
}
// Sync screen.
screen.Show()
return a
}
// Sync forces a full re-sync of the screen buffer with the actual screen during
// the next event cycle. This is useful for when the terminal screen is
// corrupted so you may want to offer your users a keyboard shortcut to refresh
// the screen.
func (a *Application) Sync() *Application {
a.updates <- queuedUpdate{f: func() {
a.RLock()
screen := a.screen
a.RUnlock()
if screen == nil {
return
}
screen.Sync()
}}
return a
}
// SetBeforeDrawFunc installs a callback function which is invoked just before
// the root primitive is drawn during screen updates. If the function returns
// true, drawing will not continue, i.e. the root primitive will not be drawn
// (and an after-draw-handler will not be called).
//
// Note that the screen is not cleared by the application. To clear the screen,
// you may call screen.Clear().
//
// Provide nil to uninstall the callback function.
func (a *Application) SetBeforeDrawFunc(handler func(screen tcell.Screen) bool) *Application {
a.beforeDraw = handler
return a
}
// GetBeforeDrawFunc returns the callback function installed with
// SetBeforeDrawFunc() or nil if none has been installed.
func (a *Application) GetBeforeDrawFunc() func(screen tcell.Screen) bool {
return a.beforeDraw
}
// SetAfterDrawFunc installs a callback function which is invoked after the root
// primitive was drawn during screen updates.
//
// Provide nil to uninstall the callback function.
func (a *Application) SetAfterDrawFunc(handler func(screen tcell.Screen)) *Application {
a.afterDraw = handler
return a
}
// GetAfterDrawFunc returns the callback function installed with
// SetAfterDrawFunc() or nil if none has been installed.
func (a *Application) GetAfterDrawFunc() func(screen tcell.Screen) {
return a.afterDraw
}
// SetRoot sets the root primitive for this application. If "fullscreen" is set
// to true, the root primitive's position will be changed to fill the screen.
//
// This function must be called at least once or nothing will be displayed when
// the application starts.
//
// It also calls SetFocus() on the primitive.
func (a *Application) SetRoot(root Primitive, fullscreen bool) *Application {
a.Lock()
a.root = root
a.rootFullscreen = fullscreen
if a.screen != nil {
a.screen.Clear()
}
a.Unlock()
a.SetFocus(root)
return a
}
// ResizeToFullScreen resizes the given primitive such that it fills the entire
// screen.
func (a *Application) ResizeToFullScreen(p Primitive) *Application {
a.RLock()
width, height := a.screen.Size()
a.RUnlock()
p.SetRect(0, 0, width, height)
return a
}
// SetFocus sets the focus to a new primitive. All key events will be directed
// down the hierarchy (starting at the root) until a primitive handles them,
// which per default goes towards the focused primitive.
//
// Blur will be called on the previously focused [Primitive] and all of its
// parents (including the root). Then Focus will be called on the new
// [Primitive] and all of its parents (including the root).
func (a *Application) SetFocus(p Primitive) *Application {
a.RLock()
root := a.root
screen := a.screen
a.RUnlock()
// We make a focus chain with some pre-allocated space.
chain := make([]Primitive, 0, 10)
// Send blur events along the focus chain.
if root != nil && root.focusChain(&chain) {
for index, pr := range chain {
if index == 0 {
pr.Blur()
}
pr.blurred()
}
// Hide the cursor. If it's needed, the new focused primitive will show it
// again.
if screen != nil {
screen.HideCursor()
}
} // At this point, no primitive has focus.
// Focus the new primitive.
var delegated bool
if p != nil {
p.Focus(func(p Primitive) {
delegated = true // Avoids multiple focus notifications.
a.SetFocus(p)
})
}
// If the primitive delegated focus to a child, that call has already
// notified the focus listeners.
if delegated {
return a
}
// Send focus events along the new focus chain.
chain = chain[:0]
if root != nil && root.focusChain(&chain) {
for _, pr := range chain {
pr.focused()
}
}
return a
}
// GetFocus returns the primitive which has the current focus. If none has it,
// nil is returned.
func (a *Application) GetFocus() Primitive {
a.RLock()
defer a.RUnlock()
if a.root == nil {
return nil
}
chain := make([]Primitive, 0, 10)
if a.root.focusChain(&chain) && len(chain) > 0 {
return chain[0]
}
return nil
}
// QueueUpdate is used to synchronize access to primitives from non-main
// goroutines. The provided function will be executed as part of the event loop
// and thus will not cause race conditions with other such update functions or
// the Draw() function.
//
// Note that Draw() is not implicitly called after the execution of f as that
// may not be desirable. You can call Draw() from f if the screen should be
// refreshed after each update. Alternatively, use QueueUpdateDraw() to follow
// up with an immediate refresh of the screen.
//
// This function returns after f has executed.
func (a *Application) QueueUpdate(f func()) *Application {
ch := make(chan struct{})
a.updates <- queuedUpdate{f: f, done: ch}
<-ch
return a
}
// QueueUpdateDraw works like QueueUpdate() except it refreshes the screen
// immediately after executing f.
func (a *Application) QueueUpdateDraw(f func()) *Application {
a.QueueUpdate(func() {
f()
a.draw()
})
return a
}
// QueueEvent sends an event to the Application event loop.
//
// It is not recommended for event to be nil.
func (a *Application) QueueEvent(event tcell.Event) *Application {
a.events <- event
return a
}
================================================
FILE: borders.go
================================================
package tview
// Borders defines various borders used when primitives are drawn.
// These may be changed to accommodate a different look and feel.
var Borders = struct {
Horizontal rune
Vertical rune
TopLeft rune
TopRight rune
BottomLeft rune
BottomRight rune
LeftT rune
RightT rune
TopT rune
BottomT rune
Cross rune
HorizontalFocus rune
VerticalFocus rune
TopLeftFocus rune
TopRightFocus rune
BottomLeftFocus rune
BottomRightFocus rune
}{
Horizontal: BoxDrawingsLightHorizontal,
Vertical: BoxDrawingsLightVertical,
TopLeft: BoxDrawingsLightDownAndRight,
TopRight: BoxDrawingsLightDownAndLeft,
BottomLeft: BoxDrawingsLightUpAndRight,
BottomRight: BoxDrawingsLightUpAndLeft,
LeftT: BoxDrawingsLightVerticalAndRight,
RightT: BoxDrawingsLightVerticalAndLeft,
TopT: BoxDrawingsLightDownAndHorizontal,
BottomT: BoxDrawingsLightUpAndHorizontal,
Cross: BoxDrawingsLightVerticalAndHorizontal,
HorizontalFocus: BoxDrawingsDoubleHorizontal,
VerticalFocus: BoxDrawingsDoubleVertical,
TopLeftFocus: BoxDrawingsDoubleDownAndRight,
TopRightFocus: BoxDrawingsDoubleDownAndLeft,
BottomLeftFocus: BoxDrawingsDoubleUpAndRight,
BottomRightFocus: BoxDrawingsDoubleUpAndLeft,
}
================================================
FILE: box.go
================================================
package tview
import (
"github.com/gdamore/tcell/v2"
)
// Box implements the Primitive interface with an empty background and optional
// elements such as a border and a title. Box itself does not hold any content
// but serves as the superclass of all other primitives. Subclasses add their
// own content, typically (but not necessarily) keeping their content within the
// box's rectangle.
//
// Box provides a number of utility functions available to all primitives.
//
// See https://github.com/rivo/tview/wiki/Box for an example.
type Box struct {
// Points to the implementing primitive at the bottom of the hierarchy.
Primitive
// The position of the rect.
x, y, width, height int
// The inner rect reserved for the box's content. If innerX is negative,
// the rect is undefined and must be calculated.
innerX, innerY, innerWidth, innerHeight int
// Border padding.
paddingTop, paddingBottom, paddingLeft, paddingRight int
// The box's background color.
backgroundColor tcell.Color
// If set to true, the background of this box is not cleared while drawing.
dontClear bool
// Whether or not a border is drawn, reducing the box's space for content by
// two in width and height.
border bool
// The border style.
borderStyle tcell.Style
// The title. Only visible if there is a border, too.
title string
// The color of the title.
titleColor tcell.Color
// The alignment of the title.
titleAlign int
// Whether or not this box has focus. At any time, this must be true only
// for one primitive in the entire application. Such a primitive is usually
// a visible and enabled widget but may also be a container primitive (if
// no contained primitive has focus) or a primitive inaccessible to the user
// (e.g. a child primitive of a widget to which interaction is delegated).
hasFocus bool
// Optional callback functions invoked when the primitive receives or loses
// focus.
focus, blur func()
// Callback function invoked when the box itself is resized, nil if not set.
boxResize func()
// Callback function invoked when the box's inner content area is resized,
// nil if not set.
contentResize func()
// An optional capture function which receives a key event and returns the
// event to be forwarded to the primitive's default input handler (nil if
// nothing should be forwarded).
inputCapture func(event *tcell.EventKey) *tcell.EventKey
// An optional function which is called before the box is drawn.
draw func(screen tcell.Screen, x, y, width, height int) (int, int, int, int)
// An optional capture function which receives a mouse event and returns the
// event to be forwarded to the primitive's default mouse event handler (at
// least one nil if nothing should be forwarded).
mouseCapture func(action MouseAction, event *tcell.EventMouse) (MouseAction, *tcell.EventMouse)
}
// NewBox returns a [Box] without a border.
func NewBox() *Box {
b := &Box{
width: 15,
height: 10,
innerX: -1, // Mark as uninitialized.
backgroundColor: Styles.PrimitiveBackgroundColor,
borderStyle: tcell.StyleDefault.Foreground(Styles.BorderColor).Background(Styles.PrimitiveBackgroundColor),
titleColor: Styles.TitleColor,
titleAlign: AlignCenter,
}
b.Primitive = b
return b
}
// SetBorderPadding sets the size of the borders around the box content.
func (b *Box) SetBorderPadding(top, bottom, left, right int) *Box {
b.paddingTop, b.paddingBottom, b.paddingLeft, b.paddingRight = top, bottom, left, right
return b
}
// GetRect returns the current position of the rectangle, x, y, width, and
// height.
func (b *Box) GetRect() (int, int, int, int) {
return b.x, b.y, b.width, b.height
}
// GetInnerRect returns the position of the inner rectangle (x, y, width,
// height), without the border and without any padding. Width and height values
// will clamp to 0 and thus never be negative.
func (b *Box) GetInnerRect() (int, int, int, int) {
if b.innerX >= 0 {
return b.innerX, b.innerY, b.innerWidth, b.innerHeight
}
x, y, width, height := b.GetRect()
if b.border {
x++
y++
width -= 2
height -= 2
}
x, y, width, height = x+b.paddingLeft,
y+b.paddingTop,
width-b.paddingLeft-b.paddingRight,
height-b.paddingTop-b.paddingBottom
if width < 0 {
width = 0
}
if height < 0 {
height = 0
}
return x, y, width, height
}
// SetRect sets a new position of the primitive. Note that this has no effect
// if this primitive is part of a layout (e.g. Flex, Grid) or if it was added
// like this:
//
// application.SetRoot(p, true)
func (b *Box) SetRect(x, y, width, height int) {
b.x = x
b.y = y
b.width, width = width, b.width
b.height, height = height, b.height
if b.width != width || b.height != height {
if b.boxResize != nil {
b.boxResize()
}
if b.contentResize != nil {
b.contentResize()
}
}
b.innerX = -1 // Mark inner rect as uninitialized.
}
// SetDrawFunc sets a callback function which is invoked after the box primitive
// has been drawn. This allows you to add a more individual style to the box
// (and all primitives which extend it).
//
// The function is provided with the box's dimensions (set via SetRect()). It
// must return the box's inner dimensions (x, y, width, height) which will be
// returned by GetInnerRect(), used by descendent primitives to draw their own
// content.
func (b *Box) SetDrawFunc(handler func(screen tcell.Screen, x, y, width, height int) (int, int, int, int)) *Box {
b.draw = handler
return b
}
// GetDrawFunc returns the callback function which was installed with
// SetDrawFunc() or nil if no such function has been installed.
func (b *Box) GetDrawFunc() func(screen tcell.Screen, x, y, width, height int) (int, int, int, int) {
return b.draw
}
// SetBoxResizeFunc sets a callback function which is invoked when the size of
// the box itself changes. Note that this is not called when the box is moved
// (i.e. when only x and y change). Set to nil to remove the callback function.
func (b *Box) SetBoxResizeFunc(handler func()) *Box {
b.boxResize = handler
return b
}
// SetContentResizeFunc sets a callback function which is invoked when the size
// of the box's inner content area changes. Note that this is not called when
// the area is moved (i.e. when only x and y change). Set to nil to remove the
// callback function.
func (b *Box) SetContentResizeFunc(handler func()) *Box {
b.contentResize = handler
return b
}
// WrapInputHandler wraps an input handler (see [Box.InputHandler]) with the
// functionality to capture input (see [Box.SetInputCapture]) before passing it
// on to the provided (default) input handler.
//
// This is only meant to be used by subclassing primitives.
func (b *Box) WrapInputHandler(inputHandler func(*tcell.EventKey, func(p Primitive))) func(*tcell.EventKey, func(p Primitive)) {
return func(event *tcell.EventKey, setFocus func(p Primitive)) {
if b.inputCapture != nil {
event = b.inputCapture(event)
}
if event != nil && inputHandler != nil {
inputHandler(event, setFocus)
}
}
}
// InputHandler returns nil. Box has no default input handling.
func (b *Box) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
return b.WrapInputHandler(nil)
}
// WrapPasteHandler wraps a paste handler (see [Box.PasteHandler]).
func (b *Box) WrapPasteHandler(pasteHandler func(string, func(p Primitive))) func(string, func(p Primitive)) {
return func(text string, setFocus func(p Primitive)) {
if pasteHandler != nil {
pasteHandler(text, setFocus)
}
}
}
// PasteHandler returns nil. Box has no default paste handling.
func (b *Box) PasteHandler() func(pastedText string, setFocus func(p Primitive)) {
return b.WrapPasteHandler(nil)
}
// SetInputCapture installs a function which captures key events before they are
// forwarded to the primitive's default key event handler. This function can
// then choose to forward that key event (or a different one) to the default
// handler by returning it. If nil is returned, the default handler will not
// be called.
//
// Providing a nil handler will remove a previously existing handler.
//
// This function can also be used on container primitives (like Flex, Grid, or
// Form) as keyboard events will be handed down until they are handled.
//
// Pasted key events are not forwarded to the input capture function if pasting
// is enabled (see [Application.EnablePaste]).
func (b *Box) SetInputCapture(capture func(event *tcell.EventKey) *tcell.EventKey) *Box {
b.inputCapture = capture
return b
}
// GetInputCapture returns the function installed with SetInputCapture() or nil
// if no such function has been installed.
func (b *Box) GetInputCapture() func(event *tcell.EventKey) *tcell.EventKey {
return b.inputCapture
}
// WrapMouseHandler wraps a mouse event handler (see [Box.MouseHandler]) with the
// functionality to capture mouse events (see [Box.SetMouseCapture]) before passing
// them on to the provided (default) event handler.
//
// This is only meant to be used by subclassing primitives.
func (b *Box) WrapMouseHandler(mouseHandler func(MouseAction, *tcell.EventMouse, func(p Primitive)) (bool, Primitive)) func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
return func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
if b.mouseCapture != nil {
action, event = b.mouseCapture(action, event)
}
if event == nil {
if action == MouseConsumed {
consumed = true
}
} else if mouseHandler != nil {
consumed, capture = mouseHandler(action, event, setFocus)
}
return
}
}
// MouseHandler returns nil. Box has no default mouse handling.
func (b *Box) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
return b.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
if action == MouseLeftDown && b.InRect(event.Position()) {
setFocus(b)
consumed = true
}
return
})
}
// SetMouseCapture sets a function which captures mouse events (consisting of
// the original tcell mouse event and the semantic mouse action) before they are
// forwarded to the primitive's default mouse event handler. This function can
// then choose to forward that event (or a different one) by returning it or
// returning a nil mouse event, in which case the default handler will not be
// called.
//
// When a nil event is returned, the returned mouse action value may be set to
// [MouseConsumed] to indicate that the event was consumed and the screen should
// be redrawn. Any other value will not cause a redraw.
//
// Providing a nil handler will remove a previously existing handler.
//
// Note that mouse events are ignored completely if the application has not been
// enabled for mouse events (see [Application.EnableMouse]), which is the
// default.
func (b *Box) SetMouseCapture(capture func(action MouseAction, event *tcell.EventMouse) (MouseAction, *tcell.EventMouse)) *Box {
b.mouseCapture = capture
return b
}
// InRect returns true if the given coordinate is within the bounds of the box's
// rectangle.
func (b *Box) InRect(x, y int) bool {
rectX, rectY, width, height := b.GetRect()
return x >= rectX && x < rectX+width && y >= rectY && y < rectY+height
}
// InInnerRect returns true if the given coordinate is within the bounds of the
// box's inner rectangle (within the border and padding).
func (b *Box) InInnerRect(x, y int) bool {
rectX, rectY, width, height := b.GetInnerRect()
return x >= rectX && x < rectX+width && y >= rectY && y < rectY+height
}
// GetMouseCapture returns the function installed with SetMouseCapture() or nil
// if no such function has been installed.
func (b *Box) GetMouseCapture() func(action MouseAction, event *tcell.EventMouse) (MouseAction, *tcell.EventMouse) {
return b.mouseCapture
}
// SetBackgroundColor sets the box's background color.
func (b *Box) SetBackgroundColor(color tcell.Color) *Box {
b.backgroundColor = color
b.borderStyle = b.borderStyle.Background(color)
return b
}
// SetBorder sets the flag indicating whether or not the box should have a
// border.
func (b *Box) SetBorder(show bool) *Box {
b.border, show = show, b.border
if b.border != show {
if b.contentResize != nil {
b.contentResize()
}
}
return b
}
// SetBorderStyle sets the box's border style.
func (b *Box) SetBorderStyle(style tcell.Style) *Box {
b.borderStyle = style
return b
}
// SetBorderColor sets the box's border color.
func (b *Box) SetBorderColor(color tcell.Color) *Box {
b.borderStyle = b.borderStyle.Foreground(color)
return b
}
// SetBorderAttributes sets the border's style attributes. You can combine
// different attributes using bitmask operations:
//
// box.SetBorderAttributes(tcell.AttrItalic | tcell.AttrBold)
func (b *Box) SetBorderAttributes(attr tcell.AttrMask) *Box {
b.borderStyle = b.borderStyle.Attributes(attr)
return b
}
// GetBorderAttributes returns the border's style attributes.
func (b *Box) GetBorderAttributes() tcell.AttrMask {
_, _, attr := b.borderStyle.Decompose()
return attr
}
// GetBorderColor returns the box's border color.
func (b *Box) GetBorderColor() tcell.Color {
color, _, _ := b.borderStyle.Decompose()
return color
}
// GetBackgroundColor returns the box's background color.
func (b *Box) GetBackgroundColor() tcell.Color {
return b.backgroundColor
}
// SetTitle sets the box's title.
func (b *Box) SetTitle(title string) *Box {
b.title = title
return b
}
// GetTitle returns the box's current title.
func (b *Box) GetTitle() string {
return b.title
}
// SetTitleColor sets the box's title color.
func (b *Box) SetTitleColor(color tcell.Color) *Box {
b.titleColor = color
return b
}
// SetTitleAlign sets the alignment of the title, one of AlignLeft, AlignCenter,
// or AlignRight.
func (b *Box) SetTitleAlign(align int) *Box {
b.titleAlign = align
return b
}
// Draw draws this primitive onto the screen.
func (b *Box) Draw(screen tcell.Screen) {
b.DrawForSubclass(screen, b)
}
// DrawForSubclass draws this box under the assumption that primitive p is a
// subclass of this box. This is needed e.g. to draw proper box frames which
// depend on the subclass's focus.
//
// Only call this function from your own custom primitives. It is not needed in
// applications that have no custom primitives.
func (b *Box) DrawForSubclass(screen tcell.Screen, p Primitive) {
// Don't draw anything if there is no space.
if b.width <= 0 || b.height <= 0 {
return
}
// Fill background.
background := tcell.StyleDefault.Background(b.backgroundColor)
if !b.dontClear {
for y := b.y; y < b.y+b.height; y++ {
for x := b.x; x < b.x+b.width; x++ {
screen.SetContent(x, y, ' ', nil, background)
}
}
}
// Draw border.
if b.border && b.width >= 2 && b.height >= 2 {
var vertical, horizontal, topLeft, topRight, bottomLeft, bottomRight rune
if p.HasFocus() {
horizontal = Borders.HorizontalFocus
vertical = Borders.VerticalFocus
topLeft = Borders.TopLeftFocus
topRight = Borders.TopRightFocus
bottomLeft = Borders.BottomLeftFocus
bottomRight = Borders.BottomRightFocus
} else {
horizontal = Borders.Horizontal
vertical = Borders.Vertical
topLeft = Borders.TopLeft
topRight = Borders.TopRight
bottomLeft = Borders.BottomLeft
bottomRight = Borders.BottomRight
}
for x := b.x + 1; x < b.x+b.width-1; x++ {
screen.SetContent(x, b.y, horizontal, nil, b.borderStyle)
screen.SetContent(x, b.y+b.height-1, horizontal, nil, b.borderStyle)
}
for y := b.y + 1; y < b.y+b.height-1; y++ {
screen.SetContent(b.x, y, vertical, nil, b.borderStyle)
screen.SetContent(b.x+b.width-1, y, vertical, nil, b.borderStyle)
}
screen.SetContent(b.x, b.y, topLeft, nil, b.borderStyle)
screen.SetContent(b.x+b.width-1, b.y, topRight, nil, b.borderStyle)
screen.SetContent(b.x, b.y+b.height-1, bottomLeft, nil, b.borderStyle)
screen.SetContent(b.x+b.width-1, b.y+b.height-1, bottomRight, nil, b.borderStyle)
// Draw title.
if b.title != "" && b.width >= 4 {
printed, _ := Print(screen, b.title, b.x+1, b.y, b.width-2, b.titleAlign, b.titleColor)
if len(b.title)-printed > 0 && printed > 0 {
xEllipsis := b.x + b.width - 2
if b.titleAlign == AlignRight {
xEllipsis = b.x + 1
}
_, _, style, _ := screen.GetContent(xEllipsis, b.y)
fg, _, _ := style.Decompose()
Print(screen, string(SemigraphicsHorizontalEllipsis), xEllipsis, b.y, 1, AlignLeft, fg)
}
}
}
// Call custom draw function.
if b.draw != nil {
b.innerX, b.innerY, b.innerWidth, b.innerHeight = b.draw(screen, b.x, b.y, b.width, b.height)
} else {
// Remember the inner rect.
b.innerX = -1
b.innerX, b.innerY, b.innerWidth, b.innerHeight = b.GetInnerRect()
}
}
// SetFocusFunc sets a callback function which is invoked when this primitive
// receives focus. Container primitives such as [Flex] or [Grid] will also be
// notified if one of their descendents receive focus directly. Note that this
// may result in a blur notification, immediately followed by a focus
// notification, when the focus is set to a different descendent of the
// container primitive.
//
// At this point, the order in which the focus callbacks are invoked during one
// draw cycle, is not defined. However, the blur callbacks are always invoked
// before the focus callbacks.
//
// Set to nil to remove the callback function.
func (b *Box) SetFocusFunc(callback func()) *Box {
b.focus = callback
return b
}
// SetBlurFunc sets a callback function which is invoked when this primitive
// loses focus. Container primitives such as [Flex] or [Grid] will also be
// notified if one of their descendents lose focus. Note that this may result in
// a blur notification, immediately followed by a focus notification, when the
// focus is set to a different different descendent of the container primitive.
//
// At this point, the order in which the blur callbacks are invoked during one
// draw cycle, is not defined. However, the blur callbacks are always invoked
// before the focus callbacks.
//
// Set to nil to remove the callback function.
func (b *Box) SetBlurFunc(callback func()) *Box {
b.blur = callback
return b
}
// Focus is called when this primitive directly receives focus.
func (b *Box) Focus(delegate func(p Primitive)) {
b.hasFocus = true
}
// focused is called when this primitive or one of its descendents receives
// focus.
func (b *Box) focused() {
if b.focus != nil {
b.focus()
}
}
// Blur is called when this primitive directly loses focus.
func (b *Box) Blur() {
b.hasFocus = false
}
// blurred is called when this primitive or one of its descendents loses focus.
func (b *Box) blurred() {
if b.blur != nil {
b.blur()
}
}
// HasFocus returns whether or not this primitive has focus.
func (b *Box) HasFocus() bool {
return b.Primitive.focusChain(nil)
}
// focusChain implements the [Primitive]'s focusChain method.
func (b *Box) focusChain(chain *[]Primitive) bool {
if !b.hasFocus {
return false
}
if chain != nil {
*chain = append(*chain, b.Primitive)
}
return true
}
================================================
FILE: button.go
================================================
package tview
import (
"github.com/gdamore/tcell/v2"
)
// Button is labeled box that triggers an action when selected.
//
// See https://github.com/rivo/tview/wiki/Button for an example.
type Button struct {
*Box
// If set to true, the button cannot be activated.
disabled bool
// The text to be displayed inside the button.
text string
// The button's style (when deactivated).
style tcell.Style
// The button's style (when activated).
activatedStyle tcell.Style
// The button's style (when disabled).
disabledStyle tcell.Style
// An optional function which is called when the button was selected.
selected func()
// An optional function which is called when the user leaves the button. A
// key is provided indicating which key was pressed to leave (tab or
// backtab).
exit func(tcell.Key)
}
// NewButton returns a new [Button].
func NewButton(label string) *Button {
box := NewBox()
box.SetRect(0, 0, TaggedStringWidth(label)+4, 1)
b := &Button{
Box: box,
text: label,
style: tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.PrimaryTextColor),
activatedStyle: tcell.StyleDefault.Background(Styles.PrimaryTextColor).Foreground(Styles.InverseTextColor),
disabledStyle: tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.ContrastSecondaryTextColor),
}
b.Box.Primitive = b
return b
}
// SetLabel sets the button text.
func (b *Button) SetLabel(label string) *Button {
b.text = label
return b
}
// GetLabel returns the button text.
func (b *Button) GetLabel() string {
return b.text
}
// SetLabelColor sets the color of the button text.
func (b *Button) SetLabelColor(color tcell.Color) *Button {
b.style = b.style.Foreground(color)
return b
}
// SetStyle sets the style of the button used when it is not focused.
func (b *Button) SetStyle(style tcell.Style) *Button {
b.style = style
return b
}
// SetLabelColorActivated sets the color of the button text when the button is
// in focus.
func (b *Button) SetLabelColorActivated(color tcell.Color) *Button {
b.activatedStyle = b.activatedStyle.Foreground(color)
return b
}
// SetBackgroundColorActivated sets the background color of the button text when
// the button is in focus.
func (b *Button) SetBackgroundColorActivated(color tcell.Color) *Button {
b.activatedStyle = b.activatedStyle.Background(color)
return b
}
// SetActivatedStyle sets the style of the button used when it is focused.
func (b *Button) SetActivatedStyle(style tcell.Style) *Button {
b.activatedStyle = style
return b
}
// SetDisabledStyle sets the style of the button used when it is disabled.
func (b *Button) SetDisabledStyle(style tcell.Style) *Button {
b.disabledStyle = style
return b
}
// SetDisabled sets whether or not the button is disabled. Disabled buttons
// cannot be activated.
//
// If the button is part of a form, you should set focus to the form itself
// after calling this function to set focus to the next non-disabled form item.
func (b *Button) SetDisabled(disabled bool) *Button {
b.disabled = disabled
return b
}
// GetDisabled returns whether or not the button is disabled.
func (b *Button) GetDisabled() bool {
return b.disabled
}
// IsDisabled is an alias for [Button.GetDisabled]. Only here for backwards
// compatibility.
func (b *Button) IsDisabled() bool {
return b.GetDisabled()
}
// SetSelectedFunc sets a handler which is called when the button was selected.
func (b *Button) SetSelectedFunc(handler func()) *Button {
b.selected = handler
return b
}
// SetExitFunc sets a handler which is called when the user leaves the button.
// The callback function is provided with the key that was pressed, which is one
// of the following:
//
// - KeyEscape: Leaving the button with no specific direction.
// - KeyTab: Move to the next field.
// - KeyBacktab: Move to the previous field.
func (b *Button) SetExitFunc(handler func(key tcell.Key)) *Button {
b.exit = handler
return b
}
// Draw draws this primitive onto the screen.
func (b *Button) Draw(screen tcell.Screen) {
// Draw the box.
style := b.style
if b.disabled {
style = b.disabledStyle
}
if b.HasFocus() && !b.disabled {
style = b.activatedStyle
}
_, backgroundColor, _ := style.Decompose()
b.SetBackgroundColor(backgroundColor)
b.Box.DrawForSubclass(screen, b)
// Draw label.
x, y, width, height := b.GetInnerRect()
if width > 0 && height > 0 {
y = y + height/2
printWithStyle(screen, b.text, x, y, 0, width, AlignCenter, style, true)
}
}
// InputHandler returns the handler for this primitive.
func (b *Button) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
return b.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) {
if b.disabled {
return
}
// Process key event.
switch key := event.Key(); key {
case tcell.KeyEnter: // Selected.
if b.selected != nil {
b.selected()
}
case tcell.KeyBacktab, tcell.KeyTab, tcell.KeyEscape: // Leave. No action.
if b.exit != nil {
b.exit(key)
}
}
})
}
// MouseHandler returns the mouse handler for this primitive.
func (b *Button) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
return b.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
if b.disabled {
return false, nil
}
if !b.InRect(event.Position()) {
return false, nil
}
// Process mouse event.
if action == MouseLeftDown {
setFocus(b)
consumed = true
} else if action == MouseLeftClick {
if b.selected != nil {
b.selected()
}
consumed = true
}
return
})
}
================================================
FILE: checkbox.go
================================================
package tview
import (
"github.com/gdamore/tcell/v2"
)
// Checkbox implements a simple box for boolean values which can be checked and
// unchecked.
//
// See https://github.com/rivo/tview/wiki/Checkbox for an example.
type Checkbox struct {
*Box
// Whether or not this checkbox is disabled/read-only.
disabled bool
// Whether or not this box is checked.
checked bool
// The text to be displayed before the input area.
label string
// The screen width of the label area. A value of 0 means use the width of
// the label text.
labelWidth int
// The label style.
labelStyle tcell.Style
// The style of the unchecked checkbox.
uncheckedStyle tcell.Style
// The style of the checked checkbox.
checkedStyle tcell.Style
// The style of the checkbox when it is currently focused.
focusStyle tcell.Style
// The string used to display an unchecked box.
uncheckedString string
// The string used to display a checked box.
checkedString string
// An optional function which is called when the user changes the checked
// state of this checkbox.
changed func(checked bool)
// An optional function which is called when the user indicated that they
// are done entering text. The key which was pressed is provided (tab,
// shift-tab, or escape).
done func(tcell.Key)
// A callback function set by the Form class and called when the user leaves
// this form item.
finished func(tcell.Key)
}
// NewCheckbox returns a new [Checkbox].
func NewCheckbox() *Checkbox {
c := &Checkbox{
Box: NewBox(),
labelStyle: tcell.StyleDefault.Foreground(Styles.SecondaryTextColor),
uncheckedStyle: tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.PrimaryTextColor),
checkedStyle: tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.PrimaryTextColor),
focusStyle: tcell.StyleDefault.Background(Styles.PrimaryTextColor).Foreground(Styles.ContrastBackgroundColor),
uncheckedString: " ",
checkedString: "X",
}
c.Box.Primitive = c
return c
}
// SetChecked sets the state of the checkbox. This also triggers the "changed"
// callback if the state changes with this call.
func (c *Checkbox) SetChecked(checked bool) *Checkbox {
if c.checked != checked {
if c.changed != nil {
c.changed(checked)
}
c.checked = checked
}
return c
}
// IsChecked returns whether or not the box is checked.
func (c *Checkbox) IsChecked() bool {
return c.checked
}
// SetLabel sets the text to be displayed before the input area.
func (c *Checkbox) SetLabel(label string) *Checkbox {
c.label = label
return c
}
// GetLabel returns the text to be displayed before the input area.
func (c *Checkbox) GetLabel() string {
return c.label
}
// SetLabelWidth sets the screen width of the label. A value of 0 will cause the
// primitive to use the width of the label string.
func (c *Checkbox) SetLabelWidth(width int) *Checkbox {
c.labelWidth = width
return c
}
// SetLabelColor sets the color of the label.
func (c *Checkbox) SetLabelColor(color tcell.Color) *Checkbox {
c.labelStyle = c.labelStyle.Foreground(color)
return c
}
// SetLabelStyle sets the style of the label.
func (c *Checkbox) SetLabelStyle(style tcell.Style) *Checkbox {
c.labelStyle = style
return c
}
// SetFieldBackgroundColor sets the background color of the input area.
func (c *Checkbox) SetFieldBackgroundColor(color tcell.Color) *Checkbox {
c.uncheckedStyle = c.uncheckedStyle.Background(color)
c.checkedStyle = c.checkedStyle.Background(color)
c.focusStyle = c.focusStyle.Foreground(color)
return c
}
// SetFieldTextColor sets the text color of the input area.
func (c *Checkbox) SetFieldTextColor(color tcell.Color) *Checkbox {
c.uncheckedStyle = c.uncheckedStyle.Foreground(color)
c.checkedStyle = c.checkedStyle.Foreground(color)
c.focusStyle = c.focusStyle.Background(color)
return c
}
// SetUncheckedStyle sets the style of the unchecked checkbox.
func (c *Checkbox) SetUncheckedStyle(style tcell.Style) *Checkbox {
c.uncheckedStyle = style
return c
}
// SetCheckedStyle sets the style of the checked checkbox.
func (c *Checkbox) SetCheckedStyle(style tcell.Style) *Checkbox {
c.checkedStyle = style
return c
}
// SetActivatedStyle sets the style of the checkbox when it is currently
// focused.
func (c *Checkbox) SetActivatedStyle(style tcell.Style) *Checkbox {
c.focusStyle = style
return c
}
// SetCheckedString sets the string to be displayed when the checkbox is
// checked (defaults to "X"). The string may contain color tags (consider
// adapting the checkbox's various styles accordingly). See [Escape] in
// case you want to display square brackets.
func (c *Checkbox) SetCheckedString(checked string) *Checkbox {
c.checkedString = checked
return c
}
// SetUncheckedString sets the string to be displayed when the checkbox is
// not checked (defaults to the empty space " "). The string may contain color
// tags (consider adapting the checkbox's various styles accordingly). See
// [Escape] in case you want to display square brackets.
func (c *Checkbox) SetUncheckedString(unchecked string) *Checkbox {
c.uncheckedString = unchecked
return c
}
// SetFormAttributes sets attributes shared by all form items.
func (c *Checkbox) SetFormAttributes(labelWidth int, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) FormItem {
c.labelWidth = labelWidth
c.SetLabelColor(labelColor)
c.backgroundColor = bgColor
c.SetFieldTextColor(fieldTextColor)
c.SetFieldBackgroundColor(fieldBgColor)
return c
}
// GetFieldWidth returns this primitive's field width.
func (c *Checkbox) GetFieldWidth() int {
return 1
}
// GetFieldHeight returns this primitive's field height.
func (c *Checkbox) GetFieldHeight() int {
return 1
}
// SetDisabled sets whether or not the item is disabled / read-only.
func (c *Checkbox) SetDisabled(disabled bool) FormItem {
c.disabled = disabled
if c.finished != nil {
c.finished(-1)
}
return c
}
// GetDisabled returns whether or not the item is disabled / read-only.
func (c *Checkbox) GetDisabled() bool {
return c.disabled
}
// SetChangedFunc sets a handler which is called when the checked state of this
// checkbox was changed. The handler function receives the new state.
func (c *Checkbox) SetChangedFunc(handler func(checked bool)) *Checkbox {
c.changed = handler
return c
}
// SetDoneFunc sets a handler which is called when the user is done using the
// checkbox. The callback function is provided with the key that was pressed,
// which is one of the following:
//
// - KeyEscape: Abort text input.
// - KeyTab: Move to the next field.
// - KeyBacktab: Move to the previous field.
func (c *Checkbox) SetDoneFunc(handler func(key tcell.Key)) *Checkbox {
c.done = handler
return c
}
// SetFinishedFunc sets a callback invoked when the user leaves this form item.
func (c *Checkbox) SetFinishedFunc(handler func(key tcell.Key)) FormItem {
c.finished = handler
return c
}
// Focus is called when this primitive receives focus.
func (c *Checkbox) Focus(delegate func(p Primitive)) {
// If we're part of a form and this item is disabled, there's nothing the
// user can do here so we're finished.
if c.finished != nil && c.disabled {
c.finished(-1)
return
}
c.Box.Focus(delegate)
}
// Draw draws this primitive onto the screen.
func (c *Checkbox) Draw(screen tcell.Screen) {
c.Box.DrawForSubclass(screen, c)
// Prepare
x, y, width, height := c.GetInnerRect()
rightLimit := x + width
if height < 1 || rightLimit <= x {
return
}
// Draw label.
_, labelBg, _ := c.labelStyle.Decompose()
if c.labelWidth > 0 {
labelWidth := c.labelWidth
if labelWidth > width {
labelWidth = width
}
printWithStyle(screen, c.label, x, y, 0, labelWidth, AlignLeft, c.labelStyle, labelBg == tcell.ColorDefault)
x += labelWidth
width -= labelWidth
} else {
_, _, drawnWidth := printWithStyle(screen, c.label, x, y, 0, width, AlignLeft, c.labelStyle, labelBg == tcell.ColorDefault)
x += drawnWidth
width -= drawnWidth
}
// Draw checkbox.
str := c.uncheckedString
style := c.uncheckedStyle
if c.checked {
str = c.checkedString
style = c.checkedStyle
}
if c.disabled {
style = style.Background(c.backgroundColor)
}
if c.HasFocus() {
style = c.focusStyle
}
printWithStyle(screen, str, x, y, 0, width, AlignLeft, style, c.disabled)
}
// InputHandler returns the handler for this primitive.
func (c *Checkbox) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
return c.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) {
if c.disabled {
return
}
// Process key event.
switch key := event.Key(); key {
case tcell.KeyRune, tcell.KeyEnter: // Check.
if key == tcell.KeyRune && event.Rune() != ' ' {
break
}
c.checked = !c.checked
if c.changed != nil {
c.changed(c.checked)
}
case tcell.KeyTab, tcell.KeyBacktab, tcell.KeyEscape: // We're done.
if c.done != nil {
c.done(key)
}
if c.finished != nil {
c.finished(key)
}
}
})
}
// MouseHandler returns the mouse handler for this primitive.
func (c *Checkbox) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
return c.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
if c.disabled {
return false, nil
}
x, y := event.Position()
_, rectY, _, _ := c.GetInnerRect()
if !c.InRect(x, y) {
return false, nil
}
// Process mouse event.
if y == rectY {
if action == MouseLeftDown {
setFocus(c)
consumed = true
} else if action == MouseLeftClick {
c.checked = !c.checked
if c.changed != nil {
c.changed(c.checked)
}
consumed = true
}
}
return
})
}
================================================
FILE: demos/box/README.md
================================================

================================================
FILE: demos/box/main.go
================================================
// Demo code for the Box primitive.
package main
import (
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
func main() {
box := tview.NewBox().
SetBorder(true).
SetBorderAttributes(tcell.AttrBold).
SetTitle("A [red]c[yellow]o[green]l[darkcyan]o[blue]r[darkmagenta]f[red]u[yellow]l[white] [black:red]c[:yellow]o[:green]l[:darkcyan]o[:blue]r[:darkmagenta]f[:red]u[:yellow]l[white:-] [::bu]title")
if err := tview.NewApplication().SetRoot(box, true).Run(); err != nil {
panic(err)
}
}
================================================
FILE: demos/button/README.md
================================================

================================================
FILE: demos/button/main.go
================================================
// Demo code for the Button primitive.
package main
import "github.com/rivo/tview"
func main() {
app := tview.NewApplication()
button := tview.NewButton("Hit Enter to close").SetSelectedFunc(func() {
app.Stop()
})
button.SetBorder(true).SetRect(0, 0, 22, 3)
if err := app.SetRoot(button, false).EnableMouse(true).Run(); err != nil {
panic(err)
}
}
================================================
FILE: demos/checkbox/README.md
================================================

================================================
FILE: demos/checkbox/main.go
================================================
// Demo code for the Checkbox primitive.
package main
import "github.com/rivo/tview"
func main() {
app := tview.NewApplication()
checkbox := tview.NewCheckbox().SetLabel("Hit Enter to check box: ")
if err := app.SetRoot(checkbox, true).EnableMouse(true).Run(); err != nil {
panic(err)
}
}
================================================
FILE: demos/dropdown/README.md
================================================

================================================
FILE: demos/dropdown/main.go
================================================
// Demo code for the DropDown primitive.
package main
import "github.com/rivo/tview"
func main() {
app := tview.NewApplication()
dropdown := tview.NewDropDown().
SetLabel("Select an option (hit Enter): ").
SetOptions([]string{"First", "Second", "Third", "Fourth", "Fifth"}, nil)
if err := app.SetRoot(dropdown, true).EnableMouse(true).Run(); err != nil {
panic(err)
}
}
================================================
FILE: demos/flex/README.md
================================================

================================================
FILE: demos/flex/main.go
================================================
// Demo code for the Flex primitive.
package main
import (
"github.com/rivo/tview"
)
func main() {
app := tview.NewApplication()
flex := tview.NewFlex().
AddItem(tview.NewBox().SetBorder(true).SetTitle("Left (1/2 x width of Top)"), 0, 1, false).
AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
AddItem(tview.NewBox().SetBorder(true).SetTitle("Top"), 0, 1, false).
AddItem(tview.NewBox().SetBorder(true).SetTitle("Middle (3 x height of Top)"), 0, 3, false).
AddItem(tview.NewBox().SetBorder(true).SetTitle("Bottom (5 rows)"), 5, 1, false), 0, 2, false).
AddItem(tview.NewBox().SetBorder(true).SetTitle("Right (20 cols)"), 20, 1, false)
if err := app.SetRoot(flex, true).EnableMouse(true).Run(); err != nil {
panic(err)
}
}
================================================
FILE: demos/form/README.md
================================================

================================================
FILE: demos/form/main.go
================================================
// Demo code for the Form primitive.
package main
import (
"github.com/rivo/tview"
)
func main() {
app := tview.NewApplication()
form := tview.NewForm().
AddDropDown("Title", []string{"Mr.", "Ms.", "Mrs.", "Dr.", "Prof."}, 0, nil).
AddInputField("First name", "", 20, nil, nil).
AddInputField("Last name", "", 20, nil, nil).
AddTextArea("Address", "", 40, 0, 0, nil).
AddTextView("Notes", "This is just a demo.\nYou can enter whatever you wish.", 40, 2, true, false).
AddCheckbox("Age 18+", false, nil).
AddPasswordField("Password", "", 10, '*', nil).
AddButton("Save", nil).
AddButton("Quit", func() {
app.Stop()
})
form.SetBorder(true).SetTitle("Enter some data").SetTitleAlign(tview.AlignLeft)
if err := app.SetRoot(form, true).EnableMouse(true).EnablePaste(true).Run(); err != nil {
panic(err)
}
}
================================================
FILE: demos/frame/README.md
================================================

================================================
FILE: demos/frame/main.go
================================================
// Demo code for the Frame primitive.
package main
import (
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
func main() {
app := tview.NewApplication()
frame := tview.NewFrame(tview.NewBox().SetBackgroundColor(tcell.ColorBlue)).
SetBorders(2, 2, 2, 2, 4, 4).
AddText("Header left", true, tview.AlignLeft, tcell.ColorWhite).
AddText("Header middle", true, tview.AlignCenter, tcell.ColorWhite).
AddText("Header right", true, tview.AlignRight, tcell.ColorWhite).
AddText("Header second middle", true, tview.AlignCenter, tcell.ColorRed).
AddText("Footer middle", false, tview.AlignCenter, tcell.ColorGreen).
AddText("Footer second middle", false, tview.AlignCenter, tcell.ColorGreen)
if err := app.SetRoot(frame, true).EnableMouse(true).Run(); err != nil {
panic(err)
}
}
================================================
FILE: demos/grid/README.md
================================================

================================================
FILE: demos/grid/main.go
================================================
// Demo code for the Grid primitive.
package main
import (
"github.com/rivo/tview"
)
func main() {
newPrimitive := func(text string) tview.Primitive {
return tview.NewTextView().
SetTextAlign(tview.AlignCenter).
SetText(text)
}
menu := newPrimitive("Menu")
main := newPrimitive("Main content")
sideBar := newPrimitive("Side Bar")
grid := tview.NewGrid().
SetRows(3, 0, 3).
SetColumns(30, 0, 30).
SetBorders(true).
AddItem(newPrimitive("Header"), 0, 0, 1, 3, 0, 0, false).
AddItem(newPrimitive("Footer"), 2, 0, 1, 3, 0, 0, false)
// Layout for screens narrower than 100 cells (menu and side bar are hidden).
grid.AddItem(menu, 0, 0, 0, 0, 0, 0, false).
AddItem(main, 1, 0, 1, 3, 0, 0, false).
AddItem(sideBar, 0, 0, 0, 0, 0, 0, false)
// Layout for screens wider than 100 cells.
grid.AddItem(menu, 1, 0, 1, 1, 0, 100, false).
AddItem(main, 1, 1, 1, 1, 0, 100, false).
AddItem(sideBar, 1, 2, 1, 1, 0, 100, false)
if err := tview.NewApplication().SetRoot(grid, true).EnableMouse(true).Run(); err != nil {
panic(err)
}
}
================================================
FILE: demos/image/README.md
================================================

================================================
FILE: demos/image/main.go
================================================
// Demo code for the Image primitive.
package main
import (
"bytes"
"encoding/base64"
"image/jpeg"
"image/png"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
const (
beach = `/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABgEGAAMAAAABAAIAAAESAAMAAAABAAEAAAEaAAUAAAABAAAAVgEbAAUAAAABAAAAXgEoAAMAAAABAAIAAIdpAAQAAAABAAAAZgAAAAAAAABIAAAAAQAAAEgAAAABAAKgAgAEAAAAAQAAAUCgAwAEAAAAAQAAAPAAAAAA/+EJIWh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNi4wLjAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIi8+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPD94cGFja2V0IGVuZD0idyI/PgD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/+IP0ElDQ19QUk9GSUxFAAEBAAAPwGFwcGwCEAAAbW50clJHQiBYWVogB+YADAAVAAsADQAEYWNzcEFQUEwAAAAAQVBQTAAAAAAAAAAAAAAAAAAAAAAAAPbWAAEAAAAA0y1hcHBsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARZGVzYwAAAVAAAABiZHNjbQAAAbQAAAScY3BydAAABlAAAAAjd3RwdAAABnQAAAAUclhZWgAABogAAAAUZ1hZWgAABpwAAAAUYlhZWgAABrAAAAAUclRSQwAABsQAAAgMYWFyZwAADtAAAAAgdmNndAAADvAAAAAwbmRpbgAADyAAAAA+bW1vZAAAD2AAAAAodmNncAAAD4gAAAA4YlRSQwAABsQAAAgMZ1RSQwAABsQAAAgMYWFiZwAADtAAAAAgYWFnZwAADtAAAAAgZGVzYwAAAAAAAAAIRGlzcGxheQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1sdWMAAAAAAAAAJgAAAAxockhSAAAAFAAAAdhrb0tSAAAADAAAAexuYk5PAAAAEgAAAfhpZAAAAAAAEgAAAgpodUhVAAAAFAAAAhxjc0NaAAAAFgAAAjBkYURLAAAAHAAAAkZubE5MAAAAFgAAAmJmaUZJAAAAEAAAAnhpdElUAAAAGAAAAohlc0VTAAAAFgAAAqByb1JPAAAAEgAAArZmckNBAAAAFgAAAshhcgAAAAAAFAAAAt51a1VBAAAAHAAAAvJoZUlMAAAAFgAAAw56aFRXAAAACgAAAyR2aVZOAAAADgAAAy5za1NLAAAAFgAAAzx6aENOAAAACgAAAyRydVJVAAAAJAAAA1JlbkdCAAAAFAAAA3ZmckZSAAAAFgAAA4ptcwAAAAAAEgAAA6BoaUlOAAAAEgAAA7J0aFRIAAAADAAAA8RjYUVTAAAAGAAAA9BlbkFVAAAAFAAAA3Zlc1hMAAAAEgAAArZkZURFAAAAEAAAA+hlblVTAAAAEgAAA/hwdEJSAAAAGAAABApwbFBMAAAAEgAABCJlbEdSAAAAIgAABDRzdlNFAAAAEAAABFZ0clRSAAAAFAAABGZwdFBUAAAAFgAABHpqYUpQAAAADAAABJAATABDAEQAIAB1ACAAYgBvAGoAac7st+wAIABMAEMARABGAGEAcgBnAGUALQBMAEMARABMAEMARAAgAFcAYQByAG4AYQBTAHoA7QBuAGUAcwAgAEwAQwBEAEIAYQByAGUAdgBuAP0AIABMAEMARABMAEMARAAtAGYAYQByAHYAZQBzAGsA5gByAG0ASwBsAGUAdQByAGUAbgAtAEwAQwBEAFYA5AByAGkALQBMAEMARABMAEMARAAgAGEAIABjAG8AbABvAHIAaQBMAEMARAAgAGEAIABjAG8AbABvAHIATABDAEQAIABjAG8AbABvAHIAQQBDAEwAIABjAG8AdQBsAGUAdQByIA8ATABDAEQAIAZFBkQGSAZGBikEGgQ+BDsETAQ+BEAEPgQyBDgEOQAgAEwAQwBEIA8ATABDAEQAIAXmBdEF4gXVBeAF2V9pgnIATABDAEQATABDAEQAIABNAOAAdQBGAGEAcgBlAGIAbgD9ACAATABDAEQEJgQyBDUEQgQ9BD4EOQAgBBYEGgAtBDQEOARBBD8EOwQ1BDkAQwBvAGwAbwB1AHIAIABMAEMARABMAEMARAAgAGMAbwB1AGwAZQB1AHIAVwBhAHIAbgBhACAATABDAEQJMAkCCRcJQAkoACAATABDAEQATABDAEQAIA4qDjUATABDAEQAIABlAG4AIABjAG8AbABvAHIARgBhAHIAYgAtAEwAQwBEAEMAbwBsAG8AcgAgAEwAQwBEAEwAQwBEACAAQwBvAGwAbwByAGkAZABvAEsAbwBsAG8AcgAgAEwAQwBEA4gDswPHA8EDyQO8A7cAIAO/A7gDzAO9A7cAIABMAEMARABGAOQAcgBnAC0ATABDAEQAUgBlAG4AawBsAGkAIABMAEMARABMAEMARAAgAGEAIABjAG8AcgBlAHMwqzDpMPwATABDAER0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBJbmMuLCAyMDIyAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAACD3wAAPb////+7WFlaIAAAAAAAAEq/AACxNwAACrlYWVogAAAAAAAAKDgAABELAADIuWN1cnYAAAAAAAAEAAAAAAUACgAPABQAGQAeACMAKAAtADIANgA7AEAARQBKAE8AVABZAF4AYwBoAG0AcgB3AHwAgQCGAIsAkACVAJoAnwCjAKgArQCyALcAvADBAMYAywDQANUA2wDgAOUA6wDwAPYA+wEBAQcBDQETARkBHwElASsBMgE4AT4BRQFMAVIBWQFgAWcBbgF1AXwBgwGLAZIBmgGhAakBsQG5AcEByQHRAdkB4QHpAfIB+gIDAgwC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`
chart = `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`
)
func main() {
app := tview.NewApplication()
image := tview.NewImage()
b, _ := base64.StdEncoding.DecodeString(beach)
photo, _ := jpeg.Decode(bytes.NewReader(b))
b, _ = base64.StdEncoding.DecodeString(chart)
graphics, _ := png.Decode(bytes.NewReader(b))
image.SetImage(photo)
imgType := tview.NewList().
ShowSecondaryText(false).
AddItem("Photo", "", 0, func() { image.SetImage(photo) }).
AddItem("Graphics", "", 0, func() { image.SetImage(graphics) })
imgType.SetTitle("Image Type").SetBorder(true)
colors := tview.NewList().
ShowSecondaryText(false).
AddItem("2 colors", "", 0, func() { image.SetColors(2) }).
AddItem("8 colors", "", 0, func() { image.SetColors(8) }).
AddItem("256 colors", "", 0, func() { image.SetColors(256) }).
AddItem("True-color", "", 0, func() { image.SetColors(tview.TrueColor) })
colors.SetTitle("Colors").SetBorder(true)
for i, c := range []int{2, 8, 256, tview.TrueColor} {
if c == image.GetColors() {
colors.SetCurrentItem(i)
break
}
}
dithering := tview.NewList().
ShowSecondaryText(false).
AddItem("None", "", 0, func() { image.SetDithering(tview.DitheringNone) }).
AddItem("Floyd-Steinberg", "", 0, func() { image.SetDithering(tview.DitheringFloydSteinberg) }).
SetCurrentItem(1)
dithering.SetTitle("Dithering").SetBorder(true)
selections := []*tview.Box{imgType.Box, colors.Box, dithering.Box}
for i, box := range selections {
(func(index int) {
box.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyTab:
app.SetFocus(selections[(index+1)%len(selections)])
return nil
case tcell.KeyBacktab:
app.SetFocus(selections[(index+len(selections)-1)%len(selections)])
return nil
}
return event
})
})(i)
}
grid := tview.NewGrid().
SetBorders(false).
SetColumns(18, -1).
SetRows(4, 6, 4, -1).
AddItem(imgType, 0, 0, 1, 1, 0, 0, true).
AddItem(colors, 1, 0, 1, 1, 0, 0, false).
AddItem(dithering, 2, 0, 1, 1, 0, 0, false).
AddItem(image, 0, 1, 4, 1, 0, 0, false)
if err := app.SetRoot(grid, true).EnableMouse(true).Run(); err != nil {
panic(err)
}
}
================================================
FILE: demos/inputfield/README.md
================================================

================================================
FILE: demos/inputfield/autocomplete/main.go
================================================
package main
import (
"strings"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
// 1,000 most common English words.
const wordList = "ability,able,about,above,accept,according,account,across,act,action,activity,actually,add,address,administration,admit,adult,affect,after,again,against,age,agency,agent,ago,agree,agreement,ahead,air,all,allow,almost,alone,along,already,also,although,always,American,among,amount,analysis,and,animal,another,answer,any,anyone,anything,appear,apply,approach,area,argue,arm,around,arrive,art,article,artist,as,ask,assume,at,attack,attention,attorney,audience,author,authority,available,avoid,away,baby,back,bad,bag,ball,bank,bar,base,be,beat,beautiful,because,become,bed,before,begin,behavior,behind,believe,benefit,best,better,between,beyond,big,bill,billion,bit,black,blood,blue,board,body,book,born,both,box,boy,break,bring,brother,budget,build,building,business,but,buy,by,call,camera,campaign,can,cancer,candidate,capital,car,card,care,career,carry,case,catch,cause,cell,center,central,century,certain,certainly,chair,challenge,chance,change,character,charge,check,child,choice,choose,church,citizen,city,civil,claim,class,clear,clearly,close,coach,cold,collection,college,color,come,commercial,common,community,company,compare,computer,concern,condition,conference,Congress,consider,consumer,contain,continue,control,cost,could,country,couple,course,court,cover,create,crime,cultural,culture,cup,current,customer,cut,dark,data,daughter,day,dead,deal,death,debate,decade,decide,decision,deep,defense,degree,Democrat,democratic,describe,design,despite,detail,determine,develop,development,die,difference,different,difficult,dinner,direction,director,discover,discuss,discussion,disease,do,doctor,dog,door,down,draw,dream,drive,drop,drug,during,each,early,east,easy,eat,economic,economy,edge,education,effect,effort,eight,either,election,else,employee,end,energy,enjoy,enough,enter,entire,environment,environmental,especially,establish,even,evening,event,ever,every,everybody,everyone,everything,evidence,exactly,example,executive,exist,expect,experience,expert,explain,eye,face,fact,factor,fail,fall,family,far,fast,father,fear,federal,feel,feeling,few,field,fight,figure,fill,film,final,finally,financial,find,fine,finger,finish,fire,firm,first,fish,five,floor,fly,focus,follow,food,foot,for,force,foreign,forget,form,former,forward,four,free,friend,from,front,full,fund,future,game,garden,gas,general,generation,get,girl,give,glass,go,goal,good,government,great,green,ground,group,grow,growth,guess,gun,guy,hair,half,hand,hang,happen,happy,hard,have,he,head,health,hear,heart,heat,heavy,help,her,here,herself,high,him,himself,his,history,hit,hold,home,hope,hospital,hot,hotel,hour,house,how,however,huge,human,hundred,husband,idea,identify,if,image,imagine,impact,important,improve,in,include,including,increase,indeed,indicate,individual,industry,information,inside,instead,institution,interest,interesting,international,interview,into,investment,involve,issue,it,item,its,itself,job,join,just,keep,key,kid,kill,kind,kitchen,know,knowledge,land,language,large,last,late,later,laugh,law,lawyer,lay,lead,leader,learn,least,leave,left,leg,legal,less,let,letter,level,lie,life,light,like,likely,line,list,listen,little,live,local,long,look,lose,loss,lot,love,low,machine,magazine,main,maintain,major,majority,make,man,manage,management,manager,many,market,marriage,material,matter,may,maybe,me,mean,measure,media,medical,meet,meeting,member,memory,mention,message,method,middle,might,military,million,mind,minute,miss,mission,model,modern,moment,money,month,more,morning,most,mother,mouth,move,movement,movie,Mr,Mrs,much,music,must,my,myself,n't,name,nation,national,natural,nature,near,nearly,necessary,need,network,never,new,news,newspaper,next,nice,night,no,none,nor,north,not,note,nothing,notice,now,number,occur,of,off,offer,office,officer,official,often,oh,oil,ok,old,on,once,one,only,onto,open,operation,opportunity,option,or,order,organization,other,others,our,out,outside,over,own,owner,page,pain,painting,paper,parent,part,participant,particular,particularly,partner,party,pass,past,patient,pattern,pay,peace,people,per,perform,performance,perhaps,period,person,personal,phone,physical,pick,picture,piece,place,plan,plant,play,player,PM,point,police,policy,political,politics,poor,popular,population,position,positive,possible,power,practice,prepare,present,president,pressure,pretty,prevent,price,private,probably,problem,process,produce,product,production,professional,professor,program,project,property,protect,prove,provide,public,pull,purpose,push,put,quality,question,quickly,quite,race,radio,raise,range,rate,rather,reach,read,ready,real,reality,realize,really,reason,receive,recent,recently,recognize,record,red,reduce,reflect,region,relate,relationship,religious,remain,remember,remove,report,represent,Republican,require,research,resource,respond,response,responsibility,rest,result,return,reveal,rich,right,rise,risk,road,rock,role,room,rule,run,safe,same,save,say,scene,school,science,scientist,score,sea,season,seat,second,section,security,see,seek,seem,sell,send,senior,sense,series,serious,serve,service,set,seven,several,sex,sexual,shake,share,she,shoot,short,shot,should,shoulder,show,side,sign,significant,similar,simple,simply,since,sing,single,sister,sit,site,situation,six,size,skill,skin,small,smile,so,social,society,soldier,some,somebody,someone,something,sometimes,son,song,soon,sort,sound,source,south,southern,space,speak,special,specific,speech,spend,sport,spring,staff,stage,stand,standard,star,start,state,statement,station,stay,step,still,stock,stop,store,story,strategy,street,strong,structure,student,study,stuff,style,subject,success,successful,such,suddenly,suffer,suggest,summer,support,sure,surface,system,table,take,talk,task,tax,teach,teacher,team,technology,television,tell,ten,tend,term,test,than,thank,that,the,their,them,themselves,then,theory,there,these,they,thing,think,third,this,those,though,thought,thousand,threat,three,through,throughout,throw,thus,time,to,today,together,tonight,too,top,total,tough,toward,town,trade,traditional,training,travel,treat,treatment,tree,trial,trip,trouble,true,truth,try,turn,TV,two,type,under,understand,unit,until,up,upon,us,use,usually,value,various,very,victim,view,violence,visit,voice,vote,wait,walk,wall,want,war,watch,water,way,we,weapon,wear,week,weight,well,west,western,what,whatever,when,where,whether,which,while,white,who,whole,whom,whose,why,wide,wife,will,win,wind,window,wish,with,within,without,woman,wonder,word,work,worker,world,worry,would,write,writer,wrong,yard,yeah,year,yes,yet,you,young,your,yourself"
func main() {
words := strings.Split(wordList, ",")
app := tview.NewApplication()
inputField := tview.NewInputField().
SetLabel("Enter a word: ").
SetFieldWidth(30).
SetDoneFunc(func(key tcell.Key) {
app.Stop()
})
inputField.SetAutocompleteFunc(func(currentText string) (entries []string) {
if len(currentText) == 0 {
return
}
for _, word := range words {
if strings.HasPrefix(strings.ToLower(word), strings.ToLower(currentText)) {
entries = append(entries, word)
}
}
if len(entries) <= 1 {
entries = nil
}
return
})
inputField.SetAutocompletedFunc(func(text string, index, source int) bool {
if source != tview.AutocompletedNavigate {
inputField.SetText(text)
}
return source == tview.AutocompletedEnter || source == tview.AutocompletedClick
})
if err := app.EnableMouse(true).SetRoot(inputField, true).Run(); err != nil {
panic(err)
}
}
================================================
FILE: demos/inputfield/autocompleteasync/main.go
================================================
package main
import (
"encoding/json"
"net/http"
"net/url"
"strings"
"sync"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
type company struct {
Name string `json:"name"`
}
func main() {
app := tview.NewApplication()
inputField := tview.NewInputField().
SetLabel("Enter a company name: ").
SetFieldWidth(30).
SetDoneFunc(func(key tcell.Key) {
app.Stop()
})
// Set up autocomplete function.
var mutex sync.Mutex
prefixMap := make(map[string][]string)
inputField.SetAutocompleteFunc(func(currentText string) []string {
// Ignore empty text.
prefix := strings.TrimSpace(strings.ToLower(currentText))
if prefix == "" {
return nil
}
// Do we have entries for this text already?
mutex.Lock()
defer mutex.Unlock()
entries, ok := prefixMap[prefix]
if ok {
return entries
}
// No entries yet. Issue a request to the API in a goroutine.
go func() {
// Ignore errors in this demo.
url := "https://autocomplete.clearbit.com/v1/companies/suggest?query=" + url.QueryEscape(prefix)
res, err := http.Get(url)
if err != nil {
return
}
// Store the result in the prefix map.
var companies []*company
dec := json.NewDecoder(res.Body)
if err := dec.Decode(&companies); err != nil {
return
}
entries := make([]string, 0, len(companies))
OuterLoop:
for _, c := range companies {
for _, entry := range entries { // Eliminate duplicates.
if strings.EqualFold(entry, c.Name) {
continue OuterLoop
}
}
entries = append(entries, c.Name)
}
mutex.Lock()
prefixMap[prefix] = entries
mutex.Unlock()
// Trigger an update to the input field.
inputField.Autocomplete()
// Also redraw the screen.
app.Draw()
}()
return nil
})
if err := app.EnableMouse(true).SetRoot(inputField, true).Run(); err != nil {
panic(err)
}
}
================================================
FILE: demos/inputfield/main.go
================================================
// Demo code for the InputField primitive.
package main
import (
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
func main() {
app := tview.NewApplication()
inputField := tview.NewInputField().
SetLabel("Enter a number: ").
SetPlaceholder("E.g. 1234").
SetFieldWidth(10).
SetAcceptanceFunc(tview.InputFieldInteger).
SetDoneFunc(func(key tcell.Key) {
app.Stop()
})
if err := app.SetRoot(inputField, true).EnableMouse(true).EnablePaste(true).Run(); err != nil {
panic(err)
}
}
================================================
FILE: demos/list/README.md
================================================

================================================
FILE: demos/list/main.go
================================================
// Demo code for the List primitive.
package main
import (
"github.com/rivo/tview"
)
func main() {
app := tview.NewApplication()
list := tview.NewList().
AddItem("List item 1", "Some explanatory text", 'a', nil).
AddItem("List item 2", "Some explanatory text", 'b', nil).
AddItem("List item 3", "Some explanatory text", 'c', nil).
AddItem("List item 4", "Some explanatory text", 'd', nil).
AddItem("Quit", "Press to exit", 'q', func() {
app.Stop()
})
if err := app.SetRoot(list, true).EnableMouse(true).Run(); err != nil {
panic(err)
}
}
================================================
FILE: demos/modal/README.md
================================================

================================================
gitextract_rl0cd57v/ ├── .github/ │ └── FUNDING.yml ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── ansi.go ├── application.go ├── borders.go ├── box.go ├── button.go ├── checkbox.go ├── demos/ │ ├── box/ │ │ ├── README.md │ │ └── main.go │ ├── button/ │ │ ├── README.md │ │ └── main.go │ ├── checkbox/ │ │ ├── README.md │ │ └── main.go │ ├── dropdown/ │ │ ├── README.md │ │ └── main.go │ ├── flex/ │ │ ├── README.md │ │ └── main.go │ ├── form/ │ │ ├── README.md │ │ └── main.go │ ├── frame/ │ │ ├── README.md │ │ └── main.go │ ├── grid/ │ │ ├── README.md │ │ └── main.go │ ├── image/ │ │ ├── README.md │ │ └── main.go │ ├── inputfield/ │ │ ├── README.md │ │ ├── autocomplete/ │ │ │ └── main.go │ │ ├── autocompleteasync/ │ │ │ └── main.go │ │ └── main.go │ ├── list/ │ │ ├── README.md │ │ └── main.go │ ├── modal/ │ │ ├── README.md │ │ └── main.go │ ├── pages/ │ │ ├── README.md │ │ └── main.go │ ├── presentation/ │ │ ├── center.go │ │ ├── code.go │ │ ├── colors.go │ │ ├── cover.go │ │ ├── end.go │ │ ├── flex.go │ │ ├── form.go │ │ ├── grid.go │ │ ├── helloworld.go │ │ ├── inputfield.go │ │ ├── introduction.go │ │ ├── main.go │ │ ├── table.go │ │ ├── textview.go │ │ └── treeview.go │ ├── primitive/ │ │ ├── README.md │ │ └── main.go │ ├── table/ │ │ ├── README.md │ │ ├── main.go │ │ └── virtualtable/ │ │ ├── README.md │ │ └── main.go │ ├── textarea/ │ │ ├── README.md │ │ └── main.go │ ├── textview/ │ │ ├── README.md │ │ ├── chat/ │ │ │ ├── README.md │ │ │ ├── chain.txt │ │ │ └── main.go │ │ └── main.go │ ├── treeview/ │ │ ├── README.md │ │ └── main.go │ └── unicode/ │ ├── README.md │ └── main.go ├── doc.go ├── dropdown.go ├── flex.go ├── form.go ├── frame.go ├── go.mod ├── go.sum ├── grid.go ├── image.go ├── inputfield.go ├── list.go ├── modal.go ├── pages.go ├── primitive.go ├── semigraphics.go ├── strings.go ├── styles.go ├── table.go ├── textarea.go ├── textview.go ├── treeview.go └── util.go
SYMBOL INDEX (983 symbols across 62 files)
FILE: ansi.go
constant ansiText (line 13) | ansiText = iota
constant ansiEscape (line 14) | ansiEscape
constant ansiSubstring (line 15) | ansiSubstring
constant ansiControlSequence (line 16) | ansiControlSequence
type ansi (line 21) | type ansi struct
method Write (line 49) | func (a *ansi) Write(text []byte) (int, error) {
function ANSIWriter (line 37) | func ANSIWriter(writer io.Writer) io.Writer {
function TranslateANSI (line 278) | func TranslateANSI(text string) string {
FILE: application.go
constant queueSize (line 13) | queueSize = 100
constant redrawPause (line 16) | redrawPause = 50 * time.Millisecond
type MouseAction (line 24) | type MouseAction
constant MouseMove (line 28) | MouseMove MouseAction = iota
constant MouseLeftDown (line 29) | MouseLeftDown
constant MouseLeftUp (line 30) | MouseLeftUp
constant MouseLeftClick (line 31) | MouseLeftClick
constant MouseLeftDoubleClick (line 32) | MouseLeftDoubleClick
constant MouseMiddleDown (line 33) | MouseMiddleDown
constant MouseMiddleUp (line 34) | MouseMiddleUp
constant MouseMiddleClick (line 35) | MouseMiddleClick
constant MouseMiddleDoubleClick (line 36) | MouseMiddleDoubleClick
constant MouseRightDown (line 37) | MouseRightDown
constant MouseRightUp (line 38) | MouseRightUp
constant MouseRightClick (line 39) | MouseRightClick
constant MouseRightDoubleClick (line 40) | MouseRightDoubleClick
constant MouseScrollUp (line 41) | MouseScrollUp
constant MouseScrollDown (line 42) | MouseScrollDown
constant MouseScrollLeft (line 43) | MouseScrollLeft
constant MouseScrollRight (line 44) | MouseScrollRight
constant MouseConsumed (line 49) | MouseConsumed
type queuedUpdate (line 55) | type queuedUpdate struct
type Application (line 72) | type Application struct
method SetInputCapture (line 161) | func (a *Application) SetInputCapture(capture func(event *tcell.EventK...
method GetInputCapture (line 168) | func (a *Application) GetInputCapture() func(event *tcell.EventKey) *t...
method SetMouseCapture (line 178) | func (a *Application) SetMouseCapture(capture func(event *tcell.EventM...
method GetMouseCapture (line 185) | func (a *Application) GetMouseCapture() func(event *tcell.EventMouse, ...
method SetScreen (line 197) | func (a *Application) SetScreen(screen tcell.Screen) *Application {
method SetTitle (line 223) | func (a *Application) SetTitle(title string) *Application {
method EnableMouse (line 234) | func (a *Application) EnableMouse(enable bool) *Application {
method EnablePaste (line 254) | func (a *Application) EnablePaste(enable bool) *Application {
method Run (line 276) | func (a *Application) Run() error {
method fireMouseActions (line 525) | func (a *Application) fireMouseActions(event *tcell.EventMouse) (consu...
method Stop (line 623) | func (a *Application) Stop() {
method Suspend (line 642) | func (a *Application) Suspend(f func()) bool {
method Draw (line 683) | func (a *Application) Draw() *Application {
method ForceDraw (line 697) | func (a *Application) ForceDraw() *Application {
method draw (line 702) | func (a *Application) draw() *Application {
method Sync (line 752) | func (a *Application) Sync() *Application {
method SetBeforeDrawFunc (line 774) | func (a *Application) SetBeforeDrawFunc(handler func(screen tcell.Scre...
method GetBeforeDrawFunc (line 781) | func (a *Application) GetBeforeDrawFunc() func(screen tcell.Screen) bo...
method SetAfterDrawFunc (line 789) | func (a *Application) SetAfterDrawFunc(handler func(screen tcell.Scree...
method GetAfterDrawFunc (line 796) | func (a *Application) GetAfterDrawFunc() func(screen tcell.Screen) {
method SetRoot (line 807) | func (a *Application) SetRoot(root Primitive, fullscreen bool) *Applic...
method ResizeToFullScreen (line 823) | func (a *Application) ResizeToFullScreen(p Primitive) *Application {
method SetFocus (line 838) | func (a *Application) SetFocus(p Primitive) *Application {
method GetFocus (line 891) | func (a *Application) GetFocus() Primitive {
method QueueUpdate (line 915) | func (a *Application) QueueUpdate(f func()) *Application {
method QueueUpdateDraw (line 924) | func (a *Application) QueueUpdateDraw(f func()) *Application {
method QueueEvent (line 935) | func (a *Application) QueueEvent(event tcell.Event) *Application {
function NewApplication (line 134) | func NewApplication() *Application {
FILE: box.go
type Box (line 16) | type Box struct
method SetBorderPadding (line 100) | func (b *Box) SetBorderPadding(top, bottom, left, right int) *Box {
method GetRect (line 107) | func (b *Box) GetRect() (int, int, int, int) {
method GetInnerRect (line 114) | func (b *Box) GetInnerRect() (int, int, int, int) {
method SetRect (line 143) | func (b *Box) SetRect(x, y, width, height int) {
method SetDrawFunc (line 167) | func (b *Box) SetDrawFunc(handler func(screen tcell.Screen, x, y, widt...
method GetDrawFunc (line 174) | func (b *Box) GetDrawFunc() func(screen tcell.Screen, x, y, width, hei...
method SetBoxResizeFunc (line 181) | func (b *Box) SetBoxResizeFunc(handler func()) *Box {
method SetContentResizeFunc (line 190) | func (b *Box) SetContentResizeFunc(handler func()) *Box {
method WrapInputHandler (line 200) | func (b *Box) WrapInputHandler(inputHandler func(*tcell.EventKey, func...
method InputHandler (line 212) | func (b *Box) InputHandler() func(event *tcell.EventKey, setFocus func...
method WrapPasteHandler (line 217) | func (b *Box) WrapPasteHandler(pasteHandler func(string, func(p Primit...
method PasteHandler (line 226) | func (b *Box) PasteHandler() func(pastedText string, setFocus func(p P...
method SetInputCapture (line 243) | func (b *Box) SetInputCapture(capture func(event *tcell.EventKey) *tce...
method GetInputCapture (line 250) | func (b *Box) GetInputCapture() func(event *tcell.EventKey) *tcell.Eve...
method WrapMouseHandler (line 259) | func (b *Box) WrapMouseHandler(mouseHandler func(MouseAction, *tcell.E...
method MouseHandler (line 276) | func (b *Box) MouseHandler() func(action MouseAction, event *tcell.Eve...
method SetMouseCapture (line 302) | func (b *Box) SetMouseCapture(capture func(action MouseAction, event *...
method InRect (line 309) | func (b *Box) InRect(x, y int) bool {
method InInnerRect (line 316) | func (b *Box) InInnerRect(x, y int) bool {
method GetMouseCapture (line 323) | func (b *Box) GetMouseCapture() func(action MouseAction, event *tcell....
method SetBackgroundColor (line 328) | func (b *Box) SetBackgroundColor(color tcell.Color) *Box {
method SetBorder (line 336) | func (b *Box) SetBorder(show bool) *Box {
method SetBorderStyle (line 347) | func (b *Box) SetBorderStyle(style tcell.Style) *Box {
method SetBorderColor (line 353) | func (b *Box) SetBorderColor(color tcell.Color) *Box {
method SetBorderAttributes (line 362) | func (b *Box) SetBorderAttributes(attr tcell.AttrMask) *Box {
method GetBorderAttributes (line 368) | func (b *Box) GetBorderAttributes() tcell.AttrMask {
method GetBorderColor (line 374) | func (b *Box) GetBorderColor() tcell.Color {
method GetBackgroundColor (line 380) | func (b *Box) GetBackgroundColor() tcell.Color {
method SetTitle (line 385) | func (b *Box) SetTitle(title string) *Box {
method GetTitle (line 391) | func (b *Box) GetTitle() string {
method SetTitleColor (line 396) | func (b *Box) SetTitleColor(color tcell.Color) *Box {
method SetTitleAlign (line 403) | func (b *Box) SetTitleAlign(align int) *Box {
method Draw (line 409) | func (b *Box) Draw(screen tcell.Screen) {
method DrawForSubclass (line 419) | func (b *Box) DrawForSubclass(screen tcell.Screen, p Primitive) {
method SetFocusFunc (line 503) | func (b *Box) SetFocusFunc(callback func()) *Box {
method SetBlurFunc (line 519) | func (b *Box) SetBlurFunc(callback func()) *Box {
method Focus (line 525) | func (b *Box) Focus(delegate func(p Primitive)) {
method focused (line 531) | func (b *Box) focused() {
method Blur (line 538) | func (b *Box) Blur() {
method blurred (line 543) | func (b *Box) blurred() {
method HasFocus (line 550) | func (b *Box) HasFocus() bool {
method focusChain (line 555) | func (b *Box) focusChain(chain *[]Primitive) bool {
function NewBox (line 85) | func NewBox() *Box {
FILE: button.go
type Button (line 10) | type Button struct
method SetLabel (line 53) | func (b *Button) SetLabel(label string) *Button {
method GetLabel (line 59) | func (b *Button) GetLabel() string {
method SetLabelColor (line 64) | func (b *Button) SetLabelColor(color tcell.Color) *Button {
method SetStyle (line 70) | func (b *Button) SetStyle(style tcell.Style) *Button {
method SetLabelColorActivated (line 77) | func (b *Button) SetLabelColorActivated(color tcell.Color) *Button {
method SetBackgroundColorActivated (line 84) | func (b *Button) SetBackgroundColorActivated(color tcell.Color) *Button {
method SetActivatedStyle (line 90) | func (b *Button) SetActivatedStyle(style tcell.Style) *Button {
method SetDisabledStyle (line 96) | func (b *Button) SetDisabledStyle(style tcell.Style) *Button {
method SetDisabled (line 106) | func (b *Button) SetDisabled(disabled bool) *Button {
method GetDisabled (line 112) | func (b *Button) GetDisabled() bool {
method IsDisabled (line 118) | func (b *Button) IsDisabled() bool {
method SetSelectedFunc (line 123) | func (b *Button) SetSelectedFunc(handler func()) *Button {
method SetExitFunc (line 135) | func (b *Button) SetExitFunc(handler func(key tcell.Key)) *Button {
method Draw (line 141) | func (b *Button) Draw(screen tcell.Screen) {
method InputHandler (line 163) | func (b *Button) InputHandler() func(event *tcell.EventKey, setFocus f...
method MouseHandler (line 184) | func (b *Button) MouseHandler() func(action MouseAction, event *tcell....
function NewButton (line 38) | func NewButton(label string) *Button {
FILE: checkbox.go
type Checkbox (line 11) | type Checkbox struct
method SetChecked (line 76) | func (c *Checkbox) SetChecked(checked bool) *Checkbox {
method IsChecked (line 87) | func (c *Checkbox) IsChecked() bool {
method SetLabel (line 92) | func (c *Checkbox) SetLabel(label string) *Checkbox {
method GetLabel (line 98) | func (c *Checkbox) GetLabel() string {
method SetLabelWidth (line 104) | func (c *Checkbox) SetLabelWidth(width int) *Checkbox {
method SetLabelColor (line 110) | func (c *Checkbox) SetLabelColor(color tcell.Color) *Checkbox {
method SetLabelStyle (line 116) | func (c *Checkbox) SetLabelStyle(style tcell.Style) *Checkbox {
method SetFieldBackgroundColor (line 122) | func (c *Checkbox) SetFieldBackgroundColor(color tcell.Color) *Checkbox {
method SetFieldTextColor (line 130) | func (c *Checkbox) SetFieldTextColor(color tcell.Color) *Checkbox {
method SetUncheckedStyle (line 138) | func (c *Checkbox) SetUncheckedStyle(style tcell.Style) *Checkbox {
method SetCheckedStyle (line 144) | func (c *Checkbox) SetCheckedStyle(style tcell.Style) *Checkbox {
method SetActivatedStyle (line 151) | func (c *Checkbox) SetActivatedStyle(style tcell.Style) *Checkbox {
method SetCheckedString (line 160) | func (c *Checkbox) SetCheckedString(checked string) *Checkbox {
method SetUncheckedString (line 169) | func (c *Checkbox) SetUncheckedString(unchecked string) *Checkbox {
method SetFormAttributes (line 175) | func (c *Checkbox) SetFormAttributes(labelWidth int, labelColor, bgCol...
method GetFieldWidth (line 185) | func (c *Checkbox) GetFieldWidth() int {
method GetFieldHeight (line 190) | func (c *Checkbox) GetFieldHeight() int {
method SetDisabled (line 195) | func (c *Checkbox) SetDisabled(disabled bool) FormItem {
method GetDisabled (line 204) | func (c *Checkbox) GetDisabled() bool {
method SetChangedFunc (line 210) | func (c *Checkbox) SetChangedFunc(handler func(checked bool)) *Checkbox {
method SetDoneFunc (line 222) | func (c *Checkbox) SetDoneFunc(handler func(key tcell.Key)) *Checkbox {
method SetFinishedFunc (line 228) | func (c *Checkbox) SetFinishedFunc(handler func(key tcell.Key)) FormIt...
method Focus (line 234) | func (c *Checkbox) Focus(delegate func(p Primitive)) {
method Draw (line 246) | func (c *Checkbox) Draw(screen tcell.Screen) {
method InputHandler (line 289) | func (c *Checkbox) InputHandler() func(event *tcell.EventKey, setFocus...
method MouseHandler (line 317) | func (c *Checkbox) MouseHandler() func(action MouseAction, event *tcel...
function NewCheckbox (line 60) | func NewCheckbox() *Checkbox {
FILE: demos/box/main.go
function main (line 9) | func main() {
FILE: demos/button/main.go
function main (line 6) | func main() {
FILE: demos/checkbox/main.go
function main (line 6) | func main() {
FILE: demos/dropdown/main.go
function main (line 6) | func main() {
FILE: demos/flex/main.go
function main (line 8) | func main() {
FILE: demos/form/main.go
function main (line 8) | func main() {
FILE: demos/frame/main.go
function main (line 9) | func main() {
FILE: demos/grid/main.go
function main (line 8) | func main() {
FILE: demos/image/main.go
constant beach (line 16) | beach = `/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABgEGAAMAAAA...
constant chart (line 18) | chart = `iVBORw0KGgoAAAANSUhEUgAAAWgAAAD0CAIAAAA5VCsOAAAMP2lDQ1BJQ0MgUHJ...
function main (line 21) | func main() {
FILE: demos/inputfield/autocomplete/main.go
constant wordList (line 11) | wordList = "ability,able,about,above,accept,according,account,across,act...
function main (line 13) | func main() {
FILE: demos/inputfield/autocompleteasync/main.go
type company (line 14) | type company struct
function main (line 18) | func main() {
FILE: demos/inputfield/main.go
function main (line 9) | func main() {
FILE: demos/list/main.go
function main (line 8) | func main() {
FILE: demos/modal/main.go
function main (line 8) | func main() {
FILE: demos/pages/main.go
constant pageCount (line 10) | pageCount = 5
function main (line 12) | func main() {
FILE: demos/presentation/center.go
function Center (line 7) | func Center(width, height int, p tview.Primitive) tview.Primitive {
FILE: demos/presentation/code.go
constant codeWidth (line 10) | codeWidth = 56
function Code (line 14) | func Code(p tview.Primitive, width, height int, code string) tview.Primi...
FILE: demos/presentation/colors.go
constant colorsText (line 10) | colorsText = `You can use style tags almost everywhere to partially chan...
function Colors (line 13) | func Colors(nextSlide func()) (title string, content tview.Primitive) {
FILE: demos/presentation/cover.go
constant logo (line 11) | logo = `
constant subtitle (line 21) | subtitle = `tview - Rich Widgets for Terminal UIs`
constant navigation (line 22) | navigation = `[yellow]Ctrl-N[-]: Next slide [yellow]Ctrl-P[-]: Previo...
constant mouse (line 23) | mouse = `(or use your mouse)`
function Cover (line 27) | func Cover(nextSlide func()) (title string, content tview.Primitive) {
FILE: demos/presentation/end.go
function End (line 11) | func End(nextSlide func()) (title string, content tview.Primitive) {
FILE: demos/presentation/flex.go
function Flex (line 9) | func Flex(nextSlide func()) (title string, content tview.Primitive) {
FILE: demos/presentation/form.go
constant form (line 11) | form = `[green]package[white] main
constant photo (line 37) | photo = `/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAQEBAQEBAQEBAQGBgUGBggHBwcHCAw...
function Form (line 40) | func Form(nextSlide func()) (title string, content tview.Primitive) {
FILE: demos/presentation/grid.go
function Grid (line 9) | func Grid(nextSlide func()) (title string, content tview.Primitive) {
FILE: demos/presentation/helloworld.go
constant helloWorld (line 8) | helloWorld = `[green]package[white] main
function HelloWorld (line 24) | func HelloWorld(nextSlide func()) (title string, content tview.Primitive) {
FILE: demos/presentation/inputfield.go
constant inputField (line 8) | inputField = `[green]package[white] main
function InputField (line 33) | func InputField(nextSlide func()) (title string, content tview.Primitive) {
FILE: demos/presentation/introduction.go
function Introduction (line 6) | func Introduction(nextSlide func()) (title string, content tview.Primiti...
FILE: demos/presentation/main.go
type Slide (line 26) | type Slide
function main (line 32) | func main() {
FILE: demos/presentation/table.go
constant tableData (line 11) | tableData = `OrderDate|Region|Rep|Item|Units|UnitCost|Total
constant tableBasic (line 56) | tableBasic = `[green]func[white] [yellow]main[white]() {
constant tableSeparator (line 87) | tableSeparator = `[green]func[white] [yellow]main[white]() {
constant tableBorders (line 119) | tableBorders = `[green]func[white] [yellow]main[white]() {
constant tableSelectRow (line 151) | tableSelectRow = `[green]func[white] [yellow]main[white]() {
constant tableSelectColumn (line 184) | tableSelectColumn = `[green]func[white] [yellow]main[white]() {
constant tableSelectCell (line 217) | tableSelectCell = `[green]func[white] [yellow]main[white]() {
function Table (line 251) | func Table(nextSlide func()) (title string, content tview.Primitive) {
FILE: demos/presentation/textview.go
constant textView1 (line 12) | textView1 = `[green]func[white] [yellow]main[white]() {
function TextView1 (line 33) | func TextView1(nextSlide func()) (title string, content tview.Primitive) {
constant textView2 (line 66) | textView2 = `[green]package[white] main
function TextView2 (line 114) | func TextView2(nextSlide func()) (title string, content tview.Primitive) {
FILE: demos/presentation/treeview.go
constant treeAllCode (line 10) | treeAllCode = `[green]package[white] main
constant treeBasicCode (line 34) | treeBasicCode = `tree := tview.[yellow]NewTreeView[white]()`
constant treeTopLevelCode (line 36) | treeTopLevelCode = `tree := tview.[yellow]NewTreeView[white]().
constant treeAlignCode (line 39) | treeAlignCode = `tree := tview.[yellow]NewTreeView[white]().
constant treePrefixCode (line 42) | treePrefixCode = `tree := tview.[yellow]NewTreeView[white]().
type node (line 51) | type node struct
function TreeView (line 109) | func TreeView(nextSlide func()) (title string, content tview.Primitive) {
FILE: demos/primitive/main.go
type RadioButtons (line 12) | type RadioButtons struct
method Draw (line 27) | func (r *RadioButtons) Draw(screen tcell.Screen) {
method InputHandler (line 45) | func (r *RadioButtons) InputHandler() func(event *tcell.EventKey, setF...
method MouseHandler (line 63) | func (r *RadioButtons) MouseHandler() func(action tview.MouseAction, e...
function NewRadioButtons (line 19) | func NewRadioButtons(options []string) *RadioButtons {
function main (line 84) | func main() {
FILE: demos/table/main.go
function main (line 11) | func main() {
FILE: demos/table/virtualtable/main.go
type TableData (line 10) | type TableData struct
method GetCell (line 14) | func (d *TableData) GetCell(row, column int) *tview.TableCell {
method GetRowCount (line 27) | func (d *TableData) GetRowCount() int {
method GetColumnCount (line 31) | func (d *TableData) GetColumnCount() int {
function main (line 35) | func main() {
FILE: demos/textarea/main.go
function main (line 11) | func main() {
FILE: demos/textview/chat/main.go
type MarkovChain (line 21) | type MarkovChain struct
function main (line 35) | func main() {
function loadChain (line 119) | func loadChain() {
function generateChat (line 135) | func generateChat() <-chan []string {
FILE: demos/textview/main.go
constant corporate (line 14) | corporate = `Leverage agile frameworks to provide a robust synopsis for ...
function main (line 22) | func main() {
FILE: demos/treeview/main.go
function main (line 13) | func main() {
FILE: demos/unicode/main.go
function main (line 10) | func main() {
function alert (line 37) | func alert(pages *tview.Pages, id string, message string) *tview.Pages {
FILE: dropdown.go
type dropDownOption (line 11) | type dropDownOption struct
type DropDown (line 20) | type DropDown struct
method SetCurrentOption (line 126) | func (d *DropDown) SetCurrentOption(index int) *DropDown {
method GetCurrentOption (line 148) | func (d *DropDown) GetCurrentOption() (int, string) {
method SetTextOptions (line 161) | func (d *DropDown) SetTextOptions(prefix, suffix, currentPrefix, curre...
method SetUseStyleTags (line 176) | func (d *DropDown) SetUseStyleTags(useStyleTags bool) *DropDown {
method SetLabel (line 182) | func (d *DropDown) SetLabel(label string) *DropDown {
method GetLabel (line 188) | func (d *DropDown) GetLabel() string {
method SetLabelWidth (line 194) | func (d *DropDown) SetLabelWidth(width int) *DropDown {
method SetLabelColor (line 200) | func (d *DropDown) SetLabelColor(color tcell.Color) *DropDown {
method SetLabelStyle (line 206) | func (d *DropDown) SetLabelStyle(style tcell.Style) *DropDown {
method SetFieldBackgroundColor (line 213) | func (d *DropDown) SetFieldBackgroundColor(color tcell.Color) *DropDown {
method SetFieldTextColor (line 220) | func (d *DropDown) SetFieldTextColor(color tcell.Color) *DropDown {
method SetFieldStyle (line 226) | func (d *DropDown) SetFieldStyle(style tcell.Style) *DropDown {
method SetFocusedStyle (line 233) | func (d *DropDown) SetFocusedStyle(style tcell.Style) *DropDown {
method SetDisabledStyle (line 240) | func (d *DropDown) SetDisabledStyle(style tcell.Style) *DropDown {
method SetPrefixTextColor (line 248) | func (d *DropDown) SetPrefixTextColor(color tcell.Color) *DropDown {
method SetPrefixStyle (line 256) | func (d *DropDown) SetPrefixStyle(style tcell.Style) *DropDown {
method SetListStyles (line 264) | func (d *DropDown) SetListStyles(unselected, selected tcell.Style) *Dr...
method SetFormAttributes (line 272) | func (d *DropDown) SetFormAttributes(labelWidth int, labelColor, bgCol...
method SetFieldWidth (line 282) | func (d *DropDown) SetFieldWidth(width int) *DropDown {
method GetFieldWidth (line 288) | func (d *DropDown) GetFieldWidth() int {
method GetFieldHeight (line 303) | func (d *DropDown) GetFieldHeight() int {
method SetDisabled (line 308) | func (d *DropDown) SetDisabled(disabled bool) FormItem {
method GetDisabled (line 317) | func (d *DropDown) GetDisabled() bool {
method AddOption (line 323) | func (d *DropDown) AddOption(text string, selected func()) *DropDown {
method SetOptions (line 333) | func (d *DropDown) SetOptions(texts []string, selected func(text strin...
method GetOptionCount (line 344) | func (d *DropDown) GetOptionCount() int {
method RemoveOption (line 351) | func (d *DropDown) RemoveOption(index int) *DropDown {
method SetSelectedFunc (line 365) | func (d *DropDown) SetSelectedFunc(handler func(text string, index int...
method SetDoneFunc (line 377) | func (d *DropDown) SetDoneFunc(handler func(key tcell.Key)) *DropDown {
method SetFinishedFunc (line 383) | func (d *DropDown) SetFinishedFunc(handler func(key tcell.Key)) FormIt...
method Draw (line 389) | func (d *DropDown) Draw(screen tcell.Screen) {
method InputHandler (line 538) | func (d *DropDown) InputHandler() func(event *tcell.EventKey, setFocus...
method evalPrefix (line 582) | func (d *DropDown) evalPrefix() {
method openList (line 601) | func (d *DropDown) openList(setFocus func(Primitive)) {
method closeList (line 650) | func (d *DropDown) closeList(setFocus func(Primitive)) {
method IsOpen (line 661) | func (d *DropDown) IsOpen() bool {
method Focus (line 666) | func (d *DropDown) Focus(delegate func(p Primitive)) {
method focusChain (line 682) | func (d *DropDown) focusChain(chain *[]Primitive) bool {
method MouseHandler (line 695) | func (d *DropDown) MouseHandler() func(action MouseAction, event *tcel...
method PasteHandler (line 743) | func (d *DropDown) PasteHandler() func(pastedText string, setFocus fun...
function NewDropDown (line 96) | func NewDropDown() *DropDown {
FILE: flex.go
constant FlexRow (line 10) | FlexRow = 0
constant FlexColumn (line 12) | FlexColumn = 1
constant FlexRowCSS (line 14) | FlexRowCSS = 1
constant FlexColumnCSS (line 16) | FlexColumnCSS = 0
type flexItem (line 20) | type flexItem struct
type Flex (line 33) | type Flex struct
method SetDirection (line 70) | func (f *Flex) SetDirection(direction int) *Flex {
method SetFullScreen (line 77) | func (f *Flex) SetFullScreen(fullScreen bool) *Flex {
method AddItem (line 96) | func (f *Flex) AddItem(item Primitive, fixedSize, proportion int, focu...
method RemoveItem (line 103) | func (f *Flex) RemoveItem(p Primitive) *Flex {
method GetItemCount (line 113) | func (f *Flex) GetItemCount() int {
method GetItem (line 121) | func (f *Flex) GetItem(index int) Primitive {
method Clear (line 126) | func (f *Flex) Clear() *Flex {
method ResizeItem (line 134) | func (f *Flex) ResizeItem(p Primitive, fixedSize, proportion int) *Flex {
method Draw (line 145) | func (f *Flex) Draw(screen tcell.Screen) {
method Focus (line 207) | func (f *Flex) Focus(delegate func(p Primitive)) {
method focusChain (line 218) | func (f *Flex) focusChain(chain *[]Primitive) bool {
method MouseHandler (line 234) | func (f *Flex) MouseHandler() func(action MouseAction, event *tcell.Ev...
method InputHandler (line 256) | func (f *Flex) InputHandler() func(event *tcell.EventKey, setFocus fun...
method PasteHandler (line 272) | func (f *Flex) PasteHandler() func(pastedText string, setFocus func(p ...
function NewFlex (line 56) | func NewFlex() *Flex {
FILE: form.go
type FormItem (line 22) | type FormItem interface
type Form (line 63) | type Form struct
method SetItemPadding (line 139) | func (f *Form) SetItemPadding(padding int) *Form {
method SetHorizontal (line 148) | func (f *Form) SetHorizontal(horizontal bool) *Form {
method SetLabelColor (line 154) | func (f *Form) SetLabelColor(color tcell.Color) *Form {
method SetFieldBackgroundColor (line 160) | func (f *Form) SetFieldBackgroundColor(color tcell.Color) *Form {
method SetFieldTextColor (line 166) | func (f *Form) SetFieldTextColor(color tcell.Color) *Form {
method SetFieldStyle (line 173) | func (f *Form) SetFieldStyle(style tcell.Style) *Form {
method SetButtonsAlign (line 180) | func (f *Form) SetButtonsAlign(align int) *Form {
method SetButtonBackgroundColor (line 187) | func (f *Form) SetButtonBackgroundColor(color tcell.Color) *Form {
method SetButtonTextColor (line 195) | func (f *Form) SetButtonTextColor(color tcell.Color) *Form {
method SetButtonStyle (line 202) | func (f *Form) SetButtonStyle(style tcell.Style) *Form {
method SetButtonActivatedStyle (line 208) | func (f *Form) SetButtonActivatedStyle(style tcell.Style) *Form {
method SetButtonDisabledStyle (line 214) | func (f *Form) SetButtonDisabledStyle(style tcell.Style) *Form {
method SetFocus (line 224) | func (f *Form) SetFocus(index int) *Form {
method AddTextArea (line 239) | func (f *Form) AddTextArea(label, text string, fieldWidth, fieldHeight...
method AddTextView (line 266) | func (f *Form) AddTextView(label, text string, fieldWidth, fieldHeight...
method AddInputField (line 286) | func (f *Form) AddInputField(label, value string, fieldWidth int, acce...
method AddPasswordField (line 304) | func (f *Form) AddPasswordField(label, value string, fieldWidth int, m...
method AddDropDown (line 323) | func (f *Form) AddDropDown(label string, options []string, initialOpti...
method AddCheckbox (line 336) | func (f *Form) AddCheckbox(label string, checked bool, changed func(ch...
method AddImage (line 351) | func (f *Form) AddImage(label string, image image.Image, width, height...
method AddButton (line 365) | func (f *Form) AddButton(label string, selected func()) *Form {
method GetButton (line 376) | func (f *Form) GetButton(index int) *Button {
method RemoveButton (line 382) | func (f *Form) RemoveButton(index int) *Form {
method GetButtonCount (line 388) | func (f *Form) GetButtonCount() int {
method GetButtonIndex (line 395) | func (f *Form) GetButtonIndex(label string) int {
method Clear (line 406) | func (f *Form) Clear(includeButtons bool) *Form {
method ClearButtons (line 415) | func (f *Form) ClearButtons() *Form {
method AddFormItem (line 430) | func (f *Form) AddFormItem(item FormItem) *Form {
method GetFormItemCount (line 438) | func (f *Form) GetFormItemCount() int {
method GetFormItem (line 445) | func (f *Form) GetFormItem(index int) FormItem {
method RemoveFormItem (line 452) | func (f *Form) RemoveFormItem(index int) *Form {
method GetFormItemByLabel (line 460) | func (f *Form) GetFormItemByLabel(label string) FormItem {
method GetFormItemIndex (line 472) | func (f *Form) GetFormItemIndex(label string) int {
method GetFocusedItemIndex (line 483) | func (f *Form) GetFocusedItemIndex() (formItem, button int) {
method SetCancelFunc (line 496) | func (f *Form) SetCancelFunc(callback func()) *Form {
method Draw (line 502) | func (f *Form) Draw(screen tcell.Screen) {
method Focus (line 701) | func (f *Form) Focus(delegate func(p Primitive)) {
method finished (line 730) | func (f *Form) finished(key tcell.Key) {
method focusIndex (line 785) | func (f *Form) focusIndex() int {
method focusChain (line 800) | func (f *Form) focusChain(chain *[]Primitive) bool {
method MouseHandler (line 821) | func (f *Form) MouseHandler() func(action MouseAction, event *tcell.Ev...
method InputHandler (line 854) | func (f *Form) InputHandler() func(event *tcell.EventKey, setFocus fun...
method PasteHandler (line 877) | func (f *Form) PasteHandler() func(pastedText string, setFocus func(p ...
function NewForm (line 115) | func NewForm() *Form {
FILE: frame.go
type frameText (line 8) | type frameText struct
type Frame (line 19) | type Frame struct
method SetPrimitive (line 58) | func (f *Frame) SetPrimitive(p Primitive) *Frame {
method GetPrimitive (line 71) | func (f *Frame) GetPrimitive() Primitive {
method AddText (line 81) | func (f *Frame) AddText(text string, header bool, align int, color tce...
method Clear (line 92) | func (f *Frame) Clear() *Frame {
method SetBorders (line 100) | func (f *Frame) SetBorders(top, bottom, header, footer, left, right in...
method Draw (line 106) | func (f *Frame) Draw(screen tcell.Screen) {
method Focus (line 170) | func (f *Frame) Focus(delegate func(p Primitive)) {
method focusChain (line 180) | func (f *Frame) focusChain(chain *[]Primitive) bool {
method MouseHandler (line 193) | func (f *Frame) MouseHandler() func(action MouseAction, event *tcell.E...
method InputHandler (line 218) | func (f *Frame) InputHandler() func(event *tcell.EventKey, setFocus fu...
method PasteHandler (line 231) | func (f *Frame) PasteHandler() func(pastedText string, setFocus func(p...
function NewFrame (line 38) | func NewFrame(primitive Primitive) *Frame {
FILE: grid.go
type gridItem (line 10) | type gridItem struct
type Grid (line 31) | type Grid struct
method SetColumns (line 108) | func (g *Grid) SetColumns(columns ...int) *Grid {
method SetRows (line 119) | func (g *Grid) SetRows(rows ...int) *Grid {
method SetSize (line 127) | func (g *Grid) SetSize(numRows, numColumns, rowSize, columnSize int) *...
method SetMinSize (line 141) | func (g *Grid) SetMinSize(row, column int) *Grid {
method SetGap (line 152) | func (g *Grid) SetGap(row, column int) *Grid {
method SetBorders (line 163) | func (g *Grid) SetBorders(borders bool) *Grid {
method SetBordersColor (line 169) | func (g *Grid) SetBordersColor(color tcell.Color) *Grid {
method AddItem (line 201) | func (g *Grid) AddItem(p Primitive, row, column, rowSpan, colSpan, min...
method RemoveItem (line 217) | func (g *Grid) RemoveItem(p Primitive) *Grid {
method Clear (line 227) | func (g *Grid) Clear() *Grid {
method SetOffset (line 237) | func (g *Grid) SetOffset(rows, columns int) *Grid {
method GetOffset (line 244) | func (g *Grid) GetOffset() (rows, columns int) {
method Focus (line 249) | func (g *Grid) Focus(delegate func(p Primitive)) {
method focusChain (line 260) | func (g *Grid) focusChain(chain *[]Primitive) bool {
method Draw (line 276) | func (g *Grid) Draw(screen tcell.Screen) {
method MouseHandler (line 642) | func (g *Grid) MouseHandler() func(action MouseAction, event *tcell.Ev...
method InputHandler (line 664) | func (g *Grid) InputHandler() func(event *tcell.EventKey, setFocus fun...
method PasteHandler (line 713) | func (g *Grid) PasteHandler() func(pastedText string, setFocus func(p ...
function NewGrid (line 69) | func NewGrid() *Grid {
FILE: image.go
constant DitheringNone (line 12) | DitheringNone = iota
constant DitheringFloydSteinberg (line 13) | DitheringFloydSteinberg
constant TrueColor (line 17) | TrueColor = 16777216
type pixel (line 46) | type pixel struct
type Image (line 63) | type Image struct
method SetImage (line 130) | func (i *Image) SetImage(image image.Image) *Image {
method SetSize (line 142) | func (i *Image) SetSize(rows, columns int) *Image {
method SetColors (line 157) | func (i *Image) SetColors(colors int) *Image {
method GetColors (line 166) | func (i *Image) GetColors() int {
method SetDithering (line 183) | func (i *Image) SetDithering(dithering int) *Image {
method SetAspectRatio (line 194) | func (i *Image) SetAspectRatio(aspectRatio float64) *Image {
method SetAlign (line 208) | func (i *Image) SetAlign(vertical, horizontal int) *Image {
method SetLabel (line 215) | func (i *Image) SetLabel(label string) *Image {
method GetLabel (line 221) | func (i *Image) GetLabel() string {
method SetLabelWidth (line 227) | func (i *Image) SetLabelWidth(width int) *Image {
method GetFieldWidth (line 236) | func (i *Image) GetFieldWidth() int {
method GetFieldHeight (line 250) | func (i *Image) GetFieldHeight() int {
method SetDisabled (line 258) | func (i *Image) SetDisabled(disabled bool) FormItem {
method GetDisabled (line 263) | func (i *Image) GetDisabled() bool {
method SetFormAttributes (line 268) | func (i *Image) SetFormAttributes(labelWidth int, labelColor, bgColor,...
method SetLabelStyle (line 277) | func (i *Image) SetLabelStyle(style tcell.Style) *Image {
method GetLabelStyle (line 283) | func (i *Image) GetLabelStyle() tcell.Style {
method SetFinishedFunc (line 288) | func (i *Image) SetFinishedFunc(handler func(key tcell.Key)) FormItem {
method Focus (line 294) | func (i *Image) Focus(delegate func(p Primitive)) {
method render (line 308) | func (i *Image) render() {
method resize (line 380) | func (i *Image) resize() [][3]float64 {
method stamp (line 449) | func (i *Image) stamp(resized [][3]float64) {
method Draw (line 722) | func (i *Image) Draw(screen tcell.Screen) {
function NewImage (line 117) | func NewImage() *Image {
FILE: inputfield.go
constant AutocompletedNavigate (line 14) | AutocompletedNavigate = iota
constant AutocompletedTab (line 15) | AutocompletedTab
constant AutocompletedEnter (line 16) | AutocompletedEnter
constant AutocompletedClick (line 17) | AutocompletedClick
type InputField (line 78) | type InputField struct
method SetText (line 153) | func (i *InputField) SetText(text string) *InputField {
method GetText (line 159) | func (i *InputField) GetText() string {
method SetLabel (line 164) | func (i *InputField) SetLabel(label string) *InputField {
method GetLabel (line 170) | func (i *InputField) GetLabel() string {
method SetLabelWidth (line 176) | func (i *InputField) SetLabelWidth(width int) *InputField {
method SetPlaceholder (line 182) | func (i *InputField) SetPlaceholder(text string) *InputField {
method SetLabelColor (line 188) | func (i *InputField) SetLabelColor(color tcell.Color) *InputField {
method SetLabelStyle (line 194) | func (i *InputField) SetLabelStyle(style tcell.Style) *InputField {
method GetLabelStyle (line 200) | func (i *InputField) GetLabelStyle() tcell.Style {
method SetFieldBackgroundColor (line 205) | func (i *InputField) SetFieldBackgroundColor(color tcell.Color) *Input...
method SetFieldTextColor (line 211) | func (i *InputField) SetFieldTextColor(color tcell.Color) *InputField {
method SetFieldStyle (line 218) | func (i *InputField) SetFieldStyle(style tcell.Style) *InputField {
method GetFieldStyle (line 225) | func (i *InputField) GetFieldStyle() tcell.Style {
method SetPlaceholderTextColor (line 230) | func (i *InputField) SetPlaceholderTextColor(color tcell.Color) *Input...
method SetPlaceholderStyle (line 237) | func (i *InputField) SetPlaceholderStyle(style tcell.Style) *InputField {
method GetPlaceholderStyle (line 244) | func (i *InputField) GetPlaceholderStyle() tcell.Style {
method SetAutocompleteStyles (line 251) | func (i *InputField) SetAutocompleteStyles(background tcell.Color, mai...
method SetAutocompleteUseTags (line 260) | func (i *InputField) SetAutocompleteUseTags(useTags bool) *InputField {
method SetFormAttributes (line 266) | func (i *InputField) SetFormAttributes(labelWidth int, labelColor, bgC...
method SetFieldWidth (line 273) | func (i *InputField) SetFieldWidth(width int) *InputField {
method GetFieldWidth (line 279) | func (i *InputField) GetFieldWidth() int {
method GetFieldHeight (line 284) | func (i *InputField) GetFieldHeight() int {
method SetDisabled (line 289) | func (i *InputField) SetDisabled(disabled bool) FormItem {
method GetDisabled (line 298) | func (i *InputField) GetDisabled() bool {
method SetMaskCharacter (line 304) | func (i *InputField) SetMaskCharacter(mask rune) *InputField {
method SetAutocompleteFunc (line 323) | func (i *InputField) SetAutocompleteFunc(callback func(currentText str...
method SetAutocompletedFunc (line 342) | func (i *InputField) SetAutocompletedFunc(autocompleted func(text stri...
method Autocomplete (line 355) | func (i *InputField) Autocomplete() *InputField {
method SetAcceptanceFunc (line 421) | func (i *InputField) SetAcceptanceFunc(handler func(textToCheck string...
method SetChangedFunc (line 428) | func (i *InputField) SetChangedFunc(handler func(text string)) *InputF...
method SetDoneFunc (line 441) | func (i *InputField) SetDoneFunc(handler func(key tcell.Key)) *InputFi...
method SetFinishedFunc (line 447) | func (i *InputField) SetFinishedFunc(handler func(key tcell.Key)) Form...
method Focus (line 453) | func (i *InputField) Focus(delegate func(p Primitive)) {
method focusChain (line 465) | func (i *InputField) focusChain(chain *[]Primitive) bool {
method Blur (line 476) | func (i *InputField) Blur() {
method Draw (line 482) | func (i *InputField) Draw(screen tcell.Screen) {
method InputHandler (line 541) | func (i *InputField) InputHandler() func(event *tcell.EventKey, setFoc...
method MouseHandler (line 646) | func (i *InputField) MouseHandler() func(action MouseAction, event *tc...
method PasteHandler (line 707) | func (i *InputField) PasteHandler() func(pastedText string, setFocus f...
function NewInputField (line 131) | func NewInputField() *InputField {
FILE: list.go
type listItem (line 11) | type listItem struct
type List (line 41) | type List struct
method SetCurrentItem (line 123) | func (l *List) SetCurrentItem(index int) *List {
method GetCurrentItem (line 146) | func (l *List) GetCurrentItem() int {
method SetOffset (line 158) | func (l *List) SetOffset(items, horizontal int) *List {
method GetOffset (line 167) | func (l *List) GetOffset() (int, int) {
method RemoveItem (line 179) | func (l *List) RemoveItem(index int) *List {
method SetMainTextColor (line 219) | func (l *List) SetMainTextColor(color tcell.Color) *List {
method SetMainTextStyle (line 227) | func (l *List) SetMainTextStyle(style tcell.Style) *List {
method SetSecondaryTextColor (line 233) | func (l *List) SetSecondaryTextColor(color tcell.Color) *List {
method SetSecondaryTextStyle (line 241) | func (l *List) SetSecondaryTextStyle(style tcell.Style) *List {
method SetShortcutColor (line 247) | func (l *List) SetShortcutColor(color tcell.Color) *List {
method SetShortcutStyle (line 255) | func (l *List) SetShortcutStyle(style tcell.Style) *List {
method SetSelectedTextColor (line 263) | func (l *List) SetSelectedTextColor(color tcell.Color) *List {
method SetSelectedBackgroundColor (line 269) | func (l *List) SetSelectedBackgroundColor(color tcell.Color) *List {
method SetSelectedStyle (line 277) | func (l *List) SetSelectedStyle(style tcell.Style) *List {
method SetUseStyleTags (line 284) | func (l *List) SetUseStyleTags(mainStyleTags, secondaryStyleTags bool)...
method GetUseStyleTags (line 292) | func (l *List) GetUseStyleTags() (mainStyleTags, secondaryStyleTags bo...
method SetSelectedFocusOnly (line 299) | func (l *List) SetSelectedFocusOnly(focusOnly bool) *List {
method SetHighlightFullLine (line 308) | func (l *List) SetHighlightFullLine(highlight bool) *List {
method ShowSecondaryText (line 314) | func (l *List) ShowSecondaryText(show bool) *List {
method SetWrapAround (line 324) | func (l *List) SetWrapAround(wrapAround bool) *List {
method SetChangedFunc (line 335) | func (l *List) SetChangedFunc(handler func(index int, mainText string,...
method SetSelectedFunc (line 344) | func (l *List) SetSelectedFunc(handler func(int, string, string, rune)...
method GetSelectedFunc (line 351) | func (l *List) GetSelectedFunc() func(int, string, string, rune) {
method SetDoneFunc (line 357) | func (l *List) SetDoneFunc(handler func()) *List {
method AddItem (line 363) | func (l *List) AddItem(mainText, secondaryText string, shortcut rune, ...
method InsertItem (line 390) | func (l *List) InsertItem(index int, mainText, secondaryText string, s...
method GetItemCount (line 430) | func (l *List) GetItemCount() int {
method GetItemSelectedFunc (line 437) | func (l *List) GetItemSelectedFunc(index int) func() {
method GetItemText (line 443) | func (l *List) GetItemText(index int) (main, secondary string) {
method SetItemText (line 449) | func (l *List) SetItemText(index int, main, secondary string) *List {
method FindItems (line 466) | func (l *List) FindItems(mainSearch, secondarySearch string, mustConta...
method Clear (line 497) | func (l *List) Clear() *List {
method Draw (line 504) | func (l *List) Draw(screen tcell.Screen) {
method InputHandler (line 612) | func (l *List) InputHandler() func(event *tcell.EventKey, setFocus fun...
method indexAtPoint (line 711) | func (l *List) indexAtPoint(x, y int) int {
method MouseHandler (line 730) | func (l *List) MouseHandler() func(action MouseAction, event *tcell.Ev...
function NewList (line 101) | func NewList() *List {
FILE: modal.go
type Modal (line 12) | type Modal struct
method SetBackgroundColor (line 56) | func (m *Modal) SetBackgroundColor(color tcell.Color) *Modal {
method SetTextColor (line 63) | func (m *Modal) SetTextColor(color tcell.Color) *Modal {
method SetButtonBackgroundColor (line 69) | func (m *Modal) SetButtonBackgroundColor(color tcell.Color) *Modal {
method SetButtonTextColor (line 75) | func (m *Modal) SetButtonTextColor(color tcell.Color) *Modal {
method SetButtonStyle (line 81) | func (m *Modal) SetButtonStyle(style tcell.Style) *Modal {
method SetButtonActivatedStyle (line 87) | func (m *Modal) SetButtonActivatedStyle(style tcell.Style) *Modal {
method SetDoneFunc (line 96) | func (m *Modal) SetDoneFunc(handler func(buttonIndex int, buttonLabel ...
method SetText (line 104) | func (m *Modal) SetText(text string) *Modal {
method AddButtons (line 111) | func (m *Modal) AddButtons(labels []string) *Modal {
method ClearButtons (line 135) | func (m *Modal) ClearButtons() *Modal {
method SetFocus (line 141) | func (m *Modal) SetFocus(index int) *Modal {
method Focus (line 147) | func (m *Modal) Focus(delegate func(p Primitive)) {
method focusChain (line 152) | func (m *Modal) focusChain(chain *[]Primitive) bool {
method Draw (line 163) | func (m *Modal) Draw(screen tcell.Screen) {
method MouseHandler (line 199) | func (m *Modal) MouseHandler() func(action MouseAction, event *tcell.E...
method InputHandler (line 212) | func (m *Modal) InputHandler() func(event *tcell.EventKey, setFocus fu...
function NewModal (line 33) | func NewModal() *Modal {
FILE: pages.go
type page (line 8) | type page struct
type Pages (line 20) | type Pages struct
method SetChangedFunc (line 46) | func (p *Pages) SetChangedFunc(handler func()) *Pages {
method GetPageCount (line 52) | func (p *Pages) GetPageCount() int {
method GetPageNames (line 58) | func (p *Pages) GetPageNames(visibleOnly bool) []string {
method Clear (line 69) | func (p *Pages) Clear() *Pages {
method AddPage (line 83) | func (p *Pages) AddPage(name string, item Primitive, resize, visible b...
method AddAndSwitchToPage (line 103) | func (p *Pages) AddAndSwitchToPage(name string, item Primitive, resize...
method RemovePage (line 111) | func (p *Pages) RemovePage(name string) *Pages {
method HasPage (line 142) | func (p *Pages) HasPage(name string) bool {
method ShowPage (line 153) | func (p *Pages) ShowPage(name string) *Pages {
method HidePage (line 170) | func (p *Pages) HidePage(name string) *Pages {
method SwitchToPage (line 188) | func (p *Pages) SwitchToPage(name string) *Pages {
method SendToFront (line 208) | func (p *Pages) SendToFront(name string) *Pages {
method SendToBack (line 229) | func (p *Pages) SendToBack(name string) *Pages {
method GetFrontPage (line 249) | func (p *Pages) GetFrontPage() (name string, item Primitive) {
method GetPage (line 260) | func (p *Pages) GetPage(name string) Primitive {
method focusChain (line 270) | func (p *Pages) focusChain(chain *[]Primitive) bool {
method Focus (line 283) | func (p *Pages) Focus(delegate func(p Primitive)) {
method Draw (line 299) | func (p *Pages) Draw(screen tcell.Screen) {
method MouseHandler (line 314) | func (p *Pages) MouseHandler() func(action MouseAction, event *tcell.E...
method InputHandler (line 336) | func (p *Pages) InputHandler() func(event *tcell.EventKey, setFocus fu...
method PasteHandler (line 350) | func (p *Pages) PasteHandler() func(pastedText string, setFocus func(p...
function NewPages (line 36) | func NewPages() *Pages {
FILE: primitive.go
type Primitive (line 6) | type Primitive interface
FILE: semigraphics.go
constant SemigraphicsHorizontalEllipsis (line 11) | SemigraphicsHorizontalEllipsis rune = '\u2026'
constant BoxDrawingsLightHorizontal (line 14) | BoxDrawingsLightHorizontal rune = '\u2500'
constant BoxDrawingsHeavyHorizontal (line 15) | BoxDrawingsHeavyHorizontal rune = '\u2501'
constant BoxDrawingsLightVertical (line 16) | BoxDrawingsLightVertical rune = '\u2502'
constant BoxDrawingsHeavyVertical (line 17) | BoxDrawingsHeavyVertical rune = '\u2503'
constant BoxDrawingsLightTripleDashHorizontal (line 18) | BoxDrawingsLightTripleDashHorizontal rune = '\u2504'
constant BoxDrawingsHeavyTripleDashHorizontal (line 19) | BoxDrawingsHeavyTripleDashHorizontal rune = '\u2505'
constant BoxDrawingsLightTripleDashVertical (line 20) | BoxDrawingsLightTripleDashVertical rune = '\u2506'
constant BoxDrawingsHeavyTripleDashVertical (line 21) | BoxDrawingsHeavyTripleDashVertical rune = '\u2507'
constant BoxDrawingsLightQuadrupleDashHorizontal (line 22) | BoxDrawingsLightQuadrupleDashHorizontal rune = '\u2508'
constant BoxDrawingsHeavyQuadrupleDashHorizontal (line 23) | BoxDrawingsHeavyQuadrupleDashHorizontal rune = '\u2509'
constant BoxDrawingsLightQuadrupleDashVertical (line 24) | BoxDrawingsLightQuadrupleDashVertical rune = '\u250a'
constant BoxDrawingsHeavyQuadrupleDashVertical (line 25) | BoxDrawingsHeavyQuadrupleDashVertical rune = '\u250b'
constant BoxDrawingsLightDownAndRight (line 26) | BoxDrawingsLightDownAndRight rune = '\u250c'
constant BoxDrawingsDownLightAndRightHeavy (line 27) | BoxDrawingsDownLightAndRightHeavy rune = '\u250d'
constant BoxDrawingsDownHeavyAndRightLight (line 28) | BoxDrawingsDownHeavyAndRightLight rune = '\u250e'
constant BoxDrawingsHeavyDownAndRight (line 29) | BoxDrawingsHeavyDownAndRight rune = '\u250f'
constant BoxDrawingsLightDownAndLeft (line 30) | BoxDrawingsLightDownAndLeft rune = '\u2510'
constant BoxDrawingsDownLightAndLeftHeavy (line 31) | BoxDrawingsDownLightAndLeftHeavy rune = '\u2511'
constant BoxDrawingsDownHeavyAndLeftLight (line 32) | BoxDrawingsDownHeavyAndLeftLight rune = '\u2512'
constant BoxDrawingsHeavyDownAndLeft (line 33) | BoxDrawingsHeavyDownAndLeft rune = '\u2513'
constant BoxDrawingsLightUpAndRight (line 34) | BoxDrawingsLightUpAndRight rune = '\u2514'
constant BoxDrawingsUpLightAndRightHeavy (line 35) | BoxDrawingsUpLightAndRightHeavy rune = '\u2515'
constant BoxDrawingsUpHeavyAndRightLight (line 36) | BoxDrawingsUpHeavyAndRightLight rune = '\u2516'
constant BoxDrawingsHeavyUpAndRight (line 37) | BoxDrawingsHeavyUpAndRight rune = '\u2517'
constant BoxDrawingsLightUpAndLeft (line 38) | BoxDrawingsLightUpAndLeft rune = '\u2518'
constant BoxDrawingsUpLightAndLeftHeavy (line 39) | BoxDrawingsUpLightAndLeftHeavy rune = '\u2519'
constant BoxDrawingsUpHeavyAndLeftLight (line 40) | BoxDrawingsUpHeavyAndLeftLight rune = '\u251a'
constant BoxDrawingsHeavyUpAndLeft (line 41) | BoxDrawingsHeavyUpAndLeft rune = '\u251b'
constant BoxDrawingsLightVerticalAndRight (line 42) | BoxDrawingsLightVerticalAndRight rune = '\u251c'
constant BoxDrawingsVerticalLightAndRightHeavy (line 43) | BoxDrawingsVerticalLightAndRightHeavy rune = '\u251d'
constant BoxDrawingsUpHeavyAndRightDownLight (line 44) | BoxDrawingsUpHeavyAndRightDownLight rune = '\u251e'
constant BoxDrawingsDownHeavyAndRightUpLight (line 45) | BoxDrawingsDownHeavyAndRightUpLight rune = '\u251f'
constant BoxDrawingsVerticalHeavyAndRightLight (line 46) | BoxDrawingsVerticalHeavyAndRightLight rune = '\u2520'
constant BoxDrawingsDownLightAndRightUpHeavy (line 47) | BoxDrawingsDownLightAndRightUpHeavy rune = '\u2521'
constant BoxDrawingsUpLightAndRightDownHeavy (line 48) | BoxDrawingsUpLightAndRightDownHeavy rune = '\u2522'
constant BoxDrawingsHeavyVerticalAndRight (line 49) | BoxDrawingsHeavyVerticalAndRight rune = '\u2523'
constant BoxDrawingsLightVerticalAndLeft (line 50) | BoxDrawingsLightVerticalAndLeft rune = '\u2524'
constant BoxDrawingsVerticalLightAndLeftHeavy (line 51) | BoxDrawingsVerticalLightAndLeftHeavy rune = '\u2525'
constant BoxDrawingsUpHeavyAndLeftDownLight (line 52) | BoxDrawingsUpHeavyAndLeftDownLight rune = '\u2526'
constant BoxDrawingsDownHeavyAndLeftUpLight (line 53) | BoxDrawingsDownHeavyAndLeftUpLight rune = '\u2527'
constant BoxDrawingsVerticalHeavyAndLeftLight (line 54) | BoxDrawingsVerticalHeavyAndLeftLight rune = '\u2528'
constant BoxDrawingsDownLightAndLeftUpHeavy (line 55) | BoxDrawingsDownLightAndLeftUpHeavy rune = '\u2529'
constant BoxDrawingsUpLightAndLeftDownHeavy (line 56) | BoxDrawingsUpLightAndLeftDownHeavy rune = '\u252a'
constant BoxDrawingsHeavyVerticalAndLeft (line 57) | BoxDrawingsHeavyVerticalAndLeft rune = '\u252b'
constant BoxDrawingsLightDownAndHorizontal (line 58) | BoxDrawingsLightDownAndHorizontal rune = '\u252c'
constant BoxDrawingsLeftHeavyAndRightDownLight (line 59) | BoxDrawingsLeftHeavyAndRightDownLight rune = '\u252d'
constant BoxDrawingsRightHeavyAndLeftDownLight (line 60) | BoxDrawingsRightHeavyAndLeftDownLight rune = '\u252e'
constant BoxDrawingsDownLightAndHorizontalHeavy (line 61) | BoxDrawingsDownLightAndHorizontalHeavy rune = '\u252f'
constant BoxDrawingsDownHeavyAndHorizontalLight (line 62) | BoxDrawingsDownHeavyAndHorizontalLight rune = '\u2530'
constant BoxDrawingsRightLightAndLeftDownHeavy (line 63) | BoxDrawingsRightLightAndLeftDownHeavy rune = '\u2531'
constant BoxDrawingsLeftLightAndRightDownHeavy (line 64) | BoxDrawingsLeftLightAndRightDownHeavy rune = '\u2532'
constant BoxDrawingsHeavyDownAndHorizontal (line 65) | BoxDrawingsHeavyDownAndHorizontal rune = '\u2533'
constant BoxDrawingsLightUpAndHorizontal (line 66) | BoxDrawingsLightUpAndHorizontal rune = '\u2534'
constant BoxDrawingsLeftHeavyAndRightUpLight (line 67) | BoxDrawingsLeftHeavyAndRightUpLight rune = '\u2535'
constant BoxDrawingsRightHeavyAndLeftUpLight (line 68) | BoxDrawingsRightHeavyAndLeftUpLight rune = '\u2536'
constant BoxDrawingsUpLightAndHorizontalHeavy (line 69) | BoxDrawingsUpLightAndHorizontalHeavy rune = '\u2537'
constant BoxDrawingsUpHeavyAndHorizontalLight (line 70) | BoxDrawingsUpHeavyAndHorizontalLight rune = '\u2538'
constant BoxDrawingsRightLightAndLeftUpHeavy (line 71) | BoxDrawingsRightLightAndLeftUpHeavy rune = '\u2539'
constant BoxDrawingsLeftLightAndRightUpHeavy (line 72) | BoxDrawingsLeftLightAndRightUpHeavy rune = '\u253a'
constant BoxDrawingsHeavyUpAndHorizontal (line 73) | BoxDrawingsHeavyUpAndHorizontal rune = '\u253b'
constant BoxDrawingsLightVerticalAndHorizontal (line 74) | BoxDrawingsLightVerticalAndHorizontal rune = '\u253c'
constant BoxDrawingsLeftHeavyAndRightVerticalLight (line 75) | BoxDrawingsLeftHeavyAndRightVerticalLight rune = '\u253d'
constant BoxDrawingsRightHeavyAndLeftVerticalLight (line 76) | BoxDrawingsRightHeavyAndLeftVerticalLight rune = '\u253e'
constant BoxDrawingsVerticalLightAndHorizontalHeavy (line 77) | BoxDrawingsVerticalLightAndHorizontalHeavy rune = '\u253f'
constant BoxDrawingsUpHeavyAndDownHorizontalLight (line 78) | BoxDrawingsUpHeavyAndDownHorizontalLight rune = '\u2540'
constant BoxDrawingsDownHeavyAndUpHorizontalLight (line 79) | BoxDrawingsDownHeavyAndUpHorizontalLight rune = '\u2541'
constant BoxDrawingsVerticalHeavyAndHorizontalLight (line 80) | BoxDrawingsVerticalHeavyAndHorizontalLight rune = '\u2542'
constant BoxDrawingsLeftUpHeavyAndRightDownLight (line 81) | BoxDrawingsLeftUpHeavyAndRightDownLight rune = '\u2543'
constant BoxDrawingsRightUpHeavyAndLeftDownLight (line 82) | BoxDrawingsRightUpHeavyAndLeftDownLight rune = '\u2544'
constant BoxDrawingsLeftDownHeavyAndRightUpLight (line 83) | BoxDrawingsLeftDownHeavyAndRightUpLight rune = '\u2545'
constant BoxDrawingsRightDownHeavyAndLeftUpLight (line 84) | BoxDrawingsRightDownHeavyAndLeftUpLight rune = '\u2546'
constant BoxDrawingsDownLightAndUpHorizontalHeavy (line 85) | BoxDrawingsDownLightAndUpHorizontalHeavy rune = '\u2547'
constant BoxDrawingsUpLightAndDownHorizontalHeavy (line 86) | BoxDrawingsUpLightAndDownHorizontalHeavy rune = '\u2548'
constant BoxDrawingsRightLightAndLeftVerticalHeavy (line 87) | BoxDrawingsRightLightAndLeftVerticalHeavy rune = '\u2549'
constant BoxDrawingsLeftLightAndRightVerticalHeavy (line 88) | BoxDrawingsLeftLightAndRightVerticalHeavy rune = '\u254a'
constant BoxDrawingsHeavyVerticalAndHorizontal (line 89) | BoxDrawingsHeavyVerticalAndHorizontal rune = '\u254b'
constant BoxDrawingsLightDoubleDashHorizontal (line 90) | BoxDrawingsLightDoubleDashHorizontal rune = '\u254c'
constant BoxDrawingsHeavyDoubleDashHorizontal (line 91) | BoxDrawingsHeavyDoubleDashHorizontal rune = '\u254d'
constant BoxDrawingsLightDoubleDashVertical (line 92) | BoxDrawingsLightDoubleDashVertical rune = '\u254e'
constant BoxDrawingsHeavyDoubleDashVertical (line 93) | BoxDrawingsHeavyDoubleDashVertical rune = '\u254f'
constant BoxDrawingsDoubleHorizontal (line 94) | BoxDrawingsDoubleHorizontal rune = '\u2550'
constant BoxDrawingsDoubleVertical (line 95) | BoxDrawingsDoubleVertical rune = '\u2551'
constant BoxDrawingsDownSingleAndRightDouble (line 96) | BoxDrawingsDownSingleAndRightDouble rune = '\u2552'
constant BoxDrawingsDownDoubleAndRightSingle (line 97) | BoxDrawingsDownDoubleAndRightSingle rune = '\u2553'
constant BoxDrawingsDoubleDownAndRight (line 98) | BoxDrawingsDoubleDownAndRight rune = '\u2554'
constant BoxDrawingsDownSingleAndLeftDouble (line 99) | BoxDrawingsDownSingleAndLeftDouble rune = '\u2555'
constant BoxDrawingsDownDoubleAndLeftSingle (line 100) | BoxDrawingsDownDoubleAndLeftSingle rune = '\u2556'
constant BoxDrawingsDoubleDownAndLeft (line 101) | BoxDrawingsDoubleDownAndLeft rune = '\u2557'
constant BoxDrawingsUpSingleAndRightDouble (line 102) | BoxDrawingsUpSingleAndRightDouble rune = '\u2558'
constant BoxDrawingsUpDoubleAndRightSingle (line 103) | BoxDrawingsUpDoubleAndRightSingle rune = '\u2559'
constant BoxDrawingsDoubleUpAndRight (line 104) | BoxDrawingsDoubleUpAndRight rune = '\u255a'
constant BoxDrawingsUpSingleAndLeftDouble (line 105) | BoxDrawingsUpSingleAndLeftDouble rune = '\u255b'
constant BoxDrawingsUpDoubleAndLeftSingle (line 106) | BoxDrawingsUpDoubleAndLeftSingle rune = '\u255c'
constant BoxDrawingsDoubleUpAndLeft (line 107) | BoxDrawingsDoubleUpAndLeft rune = '\u255d'
constant BoxDrawingsVerticalSingleAndRightDouble (line 108) | BoxDrawingsVerticalSingleAndRightDouble rune = '\u255e'
constant BoxDrawingsVerticalDoubleAndRightSingle (line 109) | BoxDrawingsVerticalDoubleAndRightSingle rune = '\u255f'
constant BoxDrawingsDoubleVerticalAndRight (line 110) | BoxDrawingsDoubleVerticalAndRight rune = '\u2560'
constant BoxDrawingsVerticalSingleAndLeftDouble (line 111) | BoxDrawingsVerticalSingleAndLeftDouble rune = '\u2561'
constant BoxDrawingsVerticalDoubleAndLeftSingle (line 112) | BoxDrawingsVerticalDoubleAndLeftSingle rune = '\u2562'
constant BoxDrawingsDoubleVerticalAndLeft (line 113) | BoxDrawingsDoubleVerticalAndLeft rune = '\u2563'
constant BoxDrawingsDownSingleAndHorizontalDouble (line 114) | BoxDrawingsDownSingleAndHorizontalDouble rune = '\u2564'
constant BoxDrawingsDownDoubleAndHorizontalSingle (line 115) | BoxDrawingsDownDoubleAndHorizontalSingle rune = '\u2565'
constant BoxDrawingsDoubleDownAndHorizontal (line 116) | BoxDrawingsDoubleDownAndHorizontal rune = '\u2566'
constant BoxDrawingsUpSingleAndHorizontalDouble (line 117) | BoxDrawingsUpSingleAndHorizontalDouble rune = '\u2567'
constant BoxDrawingsUpDoubleAndHorizontalSingle (line 118) | BoxDrawingsUpDoubleAndHorizontalSingle rune = '\u2568'
constant BoxDrawingsDoubleUpAndHorizontal (line 119) | BoxDrawingsDoubleUpAndHorizontal rune = '\u2569'
constant BoxDrawingsVerticalSingleAndHorizontalDouble (line 120) | BoxDrawingsVerticalSingleAndHorizontalDouble rune = '\u256a'
constant BoxDrawingsVerticalDoubleAndHorizontalSingle (line 121) | BoxDrawingsVerticalDoubleAndHorizontalSingle rune = '\u256b'
constant BoxDrawingsDoubleVerticalAndHorizontal (line 122) | BoxDrawingsDoubleVerticalAndHorizontal rune = '\u256c'
constant BoxDrawingsLightArcDownAndRight (line 123) | BoxDrawingsLightArcDownAndRight rune = '\u256d'
constant BoxDrawingsLightArcDownAndLeft (line 124) | BoxDrawingsLightArcDownAndLeft rune = '\u256e'
constant BoxDrawingsLightArcUpAndLeft (line 125) | BoxDrawingsLightArcUpAndLeft rune = '\u256f'
constant BoxDrawingsLightArcUpAndRight (line 126) | BoxDrawingsLightArcUpAndRight rune = '\u2570'
constant BoxDrawingsLightDiagonalUpperRightToLowerLeft (line 127) | BoxDrawingsLightDiagonalUpperRightToLowerLeft rune = '\u2571'
constant BoxDrawingsLightDiagonalUpperLeftToLowerRight (line 128) | BoxDrawingsLightDiagonalUpperLeftToLowerRight rune = '\u2572'
constant BoxDrawingsLightDiagonalCross (line 129) | BoxDrawingsLightDiagonalCross rune = '\u2573'
constant BoxDrawingsLightLeft (line 130) | BoxDrawingsLightLeft rune = '\u2574'
constant BoxDrawingsLightUp (line 131) | BoxDrawingsLightUp rune = '\u2575'
constant BoxDrawingsLightRight (line 132) | BoxDrawingsLightRight rune = '\u2576'
constant BoxDrawingsLightDown (line 133) | BoxDrawingsLightDown rune = '\u2577'
constant BoxDrawingsHeavyLeft (line 134) | BoxDrawingsHeavyLeft rune = '\u2578'
constant BoxDrawingsHeavyUp (line 135) | BoxDrawingsHeavyUp rune = '\u2579'
constant BoxDrawingsHeavyRight (line 136) | BoxDrawingsHeavyRight rune = '\u257a'
constant BoxDrawingsHeavyDown (line 137) | BoxDrawingsHeavyDown rune = '\u257b'
constant BoxDrawingsLightLeftAndHeavyRight (line 138) | BoxDrawingsLightLeftAndHeavyRight rune = '\u257c'
constant BoxDrawingsLightUpAndHeavyDown (line 139) | BoxDrawingsLightUpAndHeavyDown rune = '\u257d'
constant BoxDrawingsHeavyLeftAndLightRight (line 140) | BoxDrawingsHeavyLeftAndLightRight rune = '\u257e'
constant BoxDrawingsHeavyUpAndLightDown (line 141) | BoxDrawingsHeavyUpAndLightDown rune = '\u257f'
constant BlockUpperHalfBlock (line 144) | BlockUpperHalfBlock rune = '\u2580'
constant BlockLowerOneEighthBlock (line 145) | BlockLowerOneEighthBlock rune = '\u2581'
constant BlockLowerOneQuarterBlock (line 146) | BlockLowerOneQuarterBlock rune = '\u2582'
constant BlockLowerThreeEighthsBlock (line 147) | BlockLowerThreeEighthsBlock rune = '\u2583'
constant BlockLowerHalfBlock (line 148) | BlockLowerHalfBlock rune = '\u2584'
constant BlockLowerFiveEighthsBlock (line 149) | BlockLowerFiveEighthsBlock rune = '\u2585'
constant BlockLowerThreeQuartersBlock (line 150) | BlockLowerThreeQuartersBlock rune = '\u2586'
constant BlockLowerSevenEighthsBlock (line 151) | BlockLowerSevenEighthsBlock rune = '\u2587'
constant BlockFullBlock (line 152) | BlockFullBlock rune = '\u2588'
constant BlockLeftSevenEighthsBlock (line 153) | BlockLeftSevenEighthsBlock rune = '\u2589'
constant BlockLeftThreeQuartersBlock (line 154) | BlockLeftThreeQuartersBlock rune = '\u258A'
constant BlockLeftFiveEighthsBlock (line 155) | BlockLeftFiveEighthsBlock rune = '\u258B'
constant BlockLeftHalfBlock (line 156) | BlockLeftHalfBlock rune = '\u258C'
constant BlockLeftThreeEighthsBlock (line 157) | BlockLeftThreeEighthsBlock rune = '\u258D'
constant BlockLeftOneQuarterBlock (line 158) | BlockLeftOneQuarterBlock rune = '\u258E'
constant BlockLeftOneEighthBlock (line 159) | BlockLeftOneEighthBlock rune = '\u258F'
constant BlockRightHalfBlock (line 160) | BlockRightHalfBlock rune = '\u2590'
constant BlockLightShade (line 161) | BlockLightShade rune = '\u2591'
constant BlockMediumShade (line 162) | BlockMediumShade rune = '\u2592'
constant BlockDarkShade (line 163) | BlockDarkShade rune = '\u2593'
constant BlockUpperOneEighthBlock (line 164) | BlockUpperOneEighthBlock rune = '\u2594'
constant BlockRightOneEighthBlock (line 165) | BlockRightOneEighthBlock rune = '\u2595'
constant BlockQuadrantLowerLeft (line 166) | BlockQuadrantLowerLeft rune = '\u2596'
constant BlockQuadrantLowerRight (line 167) | BlockQuadrantLowerRight rune = '\u2597'
constant BlockQuadrantUpperLeft (line 168) | BlockQuadrantUpperLeft rune = '\u2598'
constant BlockQuadrantUpperLeftAndLowerLeftAndLowerRight (line 169) | BlockQuadrantUpperLeftAndLowerLeftAndLowerRight rune = '\u2599'
constant BlockQuadrantUpperLeftAndLowerRight (line 170) | BlockQuadrantUpperLeftAndLowerRight rune = '\u259A'
constant BlockQuadrantUpperLeftAndUpperRightAndLowerLeft (line 171) | BlockQuadrantUpperLeftAndUpperRightAndLowerLeft rune = '\u259B'
constant BlockQuadrantUpperLeftAndUpperRightAndLowerRight (line 172) | BlockQuadrantUpperLeftAndUpperRightAndLowerRight rune = '\u259C'
constant BlockQuadrantUpperRight (line 173) | BlockQuadrantUpperRight rune = '\u259D'
constant BlockQuadrantUpperRightAndLowerLeft (line 174) | BlockQuadrantUpperRightAndLowerLeft rune = '\u259E'
constant BlockQuadrantUpperRightAndLowerLeftAndLowerRight (line 175) | BlockQuadrantUpperRightAndLowerLeftAndLowerRight rune = '\u259F'
function PrintJoinedSemigraphics (line 309) | func PrintJoinedSemigraphics(screen tcell.Screen, x, y int, ch rune, sty...
FILE: strings.go
type stepOptions (line 21) | type stepOptions
constant stepOptionsNone (line 25) | stepOptionsNone stepOptions = 0
constant stepOptionsStyle (line 26) | stepOptionsStyle stepOptions = 1 << iota
constant stepOptionsRegion (line 27) | stepOptionsRegion
type stepState (line 31) | type stepState struct
method IsWordBoundary (line 47) | func (s *stepState) IsWordBoundary() bool {
method IsSentenceBoundary (line 53) | func (s *stepState) IsSentenceBoundary() bool {
method LineBreak (line 61) | func (s *stepState) LineBreak() (lineBreak, optional bool) {
method Width (line 72) | func (s *stepState) Width() int {
method GrossLength (line 78) | func (s *stepState) GrossLength() int {
method Style (line 83) | func (s *stepState) Style() tcell.Style {
function step (line 110) | func step(str string, state *stepState, opts stepOptions) (cluster, rest...
function parseTag (line 221) | func parseTag(str string, state *stepState, opts stepOptions) (length in...
function TaggedStringWidth (line 544) | func TaggedStringWidth(text string) (width int) {
function WordWrap (line 560) | func WordWrap(text string, width int) (lines []string) {
function Escape (line 621) | func Escape(text string) string {
function Unescape (line 626) | func Unescape(text string) string {
function stripTags (line 632) | func stripTags(text string) string {
FILE: styles.go
type Theme (line 6) | type Theme struct
FILE: table.go
type TableCell (line 13) | type TableCell struct
method SetText (line 84) | func (c *TableCell) SetText(text string) *TableCell {
method SetAlign (line 91) | func (c *TableCell) SetAlign(align int) *TableCell {
method SetMaxWidth (line 99) | func (c *TableCell) SetMaxWidth(maxWidth int) *TableCell {
method SetExpansion (line 117) | func (c *TableCell) SetExpansion(expansion int) *TableCell {
method SetTextColor (line 126) | func (c *TableCell) SetTextColor(color tcell.Color) *TableCell {
method SetBackgroundColor (line 137) | func (c *TableCell) SetBackgroundColor(color tcell.Color) *TableCell {
method SetTransparency (line 151) | func (c *TableCell) SetTransparency(transparent bool) *TableCell {
method SetAttributes (line 160) | func (c *TableCell) SetAttributes(attr tcell.AttrMask) *TableCell {
method SetStyle (line 171) | func (c *TableCell) SetStyle(style tcell.Style) *TableCell {
method SetSelectedStyle (line 180) | func (c *TableCell) SetSelectedStyle(style tcell.Style) *TableCell {
method SetSelectable (line 186) | func (c *TableCell) SetSelectable(selectable bool) *TableCell {
method SetReference (line 194) | func (c *TableCell) SetReference(reference interface{}) *TableCell {
method GetReference (line 200) | func (c *TableCell) GetReference() interface{} {
method GetLastPosition (line 212) | func (c *TableCell) GetLastPosition() (x, y, width int) {
method SetClickedFunc (line 219) | func (c *TableCell) SetClickedFunc(clicked func() bool) *TableCell {
function NewTableCell (line 74) | func NewTableCell(text string) *TableCell {
type TableContent (line 235) | type TableContent interface
type TableContentReadOnly (line 284) | type TableContentReadOnly struct
method SetCell (line 287) | func (t TableContentReadOnly) SetCell(row, column int, cell *TableCell) {
method RemoveRow (line 292) | func (t TableContentReadOnly) RemoveRow(row int) {
method RemoveColumn (line 297) | func (t TableContentReadOnly) RemoveColumn(column int) {
method InsertRow (line 302) | func (t TableContentReadOnly) InsertRow(row int) {
method InsertColumn (line 307) | func (t TableContentReadOnly) InsertColumn(column int) {
method Clear (line 312) | func (t TableContentReadOnly) Clear() {
type tableDefaultContent (line 318) | type tableDefaultContent struct
method Clear (line 327) | func (t *tableDefaultContent) Clear() {
method SetCell (line 333) | func (t *tableDefaultContent) SetCell(row, column int, cell *TableCell) {
method RemoveRow (line 351) | func (t *tableDefaultContent) RemoveRow(row int) {
method RemoveColumn (line 359) | func (t *tableDefaultContent) RemoveColumn(column int) {
method InsertRow (line 372) | func (t *tableDefaultContent) InsertRow(row int) {
method InsertColumn (line 382) | func (t *tableDefaultContent) InsertColumn(column int) {
method GetCell (line 394) | func (t *tableDefaultContent) GetCell(row, column int) *TableCell {
method GetRowCount (line 402) | func (t *tableDefaultContent) GetRowCount() int {
method GetColumnCount (line 407) | func (t *tableDefaultContent) GetColumnCount() int {
type Table (line 464) | type Table struct
method SetContent (line 557) | func (t *Table) SetContent(content TableContent) *Table {
method Clear (line 569) | func (t *Table) Clear() *Table {
method SetBorders (line 576) | func (t *Table) SetBorders(show bool) *Table {
method SetBordersColor (line 582) | func (t *Table) SetBordersColor(color tcell.Color) *Table {
method SetSelectedStyle (line 594) | func (t *Table) SetSelectedStyle(style tcell.Style) *Table {
method SetSeparator (line 606) | func (t *Table) SetSeparator(separator rune) *Table {
method SetFixed (line 614) | func (t *Table) SetFixed(rows, columns int) *Table {
method SetSelectable (line 626) | func (t *Table) SetSelectable(rows, columns bool) *Table {
method GetSelectable (line 633) | func (t *Table) GetSelectable() (rows, columns bool) {
method GetSelection (line 640) | func (t *Table) GetSelection() (row, column int) {
method Select (line 649) | func (t *Table) Select(row, column int) *Table {
method SetOffset (line 663) | func (t *Table) SetOffset(row, column int) *Table {
method GetOffset (line 671) | func (t *Table) GetOffset() (row, column int) {
method SetEvaluateAllRows (line 684) | func (t *Table) SetEvaluateAllRows(all bool) *Table {
method SetSelectedFunc (line 693) | func (t *Table) SetSelectedFunc(handler func(row, column int)) *Table {
method SetSelectionChangedFunc (line 702) | func (t *Table) SetSelectionChangedFunc(handler func(row, column int))...
method SetDoneFunc (line 711) | func (t *Table) SetDoneFunc(handler func(key tcell.Key)) *Table {
method SetCell (line 726) | func (t *Table) SetCell(row, column int, cell *TableCell) *Table {
method SetCellSimple (line 732) | func (t *Table) SetCellSimple(row, column int, text string) *Table {
method GetCell (line 742) | func (t *Table) GetCell(row, column int) *TableCell {
method RemoveRow (line 752) | func (t *Table) RemoveRow(row int) *Table {
method RemoveColumn (line 759) | func (t *Table) RemoveColumn(column int) *Table {
method InsertRow (line 767) | func (t *Table) InsertRow(row int) *Table {
method InsertColumn (line 776) | func (t *Table) InsertColumn(column int) *Table {
method GetRowCount (line 782) | func (t *Table) GetRowCount() int {
method GetColumnCount (line 787) | func (t *Table) GetColumnCount() int {
method CellAt (line 798) | func (t *Table) CellAt(x, y int) (row, column int) {
method ScrollToBeginning (line 840) | func (t *Table) ScrollToBeginning() *Table {
method ScrollToEnd (line 851) | func (t *Table) ScrollToEnd() *Table {
method SetWrapSelection (line 868) | func (t *Table) SetWrapSelection(vertical, horizontal bool) *Table {
method Draw (line 875) | func (t *Table) Draw(screen tcell.Screen) {
method InputHandler (line 1372) | func (t *Table) InputHandler() func(event *tcell.EventKey, setFocus fu...
method MouseHandler (line 1692) | func (t *Table) MouseHandler() func(action MouseAction, event *tcell.E...
function NewTable (line 539) | func NewTable() *Table {
FILE: textarea.go
constant pieceChainMinCap (line 15) | pieceChainMinCap = 10
constant editBufferMinCap (line 18) | editBufferMinCap = 200
constant maxGraphemeClusterSize (line 22) | maxGraphemeClusterSize = 40
constant minCursorPrefixDefault (line 25) | minCursorPrefixDefault = 5
constant minCursorSuffixDefault (line 28) | minCursorSuffixDefault = 3
type taAction (line 32) | type taAction
constant taActionOther (line 35) | taActionOther taAction = iota
constant taActionTypeSpace (line 36) | taActionTypeSpace
constant taActionTypeNonSpace (line 37) | taActionTypeNonSpace
constant taActionBackspace (line 38) | taActionBackspace
constant taActionDelete (line 39) | taActionDelete
type textAreaSpan (line 68) | type textAreaSpan struct
type textAreaUndoItem (line 85) | type textAreaUndoItem struct
type TextArea (line 192) | type TextArea struct
method SetText (line 390) | func (t *TextArea) SetText(text string, cursorAtTheEnd bool) *TextArea {
method GetText (line 440) | func (t *TextArea) GetText() string {
method getTextBeforeCursor (line 463) | func (t *TextArea) getTextBeforeCursor() string {
method getTextAfterCursor (line 495) | func (t *TextArea) getTextAfterCursor() string {
method HasSelection (line 519) | func (t *TextArea) HasSelection() bool {
method GetSelection (line 532) | func (t *TextArea) GetSelection() (text string, start int, end int) {
method GetCursor (line 598) | func (t *TextArea) GetCursor() (fromRow, fromColumn, toRow, toColumn i...
method GetTextLength (line 616) | func (t *TextArea) GetTextLength() int {
method Replace (line 632) | func (t *TextArea) Replace(start, end int, text string) *TextArea {
method Select (line 653) | func (t *TextArea) Select(start, end int) *TextArea {
method SetWrap (line 762) | func (t *TextArea) SetWrap(wrap bool) *TextArea {
method SetWordWrap (line 777) | func (t *TextArea) SetWordWrap(wrapOnWords bool) *TextArea {
method SetPlaceholder (line 786) | func (t *TextArea) SetPlaceholder(placeholder string) *TextArea {
method SetLabel (line 792) | func (t *TextArea) SetLabel(label string) *TextArea {
method GetLabel (line 798) | func (t *TextArea) GetLabel() string {
method SetLabelWidth (line 804) | func (t *TextArea) SetLabelWidth(width int) *TextArea {
method GetLabelWidth (line 810) | func (t *TextArea) GetLabelWidth() int {
method SetSize (line 818) | func (t *TextArea) SetSize(rows, columns int) *TextArea {
method GetFieldWidth (line 825) | func (t *TextArea) GetFieldWidth() int {
method GetFieldHeight (line 830) | func (t *TextArea) GetFieldHeight() int {
method SetDisabled (line 835) | func (t *TextArea) SetDisabled(disabled bool) FormItem {
method GetDisabled (line 844) | func (t *TextArea) GetDisabled() bool {
method SetMaxLength (line 851) | func (t *TextArea) SetMaxLength(maxLength int) *TextArea {
method setMinCursorPadding (line 858) | func (t *TextArea) setMinCursorPadding(prefix, suffix int) *TextArea {
method SetLabelStyle (line 865) | func (t *TextArea) SetLabelStyle(style tcell.Style) *TextArea {
method GetLabelStyle (line 871) | func (t *TextArea) GetLabelStyle() tcell.Style {
method SetTextStyle (line 876) | func (t *TextArea) SetTextStyle(style tcell.Style) *TextArea {
method GetTextStyle (line 882) | func (t *TextArea) GetTextStyle() tcell.Style {
method SetSelectedStyle (line 887) | func (t *TextArea) SetSelectedStyle(style tcell.Style) *TextArea {
method SetPlaceholderStyle (line 893) | func (t *TextArea) SetPlaceholderStyle(style tcell.Style) *TextArea {
method GetPlaceholderStyle (line 899) | func (t *TextArea) GetPlaceholderStyle() tcell.Style {
method GetOffset (line 906) | func (t *TextArea) GetOffset() (row, column int) {
method SetOffset (line 914) | func (t *TextArea) SetOffset(row, column int) *TextArea {
method SetClipboard (line 927) | func (t *TextArea) SetClipboard(copyToClipboard func(string), pasteFro...
method GetClipboardText (line 947) | func (t *TextArea) GetClipboardText() string {
method SetChangedFunc (line 953) | func (t *TextArea) SetChangedFunc(handler func()) *TextArea {
method SetMovedFunc (line 960) | func (t *TextArea) SetMovedFunc(handler func()) *TextArea {
method SetFinishedFunc (line 966) | func (t *TextArea) SetFinishedFunc(handler func(key tcell.Key)) FormIt...
method Focus (line 972) | func (t *TextArea) Focus(delegate func(p Primitive)) {
method SetFormAttributes (line 984) | func (t *TextArea) SetFormAttributes(labelWidth int, labelColor, bgCol...
method replace (line 1007) | func (t *TextArea) replace(deleteStart, deleteEnd [3]int, insert strin...
method Draw (line 1162) | func (t *TextArea) Draw(screen tcell.Screen) {
method drawPlaceholder (line 1324) | func (t *TextArea) drawPlaceholder(screen tcell.Screen, x, y, width, h...
method reset (line 1337) | func (t *TextArea) reset() {
method extendLines (line 1353) | func (t *TextArea) extendLines(width, maxLines int) {
method truncateLines (line 1443) | func (t *TextArea) truncateLines(fromLine int) {
method findCursor (line 1464) | func (t *TextArea) findCursor(clamp bool, startRow int) {
method setTransform (line 1607) | func (t *TextArea) setTransform(transform func(cluster, rest string, b...
method step (line 1621) | func (t *TextArea) step(text string, pos, endPos [3]int) (cluster, res...
method moveCursor (line 1693) | func (t *TextArea) moveCursor(row, column int) {
method moveWordRight (line 1745) | func (t *TextArea) moveWordRight(after, clamp bool) {
method moveWordLeft (line 1781) | func (t *TextArea) moveWordLeft(clamp bool) {
method deleteLine (line 1836) | func (t *TextArea) deleteLine() {
method getSelection (line 1910) | func (t *TextArea) getSelection() ([3]int, [3]int, int) {
method getSelectedText (line 1923) | func (t *TextArea) getSelectedText() string {
method InputHandler (line 1949) | func (t *TextArea) InputHandler() func(event *tcell.EventKey, setFocus...
method MouseHandler (line 2340) | func (t *TextArea) MouseHandler() func(action MouseAction, event *tcel...
method PasteHandler (line 2438) | func (t *TextArea) PasteHandler() func(pastedText string, setFocus fun...
function NewTextArea (line 351) | func NewTextArea() *TextArea {
FILE: textview.go
type textViewLine (line 16) | type textViewLine struct
type Region (line 27) | type Region struct
type batchWriter (line 45) | type batchWriter struct
method Close (line 50) | func (w *batchWriter) Close() error {
method Clear (line 56) | func (w *batchWriter) Clear() {
method Write (line 62) | func (w *batchWriter) Write(p []byte) (n int, err error) {
method focusChain (line 67) | func (w *batchWriter) focusChain(chain *[]Primitive) bool {
type TextView (line 153) | type TextView struct
method SetLabel (line 280) | func (t *TextView) SetLabel(label string) *TextView {
method GetLabel (line 286) | func (t *TextView) GetLabel() string {
method SetLabelWidth (line 292) | func (t *TextView) SetLabelWidth(width int) *TextView {
method SetSize (line 301) | func (t *TextView) SetSize(rows, columns int) *TextView {
method GetFieldWidth (line 308) | func (t *TextView) GetFieldWidth() int {
method GetFieldHeight (line 313) | func (t *TextView) GetFieldHeight() int {
method SetDisabled (line 318) | func (t *TextView) SetDisabled(disabled bool) FormItem {
method GetDisabled (line 323) | func (t *TextView) GetDisabled() bool {
method SetScrollable (line 330) | func (t *TextView) SetScrollable(scrollable bool) *TextView {
method SetWrap (line 341) | func (t *TextView) SetWrap(wrap bool) *TextView {
method SetWordWrap (line 353) | func (t *TextView) SetWordWrap(wrapOnWords bool) *TextView {
method SetMaxLines (line 370) | func (t *TextView) SetMaxLines(maxLines int) *TextView {
method SetTextAlign (line 377) | func (t *TextView) SetTextAlign(align int) *TextView {
method SetTextColor (line 383) | func (t *TextView) SetTextColor(color tcell.Color) *TextView {
method SetBackgroundColor (line 392) | func (t *TextView) SetBackgroundColor(color tcell.Color) *Box {
method SetTextStyle (line 401) | func (t *TextView) SetTextStyle(style tcell.Style) *TextView {
method SetText (line 411) | func (t *TextView) SetText(text string) *TextView {
method GetText (line 427) | func (t *TextView) GetText(stripAllTags bool) string {
method GetOriginalLineCount (line 457) | func (t *TextView) GetOriginalLineCount() int {
method GetWrappedLineCount (line 485) | func (t *TextView) GetWrappedLineCount() int {
method SetDynamicColors (line 494) | func (t *TextView) SetDynamicColors(dynamic bool) *TextView {
method SetRegions (line 504) | func (t *TextView) SetRegions(regions bool) *TextView {
method SetChangedFunc (line 528) | func (t *TextView) SetChangedFunc(handler func()) *TextView {
method SetDoneFunc (line 536) | func (t *TextView) SetDoneFunc(handler func(key tcell.Key)) *TextView {
method SetHighlightedFunc (line 549) | func (t *TextView) SetHighlightedFunc(handler func(added, removed, rem...
method SetFinishedFunc (line 555) | func (t *TextView) SetFinishedFunc(handler func(key tcell.Key)) FormIt...
method SetFormAttributes (line 561) | func (t *TextView) SetFormAttributes(labelWidth int, labelColor, bgCol...
method ScrollTo (line 571) | func (t *TextView) ScrollTo(row, column int) *TextView {
method ScrollToBeginning (line 583) | func (t *TextView) ScrollToBeginning() *TextView {
method ScrollToEnd (line 596) | func (t *TextView) ScrollToEnd() *TextView {
method GetScrollOffset (line 607) | func (t *TextView) GetScrollOffset() (row, column int) {
method Clear (line 612) | func (t *TextView) Clear() *TextView {
method clear (line 624) | func (t *TextView) clear() {
method Highlight (line 648) | func (t *TextView) Highlight(regionIDs ...string) *TextView {
method GetHighlights (line 722) | func (t *TextView) GetHighlights() (regionIDs []string) {
method SetToggleHighlights (line 733) | func (t *TextView) SetToggleHighlights(toggle bool) *TextView {
method ScrollToHighlight (line 746) | func (t *TextView) ScrollToHighlight() *TextView {
method GetRegionText (line 764) | func (t *TextView) GetRegionText(regionID string) string {
method GetRegions (line 823) | func (t *TextView) GetRegions(startRow int, tail bool) []*Region {
method Focus (line 862) | func (t *TextView) Focus(delegate func(p Primitive)) {
method focusChain (line 879) | func (t *TextView) focusChain(chain *[]Primitive) bool {
method Write (line 888) | func (t *TextView) Write(p []byte) (n int, err error) {
method write (line 897) | func (t *TextView) write(p []byte) (n int, err error) {
method BatchWriter (line 927) | func (t *TextView) BatchWriter() *batchWriter {
method resetIndex (line 935) | func (t *TextView) resetIndex() {
method parseAhead (line 952) | func (t *TextView) parseAhead(width int, stop func(lineNumber int, lin...
method Draw (line 1139) | func (t *TextView) Draw(screen tcell.Screen) {
method InputHandler (line 1426) | func (t *TextView) InputHandler() func(event *tcell.EventKey, setFocus...
method MouseHandler (line 1490) | func (t *TextView) MouseHandler() func(action MouseAction, event *tcel...
function NewTextView (line 261) | func NewTextView() *TextView {
FILE: treeview.go
constant treeNone (line 9) | treeNone int = iota
constant treeHome (line 10) | treeHome
constant treeEnd (line 11) | treeEnd
constant treeMove (line 12) | treeMove
constant treeParent (line 13) | treeParent
constant treeChild (line 14) | treeChild
constant treeScroll (line 15) | treeScroll
type TreeNode (line 19) | type TreeNode struct
method Walk (line 75) | func (n *TreeNode) Walk(callback func(node, parent *TreeNode) bool) *T...
method SetReference (line 100) | func (n *TreeNode) SetReference(reference interface{}) *TreeNode {
method GetReference (line 106) | func (n *TreeNode) GetReference() interface{} {
method SetChildren (line 111) | func (n *TreeNode) SetChildren(childNodes []*TreeNode) *TreeNode {
method GetText (line 117) | func (n *TreeNode) GetText() string {
method GetChildren (line 122) | func (n *TreeNode) GetChildren() []*TreeNode {
method ClearChildren (line 127) | func (n *TreeNode) ClearChildren() *TreeNode {
method AddChild (line 133) | func (n *TreeNode) AddChild(node *TreeNode) *TreeNode {
method RemoveChild (line 140) | func (n *TreeNode) RemoveChild(node *TreeNode) *TreeNode {
method SetSelectable (line 152) | func (n *TreeNode) SetSelectable(selectable bool) *TreeNode {
method SetSelectedFunc (line 159) | func (n *TreeNode) SetSelectedFunc(handler func()) *TreeNode {
method SetExpanded (line 165) | func (n *TreeNode) SetExpanded(expanded bool) *TreeNode {
method Expand (line 171) | func (n *TreeNode) Expand() *TreeNode {
method Collapse (line 177) | func (n *TreeNode) Collapse() *TreeNode {
method ExpandAll (line 183) | func (n *TreeNode) ExpandAll() *TreeNode {
method CollapseAll (line 192) | func (n *TreeNode) CollapseAll() *TreeNode {
method IsExpanded (line 201) | func (n *TreeNode) IsExpanded() bool {
method SetText (line 206) | func (n *TreeNode) SetText(text string) *TreeNode {
method GetColor (line 212) | func (n *TreeNode) GetColor() tcell.Color {
method SetColor (line 220) | func (n *TreeNode) SetColor(color tcell.Color) *TreeNode {
method SetTextStyle (line 227) | func (n *TreeNode) SetTextStyle(style tcell.Style) *TreeNode {
method GetTextStyle (line 233) | func (n *TreeNode) GetTextStyle() tcell.Style {
method SetSelectedTextStyle (line 238) | func (n *TreeNode) SetSelectedTextStyle(style tcell.Style) *TreeNode {
method GetSelectedTextStyle (line 245) | func (n *TreeNode) GetSelectedTextStyle() tcell.Style {
method SetIndent (line 252) | func (n *TreeNode) SetIndent(indent int) *TreeNode {
method GetLevel (line 261) | func (n *TreeNode) GetLevel() int {
function NewTreeNode (line 59) | func NewTreeNode(text string) *TreeNode {
type TreeView (line 299) | type TreeView struct
method SetRoot (line 369) | func (t *TreeView) SetRoot(root *TreeNode) *TreeView {
method GetRoot (line 376) | func (t *TreeView) GetRoot() *TreeNode {
method SetCurrentNode (line 387) | func (t *TreeView) SetCurrentNode(node *TreeNode) *TreeView {
method GetCurrentNode (line 394) | func (t *TreeView) GetCurrentNode() *TreeNode {
method GetPath (line 402) | func (t *TreeView) GetPath(node *TreeNode) []*TreeNode {
method SetTopLevel (line 430) | func (t *TreeView) SetTopLevel(topLevel int) *TreeView {
method SetPrefixes (line 446) | func (t *TreeView) SetPrefixes(prefixes []string) *TreeView {
method SetAlign (line 454) | func (t *TreeView) SetAlign(align bool) *TreeView {
method SetGraphics (line 461) | func (t *TreeView) SetGraphics(showGraphics bool) *TreeView {
method SetGraphicsColor (line 467) | func (t *TreeView) SetGraphicsColor(color tcell.Color) *TreeView {
method SetChangedFunc (line 474) | func (t *TreeView) SetChangedFunc(handler func(node *TreeNode)) *TreeV...
method SetSelectedFunc (line 481) | func (t *TreeView) SetSelectedFunc(handler func(node *TreeNode)) *Tree...
method GetSelectedFunc (line 488) | func (t *TreeView) GetSelectedFunc() func(node *TreeNode) {
method SetDoneFunc (line 494) | func (t *TreeView) SetDoneFunc(handler func(key tcell.Key)) *TreeView {
method GetScrollOffset (line 502) | func (t *TreeView) GetScrollOffset() int {
method GetRowCount (line 510) | func (t *TreeView) GetRowCount() int {
method Move (line 521) | func (t *TreeView) Move(offset int) *TreeView {
method process (line 535) | func (t *TreeView) process(drawingAfter bool) {
method Draw (line 695) | func (t *TreeView) Draw(screen tcell.Screen) {
method InputHandler (line 802) | func (t *TreeView) InputHandler() func(event *tcell.EventKey, setFocus...
method MouseHandler (line 869) | func (t *TreeView) MouseHandler() func(action MouseAction, event *tcel...
function NewTreeView (line 358) | func NewTreeView() *TreeView {
FILE: util.go
constant AlignLeft (line 13) | AlignLeft = iota
constant AlignCenter (line 14) | AlignCenter
constant AlignRight (line 15) | AlignRight
constant AlignTop (line 16) | AlignTop = 0
constant AlignBottom (line 17) | AlignBottom = 2
function init (line 32) | func init() {
function Print (line 49) | func Print(screen tcell.Screen, text string, x, y, maxWidth, align int, ...
function printWithStyle (line 60) | func printWithStyle(screen tcell.Screen, text string, x, y, skipWidth, m...
function PrintSimple (line 156) | func PrintSimple(screen tcell.Screen, text string, x, y int) {
Condensed preview — 92 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (780K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 13,
"preview": "github: rivo\n"
},
{
"path": "CONTRIBUTING.md",
"chars": 3230,
"preview": "# Contributing to tview\n\nFirst of all, thank you for taking the time to contribute.\n\nThe following provides you with som"
},
{
"path": "LICENSE.txt",
"chars": 1072,
"preview": "MIT License\n\nCopyright (c) 2018 Oliver Kuederle\n\nPermission is hereby granted, free of charge, to any person obtaining a"
},
{
"path": "README.md",
"chars": 10878,
"preview": "# Rich Interactive Widgets for Terminal UIs\n\n[](https://pkg.g"
},
{
"path": "ansi.go",
"chars": 8371,
"preview": "package tview\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// The states of the ANSI escape code parser.\ncon"
},
{
"path": "application.go",
"chars": 26195,
"preview": "package tview\n\nimport (\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/gdamore/tcell/v2\"\n)\n\nconst (\n\t// The size of the event/"
},
{
"path": "borders.go",
"chars": 1260,
"preview": "package tview\n\n// Borders defines various borders used when primitives are drawn.\n// These may be changed to accommodate"
},
{
"path": "box.go",
"chars": 19266,
"preview": "package tview\n\nimport (\n\t\"github.com/gdamore/tcell/v2\"\n)\n\n// Box implements the Primitive interface with an empty backgr"
},
{
"path": "button.go",
"chars": 5765,
"preview": "package tview\n\nimport (\n\t\"github.com/gdamore/tcell/v2\"\n)\n\n// Button is labeled box that triggers an action when selected"
},
{
"path": "checkbox.go",
"chars": 9857,
"preview": "package tview\n\nimport (\n\t\"github.com/gdamore/tcell/v2\"\n)\n\n// Checkbox implements a simple box for boolean values which c"
},
{
"path": "demos/box/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/box/main.go",
"chars": 504,
"preview": "// Demo code for the Box primitive.\npackage main\n\nimport (\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/tview\"\n)\n\nfu"
},
{
"path": "demos/button/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/button/main.go",
"chars": 360,
"preview": "// Demo code for the Button primitive.\npackage main\n\nimport \"github.com/rivo/tview\"\n\nfunc main() {\n\tapp := tview.NewAppl"
},
{
"path": "demos/checkbox/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/checkbox/main.go",
"chars": 297,
"preview": "// Demo code for the Checkbox primitive.\npackage main\n\nimport \"github.com/rivo/tview\"\n\nfunc main() {\n\tapp := tview.NewAp"
},
{
"path": "demos/dropdown/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/dropdown/main.go",
"chars": 382,
"preview": "// Demo code for the DropDown primitive.\npackage main\n\nimport \"github.com/rivo/tview\"\n\nfunc main() {\n\tapp := tview.NewAp"
},
{
"path": "demos/flex/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/flex/main.go",
"chars": 751,
"preview": "// Demo code for the Flex primitive.\npackage main\n\nimport (\n\t\"github.com/rivo/tview\"\n)\n\nfunc main() {\n\tapp := tview.NewA"
},
{
"path": "demos/form/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/form/main.go",
"chars": 835,
"preview": "// Demo code for the Form primitive.\npackage main\n\nimport (\n\t\"github.com/rivo/tview\"\n)\n\nfunc main() {\n\tapp := tview.NewA"
},
{
"path": "demos/frame/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/frame/main.go",
"chars": 800,
"preview": "// Demo code for the Frame primitive.\npackage main\n\nimport (\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/tview\"\n)\n\n"
},
{
"path": "demos/grid/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/grid/main.go",
"chars": 1064,
"preview": "// Demo code for the Grid primitive.\npackage main\n\nimport (\n\t\"github.com/rivo/tview\"\n)\n\nfunc main() {\n\tnewPrimitive := f"
},
{
"path": "demos/image/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/image/main.go",
"chars": 93780,
"preview": "// Demo code for the Image primitive.\npackage main\n\nimport (\n\t\"bytes\"\n\t\"encoding/base64\"\n\n\t\"image/jpeg\"\n\t\"image/png\"\n\n\t\""
},
{
"path": "demos/inputfield/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/inputfield/autocomplete/main.go",
"chars": 7568,
"preview": "package main\n\nimport (\n\t\"strings\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/tview\"\n)\n\n// 1,000 most common Engli"
},
{
"path": "demos/inputfield/autocompleteasync/main.go",
"chars": 1866,
"preview": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\t\"gith"
},
{
"path": "demos/inputfield/main.go",
"chars": 508,
"preview": "// Demo code for the InputField primitive.\npackage main\n\nimport (\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/tview"
},
{
"path": "demos/list/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/list/main.go",
"chars": 562,
"preview": "// Demo code for the List primitive.\npackage main\n\nimport (\n\t\"github.com/rivo/tview\"\n)\n\nfunc main() {\n\tapp := tview.NewA"
},
{
"path": "demos/modal/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/modal/main.go",
"chars": 461,
"preview": "// Demo code for the Modal primitive.\npackage main\n\nimport (\n\t\"github.com/rivo/tview\"\n)\n\nfunc main() {\n\tapp := tview.New"
},
{
"path": "demos/pages/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/pages/main.go",
"chars": 784,
"preview": "// Demo code for the Pages primitive.\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/rivo/tview\"\n)\n\nconst pageCount = 5\n\nfu"
},
{
"path": "demos/presentation/center.go",
"chars": 490,
"preview": "package main\n\nimport \"github.com/rivo/tview\"\n\n// Center returns a new primitive which shows the provided primitive in it"
},
{
"path": "demos/presentation/code.go",
"chars": 621,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/rivo/tview\"\n)\n\n// The width of the code window.\nconst codeWidth = 56\n\n// Cod"
},
{
"path": "demos/presentation/colors.go",
"chars": 1280,
"preview": "package main\n\nimport (\n\t\"strings\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/tview\"\n)\n\nconst colorsText = `You ca"
},
{
"path": "demos/presentation/cover.go",
"chars": 1691,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/tview\"\n)\n\nconst logo = `\n _"
},
{
"path": "demos/presentation/end.go",
"chars": 473,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/tview\"\n)\n\n// End shows the final slide.\n"
},
{
"path": "demos/presentation/flex.go",
"chars": 1304,
"preview": "package main\n\nimport (\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/tview\"\n)\n\n// Flex demonstrates flexbox layout.\nf"
},
{
"path": "demos/presentation/form.go",
"chars": 15358,
"preview": "package main\n\nimport (\n\t\"bytes\"\n\t\"encoding/base64\"\n\t\"image/jpeg\"\n\n\t\"github.com/rivo/tview\"\n)\n\nconst form = `[green]packa"
},
{
"path": "demos/presentation/grid.go",
"chars": 1652,
"preview": "package main\n\nimport (\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/tview\"\n)\n\n// Grid demonstrates the grid layout.\n"
},
{
"path": "demos/presentation/helloworld.go",
"chars": 893,
"preview": "package main\n\nimport (\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/tview\"\n)\n\nconst helloWorld = `[green]package[whi"
},
{
"path": "demos/presentation/inputfield.go",
"chars": 1195,
"preview": "package main\n\nimport (\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/tview\"\n)\n\nconst inputField = `[green]package[whi"
},
{
"path": "demos/presentation/introduction.go",
"chars": 842,
"preview": "package main\n\nimport \"github.com/rivo/tview\"\n\n// Introduction returns a tview.List with the highlights of the tview pack"
},
{
"path": "demos/presentation/main.go",
"chars": 2561,
"preview": "/*\nA presentation of the tview package, implemented with tview.\n\n# Navigation\n\nThe presentation will advance to the next"
},
{
"path": "demos/presentation/table.go",
"chars": 13104,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/tview\"\n)\n\nconst tableData = `"
},
{
"path": "demos/presentation/textview.go",
"chars": 5043,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/tview\"\n)\n\nconst textV"
},
{
"path": "demos/presentation/treeview.go",
"chars": 5017,
"preview": "package main\n\nimport (\n\t\"strings\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/tview\"\n)\n\nconst treeAllCode = `[gree"
},
{
"path": "demos/primitive/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/primitive/main.go",
"chars": 2527,
"preview": "// Demo code which illustrates how to implement your own primitive.\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/gdamore/"
},
{
"path": "demos/table/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/table/main.go",
"chars": 1611,
"preview": "// Demo code for the Table primitive.\npackage main\n\nimport (\n\t\"strings\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/riv"
},
{
"path": "demos/table/virtualtable/README.md",
"chars": 29,
"preview": ""
},
{
"path": "demos/table/virtualtable/main.go",
"chars": 894,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\n\t\"github.com/rivo/tview\"\n)\n\ntype TableData struct {\n\ttview.TableContentReadOnly\n}"
},
{
"path": "demos/textarea/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/textarea/main.go",
"chars": 4149,
"preview": "// Demo code for the TextArea primitive.\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo"
},
{
"path": "demos/textview/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/textview/chat/README.md",
"chars": 29,
"preview": ""
},
{
"path": "demos/textview/chat/chain.txt",
"chars": 13280,
"preview": "H4sIAAAAAAAA/0y6DYhUV7su6Lv+qrrj5/VkxBEpmkYaCSKOn9cTvBLE8fY4XsnxNh5xMn084q69V1Vte9fedfba1W2JOI4nIyJeb+M44ogYCY6IZMRxRCQE"
},
{
"path": "demos/textview/chat/main.go",
"chars": 4353,
"preview": "// Demo code for a simple chat application using TextView regions.\npackage main\n\nimport (\n\t\"bytes\"\n\t\"compress/gzip\"\n\t_ \""
},
{
"path": "demos/textview/main.go",
"chars": 2372,
"preview": "// Demo code for the TextView primitive.\npackage main\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/gdamo"
},
{
"path": "demos/treeview/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/treeview/main.go",
"chars": 1496,
"preview": "// Demo code for the TreeView primitive.\npackage main\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\t"
},
{
"path": "demos/unicode/README.md",
"chars": 30,
"preview": "\n"
},
{
"path": "demos/unicode/main.go",
"chars": 1246,
"preview": "// Demo code for unicode support (demonstrates wide Chinese characters).\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/riv"
},
{
"path": "doc.go",
"chars": 8698,
"preview": "/*\nPackage tview implements rich widgets for terminal based user interfaces. The\nwidgets provided with this package are "
},
{
"path": "dropdown.go",
"chars": 23256,
"preview": "package tview\n\nimport (\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/gdamore/tcell/v2\"\n)\n\n// dropDownOption is one option that can"
},
{
"path": "flex.go",
"chars": 8279,
"preview": "package tview\n\nimport (\n\t\"github.com/gdamore/tcell/v2\"\n)\n\n// Flex directions.\nconst (\n\t// One item per row.\n\tFlexRow = 0"
},
{
"path": "form.go",
"chars": 26898,
"preview": "package tview\n\nimport (\n\t\"image\"\n\n\t\"github.com/gdamore/tcell/v2\"\n)\n\nvar (\n\t// DefaultFormFieldWidth is the default field"
},
{
"path": "frame.go",
"chars": 6406,
"preview": "package tview\n\nimport (\n\t\"github.com/gdamore/tcell/v2\"\n)\n\n// frameText holds information about a line of text shown in t"
},
{
"path": "go.mod",
"chars": 389,
"preview": "module github.com/rivo/tview\n\ngo 1.18\n\nrequire (\n\tgithub.com/gdamore/tcell/v2 v2.8.1\n\tgithub.com/lucasb-eyer/go-colorful"
},
{
"path": "go.sum",
"chars": 6915,
"preview": "github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw=\ngithub.com/gdamore/encoding v1.0.1/go"
},
{
"path": "grid.go",
"chars": 21091,
"preview": "package tview\n\nimport (\n\t\"math\"\n\n\t\"github.com/gdamore/tcell/v2\"\n)\n\n// gridItem represents one primitive and its possible"
},
{
"path": "image.go",
"chars": 25429,
"preview": "package tview\n\nimport (\n\t\"image\"\n\t\"math\"\n\n\t\"github.com/gdamore/tcell/v2\"\n)\n\n// Types of dithering applied to images.\ncon"
},
{
"path": "inputfield.go",
"chars": 23921,
"preview": "package tview\n\nimport (\n\t\"math\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/uniseg\"\n"
},
{
"path": "list.go",
"chars": 24154,
"preview": "package tview\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/gdamore/tcell/v2\"\n)\n\n// listItem represents one item in a List.\n"
},
{
"path": "modal.go",
"chars": 6645,
"preview": "package tview\n\nimport (\n\t\"github.com/gdamore/tcell/v2\"\n)\n\n// Modal is a centered message window used to inform the user "
},
{
"path": "pages.go",
"chars": 9299,
"preview": "package tview\n\nimport (\n\t\"github.com/gdamore/tcell/v2\"\n)\n\n// page represents one page of a Pages object.\ntype page struc"
},
{
"path": "primitive.go",
"chars": 4163,
"preview": "package tview\n\nimport \"github.com/gdamore/tcell/v2\"\n\n// Primitive is the top-most interface for all graphical primitives"
},
{
"path": "semigraphics.go",
"chars": 20078,
"preview": "package tview\n\nimport \"github.com/gdamore/tcell/v2\"\n\n// Semigraphics provides an easy way to access unicode characters f"
},
{
"path": "strings.go",
"chars": 19322,
"preview": "package tview\n\nimport (\n\t\"math/rand\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode/utf8\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\t\"g"
},
{
"path": "styles.go",
"chars": 1684,
"preview": "package tview\n\nimport \"github.com/gdamore/tcell/v2\"\n\n// Theme defines the colors used when primitives are initialized.\nt"
},
{
"path": "table.go",
"chars": 52916,
"preview": "package tview\n\nimport (\n\t\"sort\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\tcolorful \"github.com/lucasb-eyer/go-colorful\"\n)\n\n// Tab"
},
{
"path": "textarea.go",
"chars": 79962,
"preview": "package tview\n\nimport (\n\t\"math\"\n\t\"strings\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\t\"github.com/rivo/"
},
{
"path": "textview.go",
"chars": 46468,
"preview": "package tview\n\nimport (\n\t\"math\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/gdamore/tcell/v2\"\n\tcolorful \"github.com/lucasb-eyer/go-"
},
{
"path": "treeview.go",
"chars": 26102,
"preview": "package tview\n\nimport (\n\t\"github.com/gdamore/tcell/v2\"\n)\n\n// Tree navigation events.\nconst (\n\ttreeNone int = iota\n\ttreeH"
},
{
"path": "util.go",
"chars": 4808,
"preview": "package tview\n\nimport (\n\t\"math\"\n\t\"os\"\n\t\"regexp\"\n\n\t\"github.com/gdamore/tcell/v2\"\n)\n\n// Text alignment within a box. Also "
}
]
About this extraction
This page contains the full source code of the rivo/tview GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 92 files (710.3 KB), approximately 246.4k tokens, and a symbol index with 983 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.