Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Feature/swap to tcell/v2 #73

Merged
merged 29 commits into from
Dec 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
cb1cfb0
Add frame customization
dankox Oct 28, 2020
bf52b10
first try to swap termbox to tcell
dankox Nov 2, 2020
ace8fe6
copy of termbox compat from tcell with some changes
dankox Nov 4, 2020
83d33e6
add debug configuration
dankox Nov 4, 2020
a4fe1ef
return back CtrlC (it works now)
dankox Nov 4, 2020
5f6ae5b
fix CtrlSpace and Spacebar keys
dankox Nov 4, 2020
db74815
fix widget example (coloring)
dankox Nov 4, 2020
462a239
True colors implementation with example
dankox Nov 5, 2020
8e73c55
fix colors for lower output modes
dankox Nov 5, 2020
a78cd5e
Fix colorstrue example terminal settings
dankox Nov 7, 2020
7a7f847
Add mouse event support
dankox Nov 7, 2020
a81de49
Change to tcell v2
dankox Nov 7, 2020
765f780
Change tcell calls to private
dankox Nov 8, 2020
0414b07
minor correction in mouse example
dankox Nov 8, 2020
eaa6f5a
Change colors to mimic tcell/v2 colors
dankox Nov 8, 2020
4377f3d
remove .vscode/launch.json and update gitignore
dankox Nov 8, 2020
7e477c7
update go.sum
dankox Nov 8, 2020
f84d3fd
Update mouse example and add comment to SetKeybinding about mouse keys
dankox Nov 8, 2020
ea044eb
Update readme and hello example
mjarkk Nov 8, 2020
ae9b323
Add new feature to readme
mjarkk Nov 8, 2020
e19a29b
Move attributes and keys to respective files
dankox Nov 8, 2020
99abdfd
Fix some keybindings
dankox Nov 8, 2020
da67745
refactoring tcell functions part 1
dankox Nov 9, 2020
5c8be1d
Add strikethrough attribute
dankox Nov 9, 2020
5921dae
fix KeySpace
dankox Nov 9, 2020
8b345d0
refactoring tcell functions finished
dankox Nov 10, 2020
e283cd1
fix g.Rune() function
dankox Nov 10, 2020
ab1c231
Add CHANGES documentation
dankox Nov 10, 2020
d20d452
Remove all gocui. prefixes in changes_tcell
mjarkk Nov 14, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*.swp
.idea
.vscode
56 changes: 56 additions & 0 deletions CHANGES_tcell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Change from termbox to tcell

Original GOCUI was written on top of [termbox](https://github.com/nsf/termbox-go) package. This document describes changes which were done to be able to use to [tcell/v2](https://github.com/gdamore/tcell) package.

## Attribute color
mjarkk marked this conversation as resolved.
Show resolved Hide resolved

Attribute type represents a terminal attribute like color and font effects. Color and font effects can be combined using bitwise OR (`|`).

In `termbox` colors were represented by range 1 to 256. `0` was default color which uses the terminal default setting.

In `tcell` colors can be represented in 24bit, and all of them starts from 0. Valid colors have special flag which gives them real value starting from 4294967296. `0` is a default similart to `termbox`.
The change to support all these colors was made in a way, that original colors from 1 to 256 are backward compatible and if user has color specified as
`Attribute(ansicolor+1)` without the valid color flag, it will be translated to `tcell` color by subtracting 1 and making the color valid by adding the flag. This should ensure backward compatibility.
mjarkk marked this conversation as resolved.
Show resolved Hide resolved

All the color constants are the same with different underlying values. From user perspective, this should be fine unless some arithmetic is done with it. For example `ColorBlack` was `1` in original version but is `4294967296` in new version.

GOCUI provides a few helper functions which could be used to get the real color value or to create a color attribute.

- `(a Attribute).Hex()` - returns `int32` value of the color represented as `Red << 16 | Green << 8 | Blue`
- `(a Attribute).RGB()` - returns 3 `int32` values for red, green and blue color.
mjarkk marked this conversation as resolved.
Show resolved Hide resolved
- `GetColor(string)` - creates `Attribute` from color passed as a string. This can be hex value or color name (W3C name).
- `Get256Color(int32)` - creates `Attribute` from color number (ANSI colors).
- `GetRGBColor(int32)` - creates `Attribute` from color number created the same way as `Hex()` function returns.
- `NewRGBColor(int32, int32, int32)` - creates `Attribute` from color numbers for red, green and blue values.

## Attribute font effect

There were 3 attributes for font effect, `AttrBold`, `AttrUnderline` and `AttrReverse`.

`tcell` supports more attributes, so they were added. All of these attributes have different values from before. However they can be used in the same way as before.

All the font effect attributes:
- `AttrBold`
- `AttrBlink`
- `AttrReverse`
- `AttrUnderline`
- `AttrDim`
- `AttrItalic`
- `AttrStrikeThrough`
mjarkk marked this conversation as resolved.
Show resolved Hide resolved

## OutputMode

`OutputMode` in `termbox` was used to translate colors into the correct range. So for example in `OutputGrayscale` you had colors from 1 - 24 all representing gray colors in range 232 - 255, and white and black color.
mjarkk marked this conversation as resolved.
Show resolved Hide resolved

`tcell` colors are 24bit and they are translated by the library into the color which can be read by terminal.

The original translation from `termbox` was included in GOCUI to be backward compatible. This is enabled in all the original modes: `OutputNormal`, `Output216`, `OutputGrayscale` and `Output256`.
mjarkk marked this conversation as resolved.
Show resolved Hide resolved

`OutputTrue` is a new mode. It is recomended, because in this mode GOCUI doesn't do any kind of translation of the colors and pass them directly to `tcell`. If user wants to use true color in terminal and this mode doesn't work, it might be because of the terminal setup. `tcell` has a documentation what needs to be done, but in short `COLORTERM=truecolor` environment variable should help (see [_examples/colorstrue.go](./_examples/colorstrue.go)). Other way would be to have `TERM` environment variable having value with suffix `-truecolor`. To disable true color set `TCELL_TRUECOLOR=disable`.
mjarkk marked this conversation as resolved.
Show resolved Hide resolved

## Keybinding

`termbox` had different way of handling input from terminal than `tcell`. This leads to some adjustement on how the keys are represented.
In general, all the keys in GOCUI should be presented from before, but the underlying values might be different. This could lead to some problems if a user uses different parser to create the `Key` for the keybinding. If using GOCUI parser, everything should be ok.

Mouse is handled differently in `tcell`, but translation was done to keep it in the same way as it was before. However this was harder to test due to different behaviour across the platforms, so if anything is missing or not working, please report.
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[![GoDoc](https://godoc.org/github.com/awesome-gocui/gocui?status.svg)](https://godoc.org/github.com/awesome-gocui/gocui)
![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/awesome-gocui/gocui.svg)

Minimalist Go package aimed at creating Console User Interfaces.
Minimalist Go package aimed at creating Console User Interfaces.
A community fork based on the amazing work of [jroimartin](https://github.com/jroimartin/gocui)

## Features
Expand All @@ -23,8 +23,9 @@ A community fork based on the amazing work of [jroimartin](https://github.com/jr

## About fork

This fork has many improvements over the original work from [jroimartin](https://github.com/jroimartin/gocui).
This fork has many improvements over the original work from [jroimartin](https://github.com/jroimartin/gocui).

* Written ontop of TCell
* Better wide character support
* Support for 1 Line height views
* Better support for running in docker container
Expand Down Expand Up @@ -68,7 +69,7 @@ import (
)

func main() {
g, err := gocui.NewGui(gocui.OutputNormal, false)
g, err := gocui.NewGui(gocui.OutputNormal, true)
if err != nil {
log.Panicln(err)
}
Expand All @@ -91,11 +92,14 @@ func layout(g *gocui.Gui) error {
if !gocui.IsUnknownView(err) {
return err
}
fmt.Fprintln(v, "Hello world!")

if _, err := g.SetCurrentView("hello"); err != nil {
return err
}

fmt.Fprintln(v, "Hello world!")
}

return nil
}

Expand Down
109 changes: 109 additions & 0 deletions _examples/colorstrue.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright 2014 The gocui Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
"fmt"
"log"
"os"

"github.com/awesome-gocui/gocui"
colorful "github.com/lucasb-eyer/go-colorful"
)

var dark = false

func main() {
os.Setenv("COLORTERM", "truecolor")
g, err := gocui.NewGui(gocui.OutputTrue, true)

if err != nil {
log.Panicln(err)
}
defer g.Close()

g.SetManagerFunc(layout)

if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
log.Panicln(err)
}

if err := g.SetKeybinding("", gocui.KeyCtrlR, gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error {
if dark {
dark = false
} else {
dark = true
}
displayHsv(v)

return nil
}); err != nil {
log.Panicln(err)
}

if err := g.MainLoop(); err != nil && !gocui.IsQuit(err) {
log.Panicln(err)
}
}

func layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
rows := 33
cols := 182
if maxY < rows {
rows = maxY
}
if maxX < cols {
cols = maxX
}

if v, err := g.SetView("colors", 0, 0, cols-1, rows-1, 0); err != nil {
if !gocui.IsUnknownView(err) {
return err
}

v.FrameColor = gocui.GetColor("#FFAA55")
displayHsv(v)

if _, err := g.SetCurrentView("colors"); err != nil {
return err
}
}
return nil
}

func displayHsv(v *gocui.View) {
v.Clear()
str := ""
// HSV color space (lines are value or saturation)
for i := 50; i > 0; i -= 2 {
// Hue
for j := 0; j < 360; j += 2 {
ir, ig, ib := hsv(j, i-1)
ir2, ig2, ib2 := hsv(j, i)
str += fmt.Sprintf("\x1b[48;2;%d;%d;%dm\x1b[38;2;%d;%d;%dm▀\x1b[0m", ir, ig, ib, ir2, ig2, ib2)
}
str += "\n"
fmt.Fprint(v, str)
str = ""
}

fmt.Fprintln(v, "\n\x1b[38;5;245mCtrl + R - Switch light/dark mode")
fmt.Fprintln(v, "\nCtrl + C - Exit\n")
fmt.Fprint(v, "Example should enable true color, but if it doesn't work run this command: \x1b[0mexport COLORTERM=truecolor")
}

func hsv(hue, sv int) (uint32, uint32, uint32) {
if !dark {
ir, ig, ib, _ := colorful.Hsv(float64(hue), float64(sv)/50, float64(1)).RGBA()
return ir >> 8, ig >> 8, ib >> 8
}
ir, ig, ib, _ := colorful.Hsv(float64(hue), float64(1), float64(sv)/50).RGBA()
return ir >> 8, ig >> 8, ib >> 8
}

func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
141 changes: 141 additions & 0 deletions _examples/custom_frame.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package main

import (
"fmt"
"log"

"github.com/awesome-gocui/gocui"
)

var (
viewArr = []string{"v1", "v2", "v3", "v4"}
active = 0
)

func setCurrentViewOnTop(g *gocui.Gui, name string) (*gocui.View, error) {
if _, err := g.SetCurrentView(name); err != nil {
return nil, err
}
return g.SetViewOnTop(name)
}

func nextView(g *gocui.Gui, v *gocui.View) error {
nextIndex := (active + 1) % len(viewArr)
name := viewArr[nextIndex]

out, err := g.View("v1")
if err != nil {
return err
}
fmt.Fprintln(out, "Going from view "+v.Name()+" to "+name)

if _, err := setCurrentViewOnTop(g, name); err != nil {
return err
}

if nextIndex == 3 {
g.Cursor = true
} else {
g.Cursor = false
}

active = nextIndex
return nil
}

func layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
if v, err := g.SetView("v1", 0, 0, maxX/2-1, maxY/2-1, gocui.RIGHT); err != nil {
if !gocui.IsUnknownView(err) {
return err
}
v.Title = "v1"
v.Autoscroll = true
fmt.Fprintln(v, "View with default frame color")
fmt.Fprintln(v, "It's connected to v2 with overlay RIGHT.\n")
if _, err = setCurrentViewOnTop(g, "v1"); err != nil {
return err
}
}

if v, err := g.SetView("v2", maxX/2-1, 0, maxX-1, maxY/2-1, gocui.LEFT); err != nil {
if !gocui.IsUnknownView(err) {
return err
}
v.Title = "v2"
v.Wrap = true
v.FrameColor = gocui.ColorMagenta
v.FrameRunes = []rune{'═', '│'}
fmt.Fprintln(v, "View with minimum frame customization and colored frame.")
fmt.Fprintln(v, "It's connected to v1 with overlay LEFT.\n")
fmt.Fprintln(v, "\033[35;1mInstructions:\033[0m")
fmt.Fprintln(v, "Press TAB to change current view")
fmt.Fprintln(v, "Press Ctrl+O to toggle gocui.SupportOverlap\n")
fmt.Fprintln(v, "\033[32;2mSelected frame is highlighted with green color\033[0m")
}
if v, err := g.SetView("v3", 0, maxY/2, maxX/2-1, maxY-1, 0); err != nil {
if !gocui.IsUnknownView(err) {
return err
}
v.Title = "v3"
v.Wrap = true
v.Autoscroll = true
v.FrameColor = gocui.ColorCyan
v.TitleColor = gocui.ColorCyan
v.FrameRunes = []rune{'═', '║', '╔', '╗', '╚', '╝'}
fmt.Fprintln(v, "View with basic frame customization and colored frame and title")
fmt.Fprintln(v, "It's not connected to any view.")
}
if v, err := g.SetView("v4", maxX/2, maxY/2, maxX-1, maxY-1, gocui.LEFT); err != nil {
if !gocui.IsUnknownView(err) {
return err
}
v.Title = "v4"
v.Subtitle = "(editable)"
v.Editable = true
v.TitleColor = gocui.ColorYellow
v.FrameColor = gocui.ColorRed
v.FrameRunes = []rune{'═', '║', '╔', '╗', '╚', '╝', '╠', '╣', '╦', '╩', '╬'}
fmt.Fprintln(v, "View with fully customized frame and colored title differently.")
fmt.Fprintln(v, "It's connected to v3 with overlay LEFT.\n")
v.SetCursor(0, 3)
}
return nil
}

func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}

func toggleOverlap(g *gocui.Gui, v *gocui.View) error {
g.SupportOverlaps = !g.SupportOverlaps
return nil
}

func main() {
g, err := gocui.NewGui(gocui.OutputNormal, true)
if err != nil {
log.Panicln(err)
}
defer g.Close()

g.Highlight = true
g.SelFgColor = gocui.ColorGreen
g.SelFrameColor = gocui.ColorGreen

g.SetManagerFunc(layout)

if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
log.Panicln(err)
}
if err := g.SetKeybinding("", gocui.KeyCtrlO, gocui.ModNone, toggleOverlap); err != nil {
log.Panicln(err)
}
if err := g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, nextView); err != nil {
log.Panicln(err)
}

if err := g.MainLoop(); err != nil && !gocui.IsQuit(err) {
log.Panicln(err)
}
}
1 change: 1 addition & 0 deletions _examples/dynamic.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func main() {

g.Highlight = true
g.SelFgColor = gocui.ColorRed
g.SelFrameColor = gocui.ColorRed

g.SetManagerFunc(layout)

Expand Down
2 changes: 1 addition & 1 deletion _examples/hello.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func main() {
}

if err := g.MainLoop(); err != nil && !gocui.IsQuit(err) {
log.Panicln(err.Error())
log.Panicln(err)
}
}

Expand Down
11 changes: 8 additions & 3 deletions _examples/mouse.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ func keybindings(g *gocui.Gui) error {
if err := g.SetKeybinding("msg", gocui.MouseLeft, gocui.ModNone, delMsg); err != nil {
return err
}
if err := g.SetKeybinding("", gocui.MouseRight, gocui.ModNone, delMsg); err != nil {
return err
}
if err := g.SetKeybinding("", gocui.MouseMiddle, gocui.ModNone, delMsg); err != nil {
return err
}
return nil
}

Expand Down Expand Up @@ -103,8 +109,7 @@ func showMsg(g *gocui.Gui, v *gocui.View) error {
}

func delMsg(g *gocui.Gui, v *gocui.View) error {
if err := g.DeleteView("msg"); err != nil {
return err
}
// Error check removed, because delete could be called multiple times with the above keybindings
g.DeleteView("msg")
return nil
}
Loading