mirror of https://github.com/miguelmota/cointop
Merge branch 'cointop-sh:master' into feature/better-resample
commit
f37499a381
@ -0,0 +1,40 @@
|
||||
version: 2.1
|
||||
|
||||
orbs:
|
||||
base: dmx-io/base@2.0.88
|
||||
|
||||
jobs:
|
||||
build_and_push:
|
||||
working_directory: /app
|
||||
docker:
|
||||
- image: docker:17.09.0-ce-git
|
||||
steps:
|
||||
- checkout
|
||||
- setup_remote_docker
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: |
|
||||
apk update
|
||||
apk upgrade
|
||||
apk add --no-cache make
|
||||
- run:
|
||||
name: Build application Docker image
|
||||
command: |
|
||||
make docker-build
|
||||
- deploy:
|
||||
name: Push Docker image to Docker Hub
|
||||
command: |
|
||||
make docker-login-ci
|
||||
make docker-tag-ci
|
||||
make docker-push-ci
|
||||
|
||||
workflows:
|
||||
main:
|
||||
jobs:
|
||||
- build_and_push:
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
ignore: /.*/
|
@ -1,39 +0,0 @@
|
||||
package color
|
||||
|
||||
import "github.com/fatih/color"
|
||||
|
||||
// Color struct
|
||||
type Color color.Color
|
||||
|
||||
var (
|
||||
// Bold color
|
||||
Bold = color.New(color.Bold).SprintFunc()
|
||||
// Black color
|
||||
Black = color.New(color.FgBlack).SprintFunc()
|
||||
// BlackBg color
|
||||
BlackBg = color.New(color.BgBlack, color.FgWhite).SprintFunc()
|
||||
// White color
|
||||
White = color.New(color.FgWhite).SprintFunc()
|
||||
// WhiteBold bold
|
||||
WhiteBold = color.New(color.FgWhite, color.Bold).SprintFunc()
|
||||
// Yellow color
|
||||
Yellow = color.New(color.FgYellow).SprintFunc()
|
||||
// YellowBold color
|
||||
YellowBold = color.New(color.FgYellow, color.Bold).SprintFunc()
|
||||
// YellowBg color
|
||||
YellowBg = color.New(color.BgYellow, color.FgBlack).SprintFunc()
|
||||
// Green color
|
||||
Green = color.New(color.FgGreen).SprintFunc()
|
||||
// GreenBg color
|
||||
GreenBg = color.New(color.BgGreen, color.FgBlack).SprintFunc()
|
||||
// Red color
|
||||
Red = color.New(color.FgRed).SprintFunc()
|
||||
// Cyan color
|
||||
Cyan = color.New(color.FgCyan).SprintFunc()
|
||||
// CyanBg color
|
||||
CyanBg = color.New(color.BgCyan, color.FgBlack).SprintFunc()
|
||||
// Blue color
|
||||
Blue = color.New(color.FgBlue).SprintFunc()
|
||||
// BlueBg color
|
||||
BlueBg = color.New(color.BgBlue).SprintFunc()
|
||||
)
|
@ -0,0 +1,64 @@
|
||||
// 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 gocui
|
||||
|
||||
import (
|
||||
"github.com/gdamore/tcell/v2"
|
||||
)
|
||||
|
||||
// eventBinding are used to link a given key-press event with a handler.
|
||||
type eventBinding struct {
|
||||
viewName string
|
||||
ev tcell.Event // ignore the Time
|
||||
handler func(*Gui, *View) error
|
||||
}
|
||||
|
||||
// newKeybinding returns a new eventBinding object for a key event.
|
||||
func newKeybinding(viewname string, key tcell.Key, ch rune, mod tcell.ModMask, handler func(*Gui, *View) error) (kb *eventBinding) {
|
||||
kb = &eventBinding{
|
||||
viewName: viewname,
|
||||
ev: tcell.NewEventKey(key, ch, mod),
|
||||
handler: handler,
|
||||
}
|
||||
return kb
|
||||
}
|
||||
|
||||
// newKeybinding returns a new eventBinding object for a mouse event.
|
||||
func newMouseBinding(viewname string, btn tcell.ButtonMask, mod tcell.ModMask, handler func(*Gui, *View) error) (kb *eventBinding) {
|
||||
kb = &eventBinding{
|
||||
viewName: viewname,
|
||||
ev: tcell.NewEventMouse(0, 0, btn, mod),
|
||||
handler: handler,
|
||||
}
|
||||
return kb
|
||||
}
|
||||
|
||||
func (kb *eventBinding) matchEvent(e tcell.Event) bool {
|
||||
// TODO: check mask not ==mod?
|
||||
switch tev := e.(type) {
|
||||
case *tcell.EventKey:
|
||||
if kbe, ok := kb.ev.(*tcell.EventKey); ok {
|
||||
if tev.Key() == tcell.KeyRune {
|
||||
return tev.Key() == kbe.Key() && tev.Rune() == kbe.Rune() && tev.Modifiers() == kbe.Modifiers()
|
||||
}
|
||||
return tev.Key() == kbe.Key() && tev.Modifiers() == kbe.Modifiers()
|
||||
}
|
||||
|
||||
case *tcell.EventMouse:
|
||||
if kbe, ok := kb.ev.(*tcell.EventMouse); ok {
|
||||
return kbe.Buttons() == tev.Buttons() && kbe.Modifiers() == tev.Modifiers()
|
||||
}
|
||||
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// matchView returns if the eventBinding matches the current view.
|
||||
func (kb *eventBinding) matchView(v *View) bool {
|
||||
if kb.viewName == "" {
|
||||
return true
|
||||
}
|
||||
return v != nil && kb.viewName == v.name
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
version: 1.0.{build}
|
||||
clone_folder: c:\gopath\src\github.com\gdamore\encoding
|
||||
environment:
|
||||
GOPATH: c:\gopath
|
||||
build_script:
|
||||
- go version
|
||||
- go env
|
||||
- SET PATH=%LOCALAPPDATA%\atom\bin;%GOPATH%\bin;%PATH%
|
||||
- go get -t ./...
|
||||
- go build
|
||||
- go install ./...
|
||||
test_script:
|
||||
- go test ./...
|
@ -0,0 +1,7 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.9.x
|
||||
- 1.10.x
|
||||
- 1.11.x
|
||||
- tip
|
@ -0,0 +1,19 @@
|
||||
## encoding
|
||||
|
||||
[![Linux Status](https://img.shields.io/travis/gdamore/encoding.svg?label=linux)](https://travis-ci.org/gdamore/encoding)
|
||||
[![Windows Status](https://img.shields.io/appveyor/ci/gdamore/encoding.svg?label=windows)](https://ci.appveyor.com/project/gdamore/encoding)
|
||||
[![Apache License](https://img.shields.io/badge/license-APACHE2-blue.svg)](https://github.com/gdamore/encoding/blob/master/LICENSE)
|
||||
[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/gdamore/encoding)
|
||||
[![Go Report Card](http://goreportcard.com/badge/gdamore/encoding)](http://goreportcard.com/report/gdamore/encoding)
|
||||
|
||||
Package encoding provides a number of encodings that are missing from the
|
||||
standard Go [encoding]("https://godoc.org/golang.org/x/text/encoding") package.
|
||||
|
||||
We hope that we can contribute these to the standard Go library someday. It
|
||||
turns out that some of these are useful for dealing with I/O streams coming
|
||||
from non-UTF friendly sources.
|
||||
|
||||
The UTF8 Encoder is also useful for situations where valid UTF-8 might be
|
||||
carried in streams that contain non-valid UTF; in particular I use it for
|
||||
helping me cope with terminals that embed escape sequences in otherwise
|
||||
valid UTF-8.
|
@ -0,0 +1,36 @@
|
||||
// Copyright 2015 Garrett D'Amore
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"golang.org/x/text/encoding"
|
||||
)
|
||||
|
||||
// ASCII represents the 7-bit US-ASCII scheme. It decodes directly to
|
||||
// UTF-8 without change, as all ASCII values are legal UTF-8.
|
||||
// Unicode values less than 128 (i.e. 7 bits) map 1:1 with ASCII.
|
||||
// It encodes runes outside of that to 0x1A, the ASCII substitution character.
|
||||
var ASCII encoding.Encoding
|
||||
|
||||
func init() {
|
||||
amap := make(map[byte]rune)
|
||||
for i := 128; i <= 255; i++ {
|
||||
amap[byte(i)] = RuneError
|
||||
}
|
||||
|
||||
cm := &Charmap{Map: amap}
|
||||
cm.Init()
|
||||
ASCII = cm
|
||||
}
|
@ -0,0 +1,196 @@
|
||||
// Copyright 2015 Garrett D'Amore
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
const (
|
||||
// RuneError is an alias for the UTF-8 replacement rune, '\uFFFD'.
|
||||
RuneError = '\uFFFD'
|
||||
|
||||
// RuneSelf is the rune below which UTF-8 and the Unicode values are
|
||||
// identical. Its also the limit for ASCII.
|
||||
RuneSelf = 0x80
|
||||
|
||||
// ASCIISub is the ASCII substitution character.
|
||||
ASCIISub = '\x1a'
|
||||
)
|
||||
|
||||
// Charmap is a structure for setting up encodings for 8-bit character sets,
|
||||
// for transforming between UTF8 and that other character set. It has some
|
||||
// ideas borrowed from golang.org/x/text/encoding/charmap, but it uses a
|
||||
// different implementation. This implementation uses maps, and supports
|
||||
// user-defined maps.
|
||||
//
|
||||
// We do assume that a character map has a reasonable substitution character,
|
||||
// and that valid encodings are stable (exactly a 1:1 map) and stateless
|
||||
// (that is there is no shift character or anything like that.) Hence this
|
||||
// approach will not work for many East Asian character sets.
|
||||
//
|
||||
// Measurement shows little or no measurable difference in the performance of
|
||||
// the two approaches. The difference was down to a couple of nsec/op, and
|
||||
// no consistent pattern as to which ran faster. With the conversion to
|
||||
// UTF-8 the code takes about 25 nsec/op. The conversion in the reverse
|
||||
// direction takes about 100 nsec/op. (The larger cost for conversion
|
||||
// from UTF-8 is most likely due to the need to convert the UTF-8 byte stream
|
||||
// to a rune before conversion.
|
||||
//
|
||||
type Charmap struct {
|
||||
transform.NopResetter
|
||||
bytes map[rune]byte
|
||||
runes [256][]byte
|
||||
once sync.Once
|
||||
|
||||
// The map between bytes and runes. To indicate that a specific
|
||||
// byte value is invalid for a charcter set, use the rune
|
||||
// utf8.RuneError. Values that are absent from this map will
|
||||
// be assumed to have the identity mapping -- that is the default
|
||||
// is to assume ISO8859-1, where all 8-bit characters have the same
|
||||
// numeric value as their Unicode runes. (Not to be confused with
|
||||
// the UTF-8 values, which *will* be different for non-ASCII runes.)
|
||||
//
|
||||
// If no values less than RuneSelf are changed (or have non-identity
|
||||
// mappings), then the character set is assumed to be an ASCII
|
||||
// superset, and certain assumptions and optimizations become
|
||||
// available for ASCII bytes.
|
||||
Map map[byte]rune
|
||||
|
||||
// The ReplacementChar is the byte value to use for substitution.
|
||||
// It should normally be ASCIISub for ASCII encodings. This may be
|
||||
// unset (left to zero) for mappings that are strictly ASCII supersets.
|
||||
// In that case ASCIISub will be assumed instead.
|
||||
ReplacementChar byte
|
||||
}
|
||||
|
||||
type cmapDecoder struct {
|
||||
transform.NopResetter
|
||||
runes [256][]byte
|
||||
}
|
||||
|
||||
type cmapEncoder struct {
|
||||
transform.NopResetter
|
||||
bytes map[rune]byte
|
||||
replace byte
|
||||
}
|
||||
|
||||
// Init initializes internal values of a character map. This should
|
||||
// be done early, to minimize the cost of allocation of transforms
|
||||
// later. It is not strictly necessary however, as the allocation
|
||||
// functions will arrange to call it if it has not already been done.
|
||||
func (c *Charmap) Init() {
|
||||
c.once.Do(c.initialize)
|
||||
}
|
||||
|
||||
func (c *Charmap) initialize() {
|
||||
c.bytes = make(map[rune]byte)
|
||||
ascii := true
|
||||
|
||||
for i := 0; i < 256; i++ {
|
||||
r, ok := c.Map[byte(i)]
|
||||
if !ok {
|
||||
r = rune(i)
|
||||
}
|
||||
if r < 128 && r != rune(i) {
|
||||
ascii = false
|
||||
}
|
||||
if r != RuneError {
|
||||
c.bytes[r] = byte(i)
|
||||
}
|
||||
utf := make([]byte, utf8.RuneLen(r))
|
||||
utf8.EncodeRune(utf, r)
|
||||
c.runes[i] = utf
|
||||
}
|
||||
if ascii && c.ReplacementChar == '\x00' {
|
||||
c.ReplacementChar = ASCIISub
|
||||
}
|
||||
}
|
||||
|
||||
// NewDecoder returns a Decoder the converts from the 8-bit
|
||||
// character set to UTF-8. Unknown mappings, if any, are mapped
|
||||
// to '\uFFFD'.
|
||||
func (c *Charmap) NewDecoder() *encoding.Decoder {
|
||||
c.Init()
|
||||
return &encoding.Decoder{Transformer: &cmapDecoder{runes: c.runes}}
|
||||
}
|
||||
|
||||
// NewEncoder returns a Transformer that converts from UTF8 to the
|
||||
// 8-bit character set. Unknown mappings are mapped to 0x1A.
|
||||
func (c *Charmap) NewEncoder() *encoding.Encoder {
|
||||
c.Init()
|
||||
return &encoding.Encoder{
|
||||
Transformer: &cmapEncoder{
|
||||
bytes: c.bytes,
|
||||
replace: c.ReplacementChar,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *cmapDecoder) Transform(dst, src []byte, atEOF bool) (int, int, error) {
|
||||
var e error
|
||||
var ndst, nsrc int
|
||||
|
||||
for _, c := range src {
|
||||
b := d.runes[c]
|
||||
l := len(b)
|
||||
|
||||
if ndst+l > len(dst) {
|
||||
e = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
dst[ndst] = b[i]
|
||||
ndst++
|
||||
}
|
||||
nsrc++
|
||||
}
|
||||
return ndst, nsrc, e
|
||||
}
|
||||
|
||||
func (d *cmapEncoder) Transform(dst, src []byte, atEOF bool) (int, int, error) {
|
||||
var e error
|
||||
var ndst, nsrc int
|
||||
for nsrc < len(src) {
|
||||
if ndst >= len(dst) {
|
||||
e = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
|
||||
r, sz := utf8.DecodeRune(src[nsrc:])
|
||||
if r == utf8.RuneError && sz == 1 {
|
||||
// If its inconclusive due to insufficient data in
|
||||
// in the source, report it
|
||||
if !atEOF && !utf8.FullRune(src[nsrc:]) {
|
||||
e = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if c, ok := d.bytes[r]; ok {
|
||||
dst[ndst] = c
|
||||
} else {
|
||||
dst[ndst] = d.replace
|
||||
}
|
||||
nsrc += sz
|
||||
ndst++
|
||||
}
|
||||
|
||||
return ndst, nsrc, e
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
// Copyright 2015 Garrett D'Amore
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package encoding provides a few of the encoding structures that are
|
||||
// missing from the Go x/text/encoding tree.
|
||||
package encoding
|
@ -0,0 +1,273 @@
|
||||
// Copyright 2015 Garrett D'Amore
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"golang.org/x/text/encoding"
|
||||
)
|
||||
|
||||
// EBCDIC represents the 8-bit EBCDIC scheme, found in some mainframe
|
||||
// environments. If you don't know what this is, consider yourself lucky.
|
||||
var EBCDIC encoding.Encoding
|
||||
|
||||
func init() {
|
||||
cm := &Charmap{
|
||||
ReplacementChar: '\x3f',
|
||||
Map: map[byte]rune{
|
||||
// 0x00-0x03 match
|
||||
0x04: RuneError,
|
||||
0x05: '\t',
|
||||
0x06: RuneError,
|
||||
0x07: '\x7f',
|
||||
0x08: RuneError,
|
||||
0x09: RuneError,
|
||||
0x0a: RuneError,
|
||||
// 0x0b-0x13 match
|
||||
0x14: RuneError,
|
||||
0x15: '\x85', // Not in any ISO code
|
||||
0x16: '\x08',
|
||||
0x17: RuneError,
|
||||
// 0x18-0x19 match
|
||||
0x1a: RuneError,
|
||||
0x1b: RuneError,
|
||||
// 0x1c-0x1f match
|
||||
0x20: RuneError,
|
||||
0x21: RuneError,
|
||||
0x22: RuneError,
|
||||
0x23: RuneError,
|
||||
0x24: RuneError,
|
||||
0x25: '\n',
|
||||
0x26: '\x17',
|
||||
0x27: '\x1b',
|
||||
0x28: RuneError,
|
||||
0x29: RuneError,
|
||||
0x2a: RuneError,
|
||||
0x2b: RuneError,
|
||||
0x2c: RuneError,
|
||||
0x2d: '\x05',
|
||||
0x2e: '\x06',
|
||||
0x2f: '\x07',
|
||||
0x30: RuneError,
|
||||
0x31: RuneError,
|
||||
0x32: '\x16',
|
||||
0x33: RuneError,
|
||||
0x34: RuneError,
|
||||
0x35: RuneError,
|
||||
0x36: RuneError,
|
||||
0x37: '\x04',
|
||||
0x38: RuneError,
|
||||
0x39: RuneError,
|
||||
0x3a: RuneError,
|
||||
0x3b: RuneError,
|
||||
0x3c: '\x14',
|
||||
0x3d: '\x15',
|
||||
0x3e: RuneError,
|
||||
0x3f: '\x1a', // also replacement char
|
||||
0x40: ' ',
|
||||
0x41: '\xa0',
|
||||
0x42: RuneError,
|
||||
0x43: RuneError,
|
||||
0x44: RuneError,
|
||||
0x45: RuneError,
|
||||
0x46: RuneError,
|
||||
0x47: RuneError,
|
||||
0x48: RuneError,
|
||||
0x49: RuneError,
|
||||
0x4a: RuneError,
|
||||
0x4b: '.',
|
||||
0x4c: '<',
|
||||
0x4d: '(',
|
||||
0x4e: '+',
|
||||
0x4f: '|',
|
||||
0x50: '&',
|
||||
0x51: RuneError,
|
||||
0x52: RuneError,
|
||||
0x53: RuneError,
|
||||
0x54: RuneError,
|
||||
0x55: RuneError,
|
||||
0x56: RuneError,
|
||||
0x57: RuneError,
|
||||
0x58: RuneError,
|
||||
0x59: RuneError,
|
||||
0x5a: '!',
|
||||
0x5b: '$',
|
||||
0x5c: '*',
|
||||
0x5d: ')',
|
||||
0x5e: ';',
|
||||
0x5f: '¬',
|
||||
0x60: '-',
|
||||
0x61: '/',
|
||||
0x62: RuneError,
|
||||
0x63: RuneError,
|
||||
0x64: RuneError,
|
||||
0x65: RuneError,
|
||||
0x66: RuneError,
|
||||
0x67: RuneError,
|
||||
0x68: RuneError,
|
||||
0x69: RuneError,
|
||||
0x6a: '¦',
|
||||
0x6b: ',',
|
||||
0x6c: '%',
|
||||
0x6d: '_',
|
||||
0x6e: '>',
|
||||
0x6f: '?',
|
||||
0x70: RuneError,
|
||||
0x71: RuneError,
|
||||
0x72: RuneError,
|
||||
0x73: RuneError,
|
||||
0x74: RuneError,
|
||||
0x75: RuneError,
|
||||
0x76: RuneError,
|
||||
0x77: RuneError,
|
||||
0x78: RuneError,
|
||||
0x79: '`',
|
||||
0x7a: ':',
|
||||
0x7b: '#',
|
||||
0x7c: '@',
|
||||
0x7d: '\'',
|
||||
0x7e: '=',
|
||||
0x7f: '"',
|
||||
0x80: RuneError,
|
||||
0x81: 'a',
|
||||
0x82: 'b',
|
||||
0x83: 'c',
|
||||
0x84: 'd',
|
||||
0x85: 'e',
|
||||
0x86: 'f',
|
||||
0x87: 'g',
|
||||
0x88: 'h',
|
||||
0x89: 'i',
|
||||
0x8a: RuneError,
|
||||
0x8b: RuneError,
|
||||
0x8c: RuneError,
|
||||
0x8d: RuneError,
|
||||
0x8e: RuneError,
|
||||
0x8f: '±',
|
||||
0x90: RuneError,
|
||||
0x91: 'j',
|
||||
0x92: 'k',
|
||||
0x93: 'l',
|
||||
0x94: 'm',
|
||||
0x95: 'n',
|
||||
0x96: 'o',
|
||||
0x97: 'p',
|
||||
0x98: 'q',
|
||||
0x99: 'r',
|
||||
0x9a: RuneError,
|
||||
0x9b: RuneError,
|
||||
0x9c: RuneError,
|
||||
0x9d: RuneError,
|
||||
0x9e: RuneError,
|
||||
0x9f: RuneError,
|
||||
0xa0: RuneError,
|
||||
0xa1: '~',
|
||||
0xa2: 's',
|
||||
0xa3: 't',
|
||||
0xa4: 'u',
|
||||
0xa5: 'v',
|
||||
0xa6: 'w',
|
||||
0xa7: 'x',
|
||||
0xa8: 'y',
|
||||
0xa9: 'z',
|
||||
0xaa: RuneError,
|
||||
0xab: RuneError,
|
||||
0xac: RuneError,
|
||||
0xad: RuneError,
|
||||
0xae: RuneError,
|
||||
0xaf: RuneError,
|
||||
0xb0: '^',
|
||||
0xb1: RuneError,
|
||||
0xb2: RuneError,
|
||||
0xb3: RuneError,
|
||||
0xb4: RuneError,
|
||||
0xb5: RuneError,
|
||||
0xb6: RuneError,
|
||||
0xb7: RuneError,
|
||||
0xb8: RuneError,
|
||||
0xb9: RuneError,
|
||||
0xba: '[',
|
||||
0xbb: ']',
|
||||
0xbc: RuneError,
|
||||
0xbd: RuneError,
|
||||
0xbe: RuneError,
|
||||
0xbf: RuneError,
|
||||
0xc0: '{',
|
||||
0xc1: 'A',
|
||||
0xc2: 'B',
|
||||
0xc3: 'C',
|
||||
0xc4: 'D',
|
||||
0xc5: 'E',
|
||||
0xc6: 'F',
|
||||
0xc7: 'G',
|
||||
0xc8: 'H',
|
||||
0xc9: 'I',
|
||||
0xca: '\xad', // NB: soft hyphen
|
||||
0xcb: RuneError,
|
||||
0xcc: RuneError,
|
||||
0xcd: RuneError,
|
||||
0xce: RuneError,
|
||||
0xcf: RuneError,
|
||||
0xd0: '}',
|
||||
0xd1: 'J',
|
||||
0xd2: 'K',
|
||||
0xd3: 'L',
|
||||
0xd4: 'M',
|
||||
0xd5: 'N',
|
||||
0xd6: 'O',
|
||||
0xd7: 'P',
|
||||
0xd8: 'Q',
|
||||
0xd9: 'R',
|
||||
0xda: RuneError,
|
||||
0xdb: RuneError,
|
||||
0xdc: RuneError,
|
||||
0xdd: RuneError,
|
||||
0xde: RuneError,
|
||||
0xdf: RuneError,
|
||||
0xe0: '\\',
|
||||
0xe1: '\u2007', // Non-breaking space
|
||||
0xe2: 'S',
|
||||
0xe3: 'T',
|
||||
0xe4: 'U',
|
||||
0xe5: 'V',
|
||||
0xe6: 'W',
|
||||
0xe7: 'X',
|
||||
0xe8: 'Y',
|
||||
0xe9: 'Z',
|
||||
0xea: RuneError,
|
||||
0xeb: RuneError,
|
||||
0xec: RuneError,
|
||||
0xed: RuneError,
|
||||
0xee: RuneError,
|
||||
0xef: RuneError,
|
||||
0xf0: '0',
|
||||
0xf1: '1',
|
||||
0xf2: '2',
|
||||
0xf3: '3',
|
||||
0xf4: '4',
|
||||
0xf5: '5',
|
||||
0xf6: '6',
|
||||
0xf7: '7',
|
||||
0xf8: '8',
|
||||
0xf9: '9',
|
||||
0xfa: RuneError,
|
||||
0xfb: RuneError,
|
||||
0xfc: RuneError,
|
||||
0xfd: RuneError,
|
||||
0xfe: RuneError,
|
||||
0xff: RuneError,
|
||||
}}
|
||||
cm.Init()
|
||||
EBCDIC = cm
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
// Copyright 2015 Garrett D'Amore
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"golang.org/x/text/encoding"
|
||||
)
|
||||
|
||||
// ISO8859_1 represents the 8-bit ISO8859-1 scheme. It decodes directly to
|
||||
// UTF-8 without change, as all ISO8859-1 values are legal UTF-8.
|
||||
// Unicode values less than 256 (i.e. 8 bits) map 1:1 with 8859-1.
|
||||
// It encodes runes outside of that to 0x1A, the ASCII substitution character.
|
||||
var ISO8859_1 encoding.Encoding
|
||||
|
||||
func init() {
|
||||
cm := &Charmap{}
|
||||
cm.Init()
|
||||
|
||||
// 8859-1 is the 8-bit identity map for Unicode.
|
||||
ISO8859_1 = cm
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
// Copyright 2015 Garrett D'Amore
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"golang.org/x/text/encoding"
|
||||
)
|
||||
|
||||
type validUtf8 struct{}
|
||||
|
||||
// UTF8 is an encoding for UTF-8. All it does is verify that the UTF-8
|
||||
// in is valid. The main reason for its existence is that it will detect
|
||||
// and report ErrSrcShort or ErrDstShort, whereas the Nop encoding just
|
||||
// passes every byte, blithely.
|
||||
var UTF8 encoding.Encoding = validUtf8{}
|
||||
|
||||
func (validUtf8) NewDecoder() *encoding.Decoder {
|
||||
return &encoding.Decoder{Transformer: encoding.UTF8Validator}
|
||||
}
|
||||
|
||||
func (validUtf8) NewEncoder() *encoding.Encoder {
|
||||
return &encoding.Encoder{Transformer: encoding.UTF8Validator}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
version: 1.0.{build}
|
||||
clone_folder: c:\gopath\src\github.com\gdamore\tcell
|
||||
environment:
|
||||
GOPATH: c:\gopath
|
||||
build_script:
|
||||
- go version
|
||||
- go env
|
||||
- SET PATH=%LOCALAPPDATA%\atom\bin;%GOPATH%\bin;%PATH%
|
||||
- go get -t ./...
|
||||
- go build
|
||||
- go install ./...
|
||||
test_script:
|
||||
- go test ./...
|
@ -0,0 +1 @@
|
||||
coverage.txt
|
@ -0,0 +1,18 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.15.x
|
||||
- master
|
||||
|
||||
arch:
|
||||
- amd64
|
||||
- ppc64le
|
||||
|
||||
before_install:
|
||||
- go get -t -v ./...
|
||||
|
||||
script:
|
||||
- go test -race -coverprofile=coverage.txt -covermode=atomic
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
@ -0,0 +1,4 @@
|
||||
Garrett D'Amore <garrett@damore.org>
|
||||
Zachary Yedidia <zyedidia@gmail.com>
|
||||
Junegunn Choi <junegunn.c@gmail.com>
|
||||
Staysail Systems, Inc. <info@staysail.tech>
|
@ -0,0 +1,82 @@
|
||||
## Breaking Changes in _Tcell_ v2
|
||||
|
||||
A number of changes were made to _Tcell_ for version two, and some of these are breaking.
|
||||
|
||||
### Import Path
|
||||
|
||||
The import path for tcell has changed to `github.com/gdamore/tcell/v2` to reflect a new major version.
|
||||
|
||||
### Style Is Not Numeric
|
||||
|
||||
The type `Style` has changed to a structure, to allow us to add additional data such as flags for color setting,
|
||||
more attribute bits, and so forth.
|
||||
Applications that relied on this being a number will need to be updated to use the accessor methods.
|
||||
|
||||
### Mouse Event Changes
|
||||
|
||||
The middle mouse button was reported as button 2 on Linux, but as button 3 on Windows,
|
||||
and the right mouse button was reported the reverse way.
|
||||
_Tcell_ now always reports the right mouse button as button 2, and the middle button as button 3.
|
||||
To help make this clearer, new symbols `ButtonPrimary`, `ButtonSecondary`, and
|
||||
`ButtonMiddle` are provided.
|
||||
(Note that which button is right vs. left may be impacted by user preferences.
|
||||
Usually the left button will be considered the Primary, and the right will be the Secondary.)
|
||||
Applications may need to adjust their handling of mouse buttons 2 and 3 accordingly.
|
||||
|
||||
### Terminals Removed
|
||||
|
||||
A number of terminals have been removed.
|
||||
These are mostly ancient definitions unlikely to be used by anyone, such as `adm3a`.
|
||||
|
||||
### High Number Function Keys
|
||||
|
||||
Historically terminfo reported function keys with modifiers set as a different
|
||||
function key altogether. For example, Shift-F1 was reported as F13 on XTerm.
|
||||
_Tcell_ now prefers to report these using the base key (such as F1) with modifiers added.
|
||||
This works on XTerm and VTE based emulators, but some emulators may not support this.
|
||||
The new behavior more closely aligns with behavior on Windows platforms.
|
||||
|
||||
## New Features in _Tcell_ v2
|
||||
|
||||
These features are not breaking, but are introduced in version 2.
|
||||
|
||||
### Improved Modifier Support
|
||||
|
||||
For terminals that appear to behave like the venerable XTerm, _tcell_
|
||||
automatically adds modifier reporting for ALT, CTRL, SHIFT, and META keys
|
||||
when the terminal reports them.
|
||||
|
||||
### Better Support for Palettes (Themes)
|
||||
|
||||
When using a color by its name or palette entry, _Tcell_ now tries to
|
||||
use that palette entry as is; this should avoid some inconsistency and respect
|
||||
terminal themes correctly.
|
||||
|
||||
When true fidelity to RGB values is needed, the new `TrueColor()` API can be used
|
||||
to create a direct color, which bypasses the palette altogether.
|
||||
|
||||
### Automatic TrueColor Detection
|
||||
|
||||
For some terminals, if the `Tc` or `RGB` properties are present in terminfo,
|
||||
_Tcell_ will automatically assume the terminal supports 24-bit color.
|
||||
|
||||
### ColorReset
|
||||
|
||||
A new color value, `ColorReset` can be used on the foreground or background
|
||||
to reset the color the default used by the terminal.
|
||||
|
||||
### tmux Support
|
||||
|
||||
_Tcell_ now has improved support for tmux, when the `$TERM` variable is set to "tmux".
|
||||
|
||||
### Strikethrough Support
|
||||
|
||||
_Tcell_ has support for strikethrough when the terminal supports it, using the new `StrikeThrough()` API.
|
||||
|
||||
### Bracketed Paste Support
|
||||
|
||||
_Tcell_ provides the long requested capability to discriminate paste event by using the
|
||||
bracketed-paste capability present in some terminals. This is automatically available on
|
||||
terminals that support XTerm style mouse handling, but applications must opt-in to this
|
||||
by using the new `EnablePaste()` function. A new `EventPaste` type of event will be
|
||||
delivered when starting and finishing a paste operation.
|
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@ -0,0 +1,272 @@
|
||||
|
||||
# ![Tcell](logos/tcell.png)
|
||||
|
||||
_Tcell_ is a _Go_ package that provides a cell based view for text terminals, like _XTerm_.
|
||||
It was inspired by _termbox_, but includes many additional improvements.
|
||||
|
||||
[![Linux Status](https://img.shields.io/travis/gdamore/tcell.svg?label=linux)](https://travis-ci.org/gdamore/tcell)
|
||||
[![Windows Status](https://img.shields.io/appveyor/ci/gdamore/tcell.svg?label=windows)](https://ci.appveyor.com/project/gdamore/tcell)
|
||||
[![Apache License](https://img.shields.io/badge/license-APACHE2-blue.svg)](https://github.com/gdamore/tcell/blob/master/LICENSE)
|
||||
[![Documentation](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/gdamore/tcell/v2)
|
||||
[![Report Card](https://goreportcard.com/badge/gdamore/tcell)](http://goreportcard.com/report/gdamore/tcell/v2)
|
||||
[![Discord](https://img.shields.io/discord/639503822733180969?label=discord)](https://discord.gg/urTTxDN)
|
||||
[![Coverage](https://codecov.io/gh/gdamore/tcell/branch/master/graph/badge.svg)](https://codecov.io/gh/gdamore/tcell)
|
||||
|
||||
|
||||
NOTE: This is version 2 of _Tcell_. There are breaking changes relative to version 1.
|
||||
Version 1.x remains available using the import `github.com/gdamore/tcell`.
|
||||
|
||||
## Tutorial
|
||||
|
||||
A brief, and still somewhat rough, [tutorial](TUTORIAL.md) is available.
|
||||
## Examples
|
||||
|
||||
* [proxima5](https://github.com/gdamore/proxima5) - space shooter ([video](https://youtu.be/jNxKTCmY_bQ))
|
||||
* [govisor](https://github.com/gdamore/govisor) - service management UI ([screenshot](http://2.bp.blogspot.com/--OsvnfzSNow/Vf7aqMw3zXI/AAAAAAAAARo/uOMtOvw4Sbg/s1600/Screen%2BShot%2B2015-09-20%2Bat%2B9.08.41%2BAM.png))
|
||||
* mouse demo - included mouse test ([screenshot](http://2.bp.blogspot.com/-fWvW5opT0es/VhIdItdKqJI/AAAAAAAAATE/7Ojc0L1SpB0/s1600/Screen%2BShot%2B2015-10-04%2Bat%2B11.47.13%2BPM.png))
|
||||
* [gomatrix](https://github.com/gdamore/gomatrix) - converted from Termbox
|
||||
* [micro](https://github.com/zyedidia/micro/) - lightweight text editor with syntax-highlighting and themes
|
||||
* [godu](https://github.com/viktomas/godu) - utility to discover large files/folders
|
||||
* [tview](https://github.com/rivo/tview/) - rich interactive widgets
|
||||
* [cview](https://code.rocketnine.space/tslocum/cview) - user interface toolkit (fork of _tview_)
|
||||
* [awsome gocui](https://github.com/awesome-gocui/gocui) - Go Console User Interface
|
||||
* [gomandelbrot](https://github.com/rgm3/gomandelbrot) - Mandelbrot!
|
||||
* [WTF](https://github.com/senorprogrammer/wtf) - personal information dashboard
|
||||
* [browsh](https://github.com/browsh-org/browsh) - modern web browser ([video](https://www.youtube.com/watch?v=HZq86XfBoRo))
|
||||
* [go-life](https://github.com/sachaos/go-life) - Conway's Game of Life
|
||||
* [gowid](https://github.com/gcla/gowid) - compositional widgets for terminal UIs, inspired by _urwid_
|
||||
* [termshark](https://termshark.io) - interface for _tshark_, inspired by Wireshark, built on _gowid_
|
||||
* [go-tetris](https://github.com/MichaelS11/go-tetris) - Go Tetris with AI option
|
||||
* [fzf](https://github.com/junegunn/fzf) - command-line fuzzy finder
|
||||
* [ascii-fluid](https://github.com/esimov/ascii-fluid) - fluid simulation controlled by webcam
|
||||
* [cbind](https://code.rocketnine.space/tslocum/cbind) - key event encoding, decoding and handling
|
||||
* [tpong](https://github.com/spinzed/tpong) - old-school Pong
|
||||
* [aerc](https://git.sr.ht/~sircmpwn/aerc) - email client
|
||||
* [tblogs](https://github.com/ezeoleaf/tblogs) - development blogs reader
|
||||
* [spinc](https://github.com/lallassu/spinc) - _irssi_ inspired chat application for Cisco Spark/WebEx
|
||||
* [gorss](https://github.com/lallassu/gorss) - RSS/Atom feed reader
|
||||
* [memoryalike](https://github.com/Bios-Marcel/memoryalike) - memorization game
|
||||
* [lf](https://github.com/gokcehan/lf) - file manager
|
||||
* [gokeybr](https://github.com/bunyk/gokeybr) - deliberately practice your typing
|
||||
* [gonano](https://github.com/jbaramidze/gonano) - editor, mimics _nano_
|
||||
* [uchess](https://github.com/tmountain/uchess) - UCI chess client
|
||||
* [min](https://github.com/a-h/min) - Gemini browser
|
||||
* [ov](https://github.com/noborus/ov) - file pager
|
||||
* [tmux-wormhole](https://github.com/gcla/tmux-wormhole) - _tmux_ plugin to transfer files
|
||||
* [gruid-tcell](https://github.com/anaseto/gruid-tcell) - driver for the grid based UI and game framework
|
||||
* [aretext](https://github.com/aretext/aretext) - minimalist text editor with _vim_ key bindings
|
||||
|
||||
## Pure Go Terminfo Database
|
||||
|
||||
_Tcell_ includes a full parser and expander for terminfo capability strings,
|
||||
so that it can avoid hard coding escape strings for formatting. It also favors
|
||||
portability, and includes support for all POSIX systems.
|
||||
|
||||
The database is also flexible & extensible, and can be modified by either running
|
||||
a program to build the entire database, or an entry for just a single terminal.
|
||||
|
||||
## More Portable
|
||||
|
||||
_Tcell_ is portable to a wide variety of systems, and is pure Go, without
|
||||
any need for CGO.
|
||||
_Tcell_ is believed to work with mainstream systems officially supported by golang.
|
||||
|
||||
## No Async IO
|
||||
|
||||
_Tcell_ is able to operate without requiring `SIGIO` signals (unlike _termbox_),
|
||||
or asynchronous I/O, and can instead use standard Go file objects and Go routines.
|
||||
This means it should be safe, especially for
|
||||
use with programs that use exec, or otherwise need to manipulate the tty streams.
|
||||
This model is also much closer to idiomatic Go, leading to fewer surprises.
|
||||
|
||||
## Rich Unicode & non-Unicode support
|
||||
|
||||
_Tcell_ includes enhanced support for Unicode, including wide characters and
|
||||
combining characters, provided your terminal can support them.
|
||||
Note that
|
||||
Windows terminals generally don't support the full Unicode repertoire.
|
||||
|
||||
It will also convert to and from Unicode locales, so that the program
|
||||
can work with UTF-8 internally, and get reasonable output in other locales.
|
||||
_Tcell_ tries hard to convert to native characters on both input and output.
|
||||
On output _Tcell_ even makes use of the alternate character set to facilitate
|
||||
drawing certain characters.
|
||||
|
||||
## More Function Keys
|
||||
|
||||
_Tcell_ also has richer support for a larger number of special keys that some
|
||||
terminals can send.
|
||||
|
||||
## Better Color Handling
|
||||
|
||||
_Tcell_ will respect your terminal's color space as specified within your terminfo entries.
|
||||
For example attempts to emit color sequences on VT100 terminals
|
||||
won't result in unintended consequences.
|
||||
|
||||
In legacy Windows mode, _Tcell_ supports 16 colors, bold, dim, and reverse,
|
||||
instead of just termbox's 8 colors with reverse. (Note that there is some
|
||||
conflation with bold/dim and colors.)
|
||||
Modern Windows 10 can benefit from much richer colors however.
|
||||
|
||||
_Tcell_ maps 16 colors down to 8, for terminals that need it.
|
||||
(The upper 8 colors are just brighter versions of the lower 8.)
|
||||
|
||||
## Better Mouse Support
|
||||
|
||||
_Tcell_ supports enhanced mouse tracking mode, so your application can receive
|
||||
regular mouse motion events, and wheel events, if your terminal supports it.
|
||||
|
||||
(Note: The Windows 10 Terminal application suffers from a flaw in this regard,
|
||||
and does not support mouse interaction. The stock Windows 10 console host
|
||||
fired up with cmd.exe or PowerShell works fine however.)
|
||||
|
||||
## _Termbox_ Compatibility
|
||||
|
||||
A compatibility layer for _termbox_ is provided in the `compat` directory.
|
||||
To use it, try importing `github.com/gdamore/tcell/termbox` instead.
|
||||
Most _termbox-go_ programs will probably work without further modification.
|
||||
|
||||
## Working With Unicode
|
||||
|
||||
Internally _Tcell_ uses UTF-8, just like Go.
|
||||
However, _Tcell_ understands how to
|
||||
convert to and from other character sets, using the capabilities of
|
||||
the `golang.org/x/text/encoding packages`.
|
||||
Your application must supply
|
||||
them, as the full set of the most common ones bloats the program by about 2 MB.
|
||||
If you're lazy, and want them all anyway, see the `encoding` sub-directory.
|
||||
|
||||
## Wide & Combining Characters
|
||||
|
||||
The `SetContent()` API takes a primary rune, and an optional list of combining runes.
|
||||
If any of the runes is a wide (East Asian) rune occupying two cells,
|
||||
then the library will skip output from the following cell. Care must be
|
||||
taken in the application to avoid explicitly attempting to set content in the
|
||||
next cell, otherwise the results are undefined. (Normally the wide character
|
||||
is displayed, and the other character is not; do not depend on that behavior.)
|
||||
|
||||
Older terminal applications (especially on systems like Windows 8) lack support
|
||||
for advanced Unicode, and thus may not fare well.
|
||||
|
||||
## Colors
|
||||
|
||||
_Tcell_ assumes the ANSI/XTerm color model, including the 256 color map that
|
||||
XTerm uses when it supports 256 colors. The terminfo guidance will be
|
||||
honored, with respect to the number of colors supported. Also, only
|
||||
terminals which expose ANSI style `setaf` and `setab` will support color;
|
||||
if you have a color terminal that only has `setf` and `setb`, please submit
|
||||
a ticket.
|
||||
|
||||
## 24-bit Color
|
||||
|
||||
_Tcell_ _supports 24-bit color!_ (That is, if your terminal can support it.)
|
||||
|
||||
NOTE: Technically the approach of using 24-bit RGB values for color is more
|
||||
accurately described as "direct color", but most people use the term "true color".
|
||||
We follow the (inaccurate) common convention.
|
||||
|
||||
There are a few ways you can enable (or disable) true color.
|
||||
|
||||
* For many terminals, we can detect it automatically if your terminal
|
||||
includes the `RGB` or `Tc` capabilities (or rather it did when the database
|
||||
was updated.)
|
||||
|
||||
* You can force this one by setting the `COLORTERM` environment variable to
|
||||
`24-bit`, `truecolor` or `24bit`. This is the same method used
|
||||
by most other terminal applications that support 24-bit color.
|
||||
|
||||
* If you set your `TERM` environment variable to a value with the suffix `-truecolor`
|
||||
then 24-bit color compatible with XTerm and ECMA-48 will be assumed.
|
||||
(This feature is deprecated.
|
||||
It is recommended to use one of other methods listed above.)
|
||||
|
||||
* You can disable 24-bit color by setting `TCELL_TRUECOLOR=disable` in your
|
||||
environment.
|
||||
|
||||
When using TrueColor, programs will display the colors that the programmer
|
||||
intended, overriding any "`themes`" you may have set in your terminal
|
||||
emulator. (For some cases, accurate color fidelity is more important
|
||||
than respecting themes. For other cases, such as typical text apps that
|
||||
only use a few colors, its more desirable to respect the themes that
|
||||
the user has established.)
|
||||
|
||||
## Performance
|
||||
|
||||
Reasonable attempts have been made to minimize sending data to terminals,
|
||||
avoiding repeated sequences or drawing the same cell on refresh updates.
|
||||
|
||||
## Terminfo
|
||||
|
||||
(Not relevant for Windows users.)
|
||||
|
||||
The Terminfo implementation operates with a built-in database.
|
||||
This should satisfy most users. However, it can also (on systems
|
||||
with ncurses installed), dynamically parse the output from `infocmp`
|
||||
for terminals it does not already know about.
|
||||
|
||||
See the `terminfo/` directory for more information about generating
|
||||
new entries for the built-in database.
|
||||
|
||||
_Tcell_ requires that the terminal support the `cup` mode of cursor addressing.
|
||||
Ancient terminals without the ability to position the cursor directly
|
||||
are not supported.
|
||||
This is unlikely to be a problem; such terminals have not been mass-produced
|
||||
since the early 1970s.
|
||||
|
||||
## Mouse Support
|
||||
|
||||
Mouse support is detected via the `kmous` terminfo variable, however,
|
||||
enablement/disablement and decoding mouse events is done using hard coded
|
||||
sequences based on the XTerm X11 model. All popular
|
||||
terminals with mouse tracking support this model. (Full terminfo support
|
||||
is not possible as terminfo sequences are not defined.)
|
||||
|
||||
On Windows, the mouse works normally.
|
||||
|
||||
Mouse wheel buttons on various terminals are known to work, but the support
|
||||
in terminal emulators, as well as support for various buttons and
|
||||
live mouse tracking, varies widely.
|
||||
Modern _xterm_, macOS _Terminal_, and _iTerm_ all work well.
|
||||
|
||||
## Bracketed Paste
|
||||
|
||||
Terminals that appear to support the XTerm mouse model also can support
|
||||
bracketed paste, for applications that opt-in. See `EnablePaste()` for details.
|
||||
|
||||
## Testability
|
||||
|
||||
There is a `SimulationScreen`, that can be used to simulate a real screen
|
||||
for automated testing. The supplied tests do this. The simulation contains
|
||||
event delivery, screen resizing support, and capabilities to inject events
|
||||
and examine "`physical`" screen contents.
|
||||
|
||||
## Platforms
|
||||
|
||||
### POSIX (Linux, FreeBSD, macOS, Solaris, etc.)
|
||||
|
||||
Everything works using pure Go on mainstream platforms. Some more esoteric
|
||||
platforms (e.g., AIX) may need to be added. Pull requests are welcome!
|
||||
|
||||
### Windows
|
||||
|
||||
Windows console mode applications are supported.
|
||||
|
||||
Modern console applications like ConEmu and the Windows 10 terminal,
|
||||
support all the good features (resize, mouse tracking, etc.)
|
||||
|
||||
### Plan9, WASM, and others
|
||||
|
||||
These platforms won't work, but compilation stubs are supplied
|
||||
for folks that want to include parts of this in software for those
|
||||
platforms. The Simulation screen works, but as _Tcell_ doesn't know how to
|
||||
allocate a real screen object on those platforms, `NewScreen()` will fail.
|
||||
|
||||
If anyone has wisdom about how to improve support for these,
|
||||
please let me know. PRs are especially welcome.
|
||||
|
||||
### Commercial Support
|
||||
|
||||
_Tcell_ is absolutely free, but if you want to obtain commercial, professional support, there are options.
|
||||
|
||||
* [TideLift](https://tidelift.com/) subscriptions include support for _Tcell_, as well as many other open source packages.
|
||||
* [Staysail Systems Inc.](mailto:info@staysail.tech) offers direct support, and custom development around _Tcell_ on an hourly basis.
|
@ -0,0 +1,293 @@
|
||||
# _Tcell_ Tutorial
|
||||
|
||||
_Tcell_ provides a low-level, portable API for building terminal-based programs.
|
||||
A [terminal emulator](https://en.wikipedia.org/wiki/Terminal_emulator)
|
||||
(or a real terminal such as a DEC VT-220) is used to interact with such a program.
|
||||
|
||||
_Tcell_'s interface is fairly low-level.
|
||||
While it provides a reasonably portable way of dealing with all the usual terminal
|
||||
features, it may be easier to utilize a higher level framework.
|
||||
A number of such frameworks are listed on the _Tcell_ main [README](README.md).
|
||||
|
||||
This tutorial provides the details of _Tcell_, and is appropriate for developers
|
||||
wishing to create their own application frameworks or needing more direct access
|
||||
to the terminal capabilities.
|
||||
|
||||
## Resize events
|
||||
|
||||
Applications receive an event of type `EventResize` when they are first initialized and each time the terminal is resized.
|
||||
The new size is available as `Size`.
|
||||
|
||||
```golang
|
||||
switch ev := ev.(type) {
|
||||
case *tcell.EventResize:
|
||||
w, h := ev.Size()
|
||||
logMessage(fmt.Sprintf("Resized to %dx%d", w, h))
|
||||
}
|
||||
```
|
||||
|
||||
## Key events
|
||||
|
||||
When a key is pressed, applications receive an event of type `EventKey`.
|
||||
This event describes the modifier keys pressed (if any) and the pressed key or rune.
|
||||
|
||||
When a rune key is pressed, an event with its `Key` set to `KeyRune` is dispatched.
|
||||
|
||||
When a non-rune key is pressed, it is available as the `Key` of the event.
|
||||
|
||||
```golang
|
||||
switch ev := ev.(type) {
|
||||
case *tcell.EventKey:
|
||||
mod, key, ch := ev.Mod(), ev.Key(), ev.Rune()
|
||||
logMessage(fmt.Sprintf("EventKey Modifiers: %d Key: %d Rune: %d", mod, key, ch))
|
||||
}
|
||||
```
|
||||
|
||||
### Key event restrictions
|
||||
|
||||
Terminal-based programs have less visibility into keyboard activity than graphical applications.
|
||||
|
||||
When a key is pressed and held, additional key press events are sent by the terminal emulator.
|
||||
The rate of these repeated events depends on the emulator's configuration.
|
||||
Key release events are not available.
|
||||
|
||||
It is not possible to distinguish runes typed while holding shift and runes typed using caps lock.
|
||||
Capital letters are reported without the Shift modifier.
|
||||
|
||||
## Mouse events
|
||||
|
||||
Applications receive an event of type `EventMouse` when the mouse moves, or a mouse button is pressed or released.
|
||||
Mouse events are only delivered if
|
||||
`EnableMouse` has been called.
|
||||
|
||||
The mouse buttons being pressed (if any) are available as `Buttons`, and the position of the mouse is available as `Position`.
|
||||
|
||||
```golang
|
||||
switch ev := ev.(type) {
|
||||
case *tcell.EventMouse:
|
||||
mod := ev.Modifiers()
|
||||
btns := ev.Buttons()
|
||||
x, y := ev.Position()
|
||||
logMessage(fmt.Sprintf("EventMouse Modifiers: %d Buttons: %d Position: %d,%d", mod, btns, x, y))
|
||||
}
|
||||
```
|
||||
|
||||
### Mouse buttons
|
||||
|
||||
Identifier | Alias | Description
|
||||
-----------|-----------------|-----------
|
||||
Button1 | ButtonPrimary | Left button
|
||||
Button2 | ButtonSecondary | Right button
|
||||
Button3 | ButtonMiddle | Middle button
|
||||
Button4 | | Side button (thumb/next)
|
||||
Button5 | | Side button (thumb/prev)
|
||||
|
||||
## Usage
|
||||
|
||||
To create a tcell application, first initialize a screen to hold it.
|
||||
|
||||
```golang
|
||||
s, err := tcell.NewScreen()
|
||||
if err != nil {
|
||||
log.Fatalf("%+v", err)
|
||||
}
|
||||
if err := s.Init(); err != nil {
|
||||
log.Fatalf("%+v", err)
|
||||
}
|
||||
|
||||
// Set default text style
|
||||
defStyle := tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.ColorReset)
|
||||
s.SetStyle(defStyle)
|
||||
|
||||
// Clear screen
|
||||
s.Clear()
|
||||
```
|
||||
|
||||
Text may be drawn on the screen using `SetContent`.
|
||||
|
||||
```golang
|
||||
s.SetContent(0, 0, 'H', nil, defStyle)
|
||||
s.SetContent(1, 0, 'i', nil, defStyle)
|
||||
s.SetContent(2, 0, '!', nil, defStyle)
|
||||
```
|
||||
|
||||
To draw text more easily, define a render function.
|
||||
|
||||
```golang
|
||||
func drawText(s tcell.Screen, x1, y1, x2, y2 int, style tcell.Style, text string) {
|
||||
row := y1
|
||||
col := x1
|
||||
for _, r := range []rune(text) {
|
||||
s.SetContent(col, row, r, nil, style)
|
||||
col++
|
||||
if col >= x2 {
|
||||
row++
|
||||
col = x1
|
||||
}
|
||||
if row > y2 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Lastly, define an event loop to handle user input and update application state.
|
||||
|
||||
```golang
|
||||
quit := func() {
|
||||
s.Fini()
|
||||
os.Exit(0)
|
||||
}
|
||||
for {
|
||||
// Update screen
|
||||
s.Show()
|
||||
|
||||
// Poll event
|
||||
ev := s.PollEvent()
|
||||
|
||||
// Process event
|
||||
switch ev := ev.(type) {
|
||||
case *tcell.EventResize:
|
||||
s.Sync()
|
||||
case *tcell.EventKey:
|
||||
if ev.Key() == tcell.KeyEscape || ev.Key() == tcell.KeyCtrlC {
|
||||
quit()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Demo application
|
||||
|
||||
The following demonstrates how to initialize a screen, draw text/graphics and handle user input.
|
||||
|
||||
```golang
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
)
|
||||
|
||||
func drawText(s tcell.Screen, x1, y1, x2, y2 int, style tcell.Style, text string) {
|
||||
row := y1
|
||||
col := x1
|
||||
for _, r := range []rune(text) {
|
||||
s.SetContent(col, row, r, nil, style)
|
||||
col++
|
||||
if col >= x2 {
|
||||
row++
|
||||
col = x1
|
||||
}
|
||||
if row > y2 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func drawBox(s tcell.Screen, x1, y1, x2, y2 int, style tcell.Style, text string) {
|
||||
if y2 < y1 {
|
||||
y1, y2 = y2, y1
|
||||
}
|
||||
if x2 < x1 {
|
||||
x1, x2 = x2, x1
|
||||
}
|
||||
|
||||
// Fill background
|
||||
for row := y1; row <= y2; row++ {
|
||||
for col := x1; col <= x2; col++ {
|
||||
s.SetContent(col, row, ' ', nil, style)
|
||||
}
|
||||
}
|
||||
|
||||
// Draw borders
|
||||
for col := x1; col <= x2; col++ {
|
||||
s.SetContent(col, y1, tcell.RuneHLine, nil, style)
|
||||
s.SetContent(col, y2, tcell.RuneHLine, nil, style)
|
||||
}
|
||||
for row := y1 + 1; row < y2; row++ {
|
||||
s.SetContent(x1, row, tcell.RuneVLine, nil, style)
|
||||
s.SetContent(x2, row, tcell.RuneVLine, nil, style)
|
||||
}
|
||||
|
||||
// Only draw corners if necessary
|
||||
if y1 != y2 && x1 != x2 {
|
||||
s.SetContent(x1, y1, tcell.RuneULCorner, nil, style)
|
||||
s.SetContent(x2, y1, tcell.RuneURCorner, nil, style)
|
||||
s.SetContent(x1, y2, tcell.RuneLLCorner, nil, style)
|
||||
s.SetContent(x2, y2, tcell.RuneLRCorner, nil, style)
|
||||
}
|
||||
|
||||
drawText(s, x1+1, y1+1, x2-1, y2-1, style, text)
|
||||
}
|
||||
|
||||
func main() {
|
||||
defStyle := tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.ColorReset)
|
||||
boxStyle := tcell.StyleDefault.Foreground(tcell.ColorWhite).Background(tcell.ColorPurple)
|
||||
|
||||
// Initialize screen
|
||||
s, err := tcell.NewScreen()
|
||||
if err != nil {
|
||||
log.Fatalf("%+v", err)
|
||||
}
|
||||
if err := s.Init(); err != nil {
|
||||
log.Fatalf("%+v", err)
|
||||
}
|
||||
s.SetStyle(defStyle)
|
||||
s.EnableMouse()
|
||||
s.EnablePaste()
|
||||
s.Clear()
|
||||
|
||||
// Draw initial boxes
|
||||
drawBox(s, 1, 1, 42, 7, boxStyle, "Click and drag to draw a box")
|
||||
drawBox(s, 5, 9, 32, 14, boxStyle, "Press C to reset")
|
||||
|
||||
// Event loop
|
||||
ox, oy := -1, -1
|
||||
quit := func() {
|
||||
s.Fini()
|
||||
os.Exit(0)
|
||||
}
|
||||
for {
|
||||
// Update screen
|
||||
s.Show()
|
||||
|
||||
// Poll event
|
||||
ev := s.PollEvent()
|
||||
|
||||
// Process event
|
||||
switch ev := ev.(type) {
|
||||
case *tcell.EventResize:
|
||||
s.Sync()
|
||||
case *tcell.EventKey:
|
||||
if ev.Key() == tcell.KeyEscape || ev.Key() == tcell.KeyCtrlC {
|
||||
quit()
|
||||
} else if ev.Key() == tcell.KeyCtrlL {
|
||||
s.Sync()
|
||||
} else if ev.Rune() == 'C' || ev.Rune() == 'c' {
|
||||
s.Clear()
|
||||
}
|
||||
case *tcell.EventMouse:
|
||||
x, y := ev.Position()
|
||||
button := ev.Buttons()
|
||||
// Only process button events, not wheel events
|
||||
button &= tcell.ButtonMask(0xff)
|
||||
|
||||
if button != tcell.ButtonNone && ox < 0 {
|
||||
ox, oy = x, y
|
||||
}
|
||||
switch ev.Buttons() {
|
||||
case tcell.ButtonNone:
|
||||
if ox >= 0 {
|
||||
label := fmt.Sprintf("%d,%d to %d,%d", ox, oy, x, y)
|
||||
drawBox(s, ox, oy, x, y, boxStyle, label)
|
||||
ox, oy = -1, -1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
@ -0,0 +1,33 @@
|
||||
// Copyright 2020 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcell
|
||||
|
||||
// AttrMask represents a mask of text attributes, apart from color.
|
||||
// Note that support for attributes may vary widely across terminals.
|
||||
type AttrMask int
|
||||
|
||||
// Attributes are not colors, but affect the display of text. They can
|
||||
// be combined.
|
||||
const (
|
||||
AttrBold AttrMask = 1 << iota
|
||||
AttrBlink
|
||||
AttrReverse
|
||||
AttrUnderline
|
||||
AttrDim
|
||||
AttrItalic
|
||||
AttrStrikeThrough
|
||||
AttrInvalid // Mark the style or attributes invalid
|
||||
AttrNone AttrMask = 0 // Just normal text.
|
||||
)
|
@ -0,0 +1,177 @@
|
||||
// Copyright 2019 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcell
|
||||
|
||||
import (
|
||||
runewidth "github.com/mattn/go-runewidth"
|
||||
)
|
||||
|
||||
type cell struct {
|
||||
currMain rune
|
||||
currComb []rune
|
||||
currStyle Style
|
||||
lastMain rune
|
||||
lastStyle Style
|
||||
lastComb []rune
|
||||
width int
|
||||
}
|
||||
|
||||
// CellBuffer represents a two dimensional array of character cells.
|
||||
// This is primarily intended for use by Screen implementors; it
|
||||
// contains much of the common code they need. To create one, just
|
||||
// declare a variable of its type; no explicit initialization is necessary.
|
||||
//
|
||||
// CellBuffer is not thread safe.
|
||||
type CellBuffer struct {
|
||||
w int
|
||||
h int
|
||||
cells []cell
|
||||
}
|
||||
|
||||
// SetContent sets the contents (primary rune, combining runes,
|
||||
// and style) for a cell at a given location.
|
||||
func (cb *CellBuffer) SetContent(x int, y int,
|
||||
mainc rune, combc []rune, style Style) {
|
||||
|
||||
if x >= 0 && y >= 0 && x < cb.w && y < cb.h {
|
||||
c := &cb.cells[(y*cb.w)+x]
|
||||
|
||||
c.currComb = append([]rune{}, combc...)
|
||||
|
||||
if c.currMain != mainc {
|
||||
c.width = runewidth.RuneWidth(mainc)
|
||||
}
|
||||
c.currMain = mainc
|
||||
c.currStyle = style
|
||||
}
|
||||
}
|
||||
|
||||
// GetContent returns the contents of a character cell, including the
|
||||
// primary rune, any combining character runes (which will usually be
|
||||
// nil), the style, and the display width in cells. (The width can be
|
||||
// either 1, normally, or 2 for East Asian full-width characters.)
|
||||
func (cb *CellBuffer) GetContent(x, y int) (rune, []rune, Style, int) {
|
||||
var mainc rune
|
||||
var combc []rune
|
||||
var style Style
|
||||
var width int
|
||||
if x >= 0 && y >= 0 && x < cb.w && y < cb.h {
|
||||
c := &cb.cells[(y*cb.w)+x]
|
||||
mainc, combc, style = c.currMain, c.currComb, c.currStyle
|
||||
if width = c.width; width == 0 || mainc < ' ' {
|
||||
width = 1
|
||||
mainc = ' '
|
||||
}
|
||||
}
|
||||
return mainc, combc, style, width
|
||||
}
|
||||
|
||||
// Size returns the (width, height) in cells of the buffer.
|
||||
func (cb *CellBuffer) Size() (int, int) {
|
||||
return cb.w, cb.h
|
||||
}
|
||||
|
||||
// Invalidate marks all characters within the buffer as dirty.
|
||||
func (cb *CellBuffer) Invalidate() {
|
||||
for i := range cb.cells {
|
||||
cb.cells[i].lastMain = rune(0)
|
||||
}
|
||||
}
|
||||
|
||||
// Dirty checks if a character at the given location needs an
|
||||
// to be refreshed on the physical display. This returns true
|
||||
// if the cell content is different since the last time it was
|
||||
// marked clean.
|
||||
func (cb *CellBuffer) Dirty(x, y int) bool {
|
||||
if x >= 0 && y >= 0 && x < cb.w && y < cb.h {
|
||||
c := &cb.cells[(y*cb.w)+x]
|
||||
if c.lastMain == rune(0) {
|
||||
return true
|
||||
}
|
||||
if c.lastMain != c.currMain {
|
||||
return true
|
||||
}
|
||||
if c.lastStyle != c.currStyle {
|
||||
return true
|
||||
}
|
||||
if len(c.lastComb) != len(c.currComb) {
|
||||
return true
|
||||
}
|
||||
for i := range c.lastComb {
|
||||
if c.lastComb[i] != c.currComb[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// SetDirty is normally used to indicate that a cell has
|
||||
// been displayed (in which case dirty is false), or to manually
|
||||
// force a cell to be marked dirty.
|
||||
func (cb *CellBuffer) SetDirty(x, y int, dirty bool) {
|
||||
if x >= 0 && y >= 0 && x < cb.w && y < cb.h {
|
||||
c := &cb.cells[(y*cb.w)+x]
|
||||
if dirty {
|
||||
c.lastMain = rune(0)
|
||||
} else {
|
||||
if c.currMain == rune(0) {
|
||||
c.currMain = ' '
|
||||
}
|
||||
c.lastMain = c.currMain
|
||||
c.lastComb = c.currComb
|
||||
c.lastStyle = c.currStyle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Resize is used to resize the cells array, with different dimensions,
|
||||
// while preserving the original contents. The cells will be invalidated
|
||||
// so that they can be redrawn.
|
||||
func (cb *CellBuffer) Resize(w, h int) {
|
||||
|
||||
if cb.h == h && cb.w == w {
|
||||
return
|
||||
}
|
||||
|
||||
newc := make([]cell, w*h)
|
||||
for y := 0; y < h && y < cb.h; y++ {
|
||||
for x := 0; x < w && x < cb.w; x++ {
|
||||
oc := &cb.cells[(y*cb.w)+x]
|
||||
nc := &newc[(y*w)+x]
|
||||
nc.currMain = oc.currMain
|
||||
nc.currComb = oc.currComb
|
||||
nc.currStyle = oc.currStyle
|
||||
nc.width = oc.width
|
||||
nc.lastMain = rune(0)
|
||||
}
|
||||
}
|
||||
cb.cells = newc
|
||||
cb.h = h
|
||||
cb.w = w
|
||||
}
|
||||
|
||||
// Fill fills the entire cell buffer array with the specified character
|
||||
// and style. Normally choose ' ' to clear the screen. This API doesn't
|
||||
// support combining characters, or characters with a width larger than one.
|
||||
func (cb *CellBuffer) Fill(r rune, style Style) {
|
||||
for i := range cb.cells {
|
||||
c := &cb.cells[i]
|
||||
c.currMain = r
|
||||
c.currComb = nil
|
||||
c.currStyle = style
|
||||
c.width = 1
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
// +build plan9 nacl
|
||||
|
||||
// Copyright 2015 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcell
|
||||
|
||||
func getCharset() string {
|
||||
return ""
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
// +build !windows,!nacl,!plan9
|
||||
|
||||
// Copyright 2016 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcell
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func getCharset() string {
|
||||
// Determine the character set. This can help us later.
|
||||
// Per POSIX, we search for LC_ALL first, then LC_CTYPE, and
|
||||
// finally LANG. First one set wins.
|
||||
locale := ""
|
||||
if locale = os.Getenv("LC_ALL"); locale == "" {
|
||||
if locale = os.Getenv("LC_CTYPE"); locale == "" {
|
||||
locale = os.Getenv("LANG")
|
||||
}
|
||||
}
|
||||
if locale == "POSIX" || locale == "C" {
|
||||
return "US-ASCII"
|
||||
}
|
||||
if i := strings.IndexRune(locale, '@'); i >= 0 {
|
||||
locale = locale[:i]
|
||||
}
|
||||
if i := strings.IndexRune(locale, '.'); i >= 0 {
|
||||
locale = locale[i+1:]
|
||||
} else {
|
||||
// Default assumption, and on Linux we can see LC_ALL
|
||||
// without a character set, which we assume implies UTF-8.
|
||||
return "UTF-8"
|
||||
}
|
||||
// XXX: add support for aliases
|
||||
return locale
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
// +build windows
|
||||
|
||||
// Copyright 2015 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcell
|
||||
|
||||
func getCharset() string {
|
||||
return "UTF-16"
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,52 @@
|
||||
// Copyright 2016 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcell
|
||||
|
||||
import (
|
||||
"github.com/lucasb-eyer/go-colorful"
|
||||
"math"
|
||||
)
|
||||
|
||||
// FindColor attempts to find a given color, or the best match possible for it,
|
||||
// from the palette given. This is an expensive operation, so results should
|
||||
// be cached by the caller.
|
||||
func FindColor(c Color, palette []Color) Color {
|
||||
match := ColorDefault
|
||||
dist := float64(0)
|
||||
r, g, b := c.RGB()
|
||||
c1 := colorful.Color{
|
||||
R: float64(r) / 255.0,
|
||||
G: float64(g) / 255.0,
|
||||
B: float64(b) / 255.0,
|
||||
}
|
||||
for _, d := range palette {
|
||||
r, g, b = d.RGB()
|
||||
c2 := colorful.Color{
|
||||
R: float64(r) / 255.0,
|
||||
G: float64(g) / 255.0,
|
||||
B: float64(b) / 255.0,
|
||||
}
|
||||
// CIE94 is more accurate, but really really expensive.
|
||||
nd := c1.DistanceCIE76(c2)
|
||||
if math.IsNaN(nd) {
|
||||
nd = math.Inf(1)
|
||||
}
|
||||
if match == ColorDefault || nd < dist {
|
||||
match = d
|
||||
dist = nd
|
||||
}
|
||||
}
|
||||
return match
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
// +build !windows
|
||||
|
||||
// Copyright 2015 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcell
|
||||
|
||||
// NewConsoleScreen returns a console based screen. This platform
|
||||
// doesn't have support for any, so it returns nil and a suitable error.
|
||||
func NewConsoleScreen() (Screen, error) {
|
||||
return nil, ErrNoScreen
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,48 @@
|
||||
// Copyright 2018 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package tcell provides a lower-level, portable API for building
|
||||
// programs that interact with terminals or consoles. It works with
|
||||
// both common (and many uncommon!) terminals or terminal emulators,
|
||||
// and Windows console implementations.
|
||||
//
|
||||
// It provides support for up to 256 colors, text attributes, and box drawing
|
||||
// elements. A database of terminals built from a real terminfo database
|
||||
// is provided, along with code to generate new database entries.
|
||||
//
|
||||
// Tcell offers very rich support for mice, dependent upon the terminal
|
||||
// of course. (Windows, XTerm, and iTerm 2 are known to work very well.)
|
||||
//
|
||||
// If the environment is not Unicode by default, such as an ISO8859 based
|
||||
// locale or GB18030, Tcell can convert input and output, so that your
|
||||
// terminal can operate in whatever locale is most convenient, while the
|
||||
// application program can just assume "everything is UTF-8". Reasonable
|
||||
// defaults are used for updating characters to something suitable for
|
||||
// display. Unicode box drawing characters will be converted to use the
|
||||
// alternate character set of your terminal, if native conversions are
|
||||
// not available. If no ACS is available, then some ASCII fallbacks will
|
||||
// be used.
|
||||
//
|
||||
// Note that support for non-UTF-8 locales (other than C) must be enabled
|
||||
// by the application using RegisterEncoding() -- we don't have them all
|
||||
// enabled by default to avoid bloating the application unneccessarily.
|
||||
// (These days UTF-8 is good enough for almost everyone, and nobody should
|
||||
// be using legacy locales anymore.) Also, actual glyphs for various code
|
||||
// point will only be displayed if your terminal or emulator (or the font
|
||||
// the emulator is using) supports them.
|
||||
//
|
||||
// A rich set of keycodes is supported, with support for up to 65 function
|
||||
// keys, and various other special keys.
|
||||
//
|
||||
package tcell
|
@ -0,0 +1,139 @@
|
||||
// Copyright 2015 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcell
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
|
||||
gencoding "github.com/gdamore/encoding"
|
||||
)
|
||||
|
||||
var encodings map[string]encoding.Encoding
|
||||
var encodingLk sync.Mutex
|
||||
var encodingFallback EncodingFallback = EncodingFallbackFail
|
||||
|
||||
// RegisterEncoding may be called by the application to register an encoding.
|
||||
// The presence of additional encodings will facilitate application usage with
|
||||
// terminal environments where the I/O subsystem does not support Unicode.
|
||||
//
|
||||
// Windows systems use Unicode natively, and do not need any of the encoding
|
||||
// subsystem when using Windows Console screens.
|
||||
//
|
||||
// Please see the Go documentation for golang.org/x/text/encoding -- most of
|
||||
// the common ones exist already as stock variables. For example, ISO8859-15
|
||||
// can be registered using the following code:
|
||||
//
|
||||
// import "golang.org/x/text/encoding/charmap"
|
||||
//
|
||||
// ...
|
||||
// RegisterEncoding("ISO8859-15", charmap.ISO8859_15)
|
||||
//
|
||||
// Aliases can be registered as well, for example "8859-15" could be an alias
|
||||
// for "ISO8859-15".
|
||||
//
|
||||
// For POSIX systems, the tcell package will check the environment variables
|
||||
// LC_ALL, LC_CTYPE, and LANG (in that order) to determine the character set.
|
||||
// These are expected to have the following pattern:
|
||||
//
|
||||
// $language[.$codeset[@$variant]
|
||||
//
|
||||
// We extract only the $codeset part, which will usually be something like
|
||||
// UTF-8 or ISO8859-15 or KOI8-R. Note that if the locale is either "POSIX"
|
||||
// or "C", then we assume US-ASCII (the POSIX 'portable character set'
|
||||
// and assume all other characters are somehow invalid.)
|
||||
//
|
||||
// Modern POSIX systems and terminal emulators may use UTF-8, and for those
|
||||
// systems, this API is also unnecessary. For example, Darwin (MacOS X) and
|
||||
// modern Linux running modern xterm generally will out of the box without
|
||||
// any of this. Use of UTF-8 is recommended when possible, as it saves
|
||||
// quite a lot processing overhead.
|
||||
//
|
||||
// Note that some encodings are quite large (for example GB18030 which is a
|
||||
// superset of Unicode) and so the application size can be expected ot
|
||||
// increase quite a bit as each encoding is added. The East Asian encodings
|
||||
// have been seen to add 100-200K per encoding to the application size.
|
||||
//
|
||||
func RegisterEncoding(charset string, enc encoding.Encoding) {
|
||||
encodingLk.Lock()
|
||||
charset = strings.ToLower(charset)
|
||||
encodings[charset] = enc
|
||||
encodingLk.Unlock()
|
||||
}
|
||||
|
||||
// EncodingFallback describes how the system behavees when the locale
|
||||
// requires a character set that we do not support. The system always
|
||||
// supports UTF-8 and US-ASCII. On Windows consoles, UTF-16LE is also
|
||||
// supported automatically. Other character sets must be added using the
|
||||
// RegisterEncoding API. (A large group of nearly all of them can be
|
||||
// added using the RegisterAll function in the encoding sub package.)
|
||||
type EncodingFallback int
|
||||
|
||||
const (
|
||||
// EncodingFallbackFail behavior causes GetEncoding to fail
|
||||
// when it cannot find an encoding.
|
||||
EncodingFallbackFail = iota
|
||||
|
||||
// EncodingFallbackASCII behaviore causes GetEncoding to fall back
|
||||
// to a 7-bit ASCII encoding, if no other encoding can be found.
|
||||
EncodingFallbackASCII
|
||||
|
||||
// EncodingFallbackUTF8 behavior causes GetEncoding to assume
|
||||
// UTF8 can pass unmodified upon failure. Note that this behavior
|
||||
// is not recommended, unless you are sure your terminal can cope
|
||||
// with real UTF8 sequences.
|
||||
EncodingFallbackUTF8
|
||||
)
|
||||
|
||||
// SetEncodingFallback changes the behavior of GetEncoding when a suitable
|
||||
// encoding is not found. The default is EncodingFallbackFail, which
|
||||
// causes GetEncoding to simply return nil.
|
||||
func SetEncodingFallback(fb EncodingFallback) {
|
||||
encodingLk.Lock()
|
||||
encodingFallback = fb
|
||||
encodingLk.Unlock()
|
||||
}
|
||||
|
||||
// GetEncoding is used by Screen implementors who want to locate an encoding
|
||||
// for the given character set name. Note that this will return nil for
|
||||
// either the Unicode (UTF-8) or ASCII encodings, since we don't use
|
||||
// encodings for them but instead have our own native methods.
|
||||
func GetEncoding(charset string) encoding.Encoding {
|
||||
charset = strings.ToLower(charset)
|
||||
encodingLk.Lock()
|
||||
defer encodingLk.Unlock()
|
||||
if enc, ok := encodings[charset]; ok {
|
||||
return enc
|
||||
}
|
||||
switch encodingFallback {
|
||||
case EncodingFallbackASCII:
|
||||
return gencoding.ASCII
|
||||
case EncodingFallbackUTF8:
|
||||
return encoding.Nop
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
// We always support UTF-8 and ASCII.
|
||||
encodings = make(map[string]encoding.Encoding)
|
||||
encodings["utf-8"] = gencoding.UTF8
|
||||
encodings["utf8"] = gencoding.UTF8
|
||||
encodings["us-ascii"] = gencoding.ASCII
|
||||
encodings["ascii"] = gencoding.ASCII
|
||||
encodings["iso646"] = gencoding.ASCII
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
// Copyright 2015 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcell
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/gdamore/tcell/v2/terminfo"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrTermNotFound indicates that a suitable terminal entry could
|
||||
// not be found. This can result from either not having TERM set,
|
||||
// or from the TERM failing to support certain minimal functionality,
|
||||
// in particular absolute cursor addressability (the cup capability)
|
||||
// is required. For example, legacy "adm3" lacks this capability,
|
||||
// whereas the slightly newer "adm3a" supports it. This failure
|
||||
// occurs most often with "dumb".
|
||||
ErrTermNotFound = terminfo.ErrTermNotFound
|
||||
|
||||
// ErrNoScreen indicates that no suitable screen could be found.
|
||||
// This may result from attempting to run on a platform where there
|
||||
// is no support for either termios or console I/O (such as nacl),
|
||||
// or from running in an environment where there is no access to
|
||||
// a suitable console/terminal device. (For example, running on
|
||||
// without a controlling TTY or with no /dev/tty on POSIX platforms.)
|
||||
ErrNoScreen = errors.New("no suitable screen available")
|
||||
|
||||
// ErrNoCharset indicates that the locale environment the
|
||||
// program is not supported by the program, because no suitable
|
||||
// encoding was found for it. This problem never occurs if
|
||||
// the environment is UTF-8 or UTF-16.
|
||||
ErrNoCharset = errors.New("character set not supported")
|
||||
|
||||
// ErrEventQFull indicates that the event queue is full, and
|
||||
// cannot accept more events.
|
||||
ErrEventQFull = errors.New("event queue full")
|
||||
)
|
||||
|
||||
// An EventError is an event representing some sort of error, and carries
|
||||
// an error payload.
|
||||
type EventError struct {
|
||||
t time.Time
|
||||
err error
|
||||
}
|
||||
|
||||
// When returns the time when the event was created.
|
||||
func (ev *EventError) When() time.Time {
|
||||
return ev.t
|
||||
}
|
||||
|
||||
// Error implements the error.
|
||||
func (ev *EventError) Error() string {
|
||||
return ev.err.Error()
|
||||
}
|
||||
|
||||
// NewEventError creates an ErrorEvent with the given error payload.
|
||||
func NewEventError(err error) *EventError {
|
||||
return &EventError{t: time.Now(), err: err}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
// Copyright 2015 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcell
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Event is a generic interface used for passing around Events.
|
||||
// Concrete types follow.
|
||||
type Event interface {
|
||||
// When reports the time when the event was generated.
|
||||
When() time.Time
|
||||
}
|
||||
|
||||
// EventTime is a simple base event class, suitable for easy reuse.
|
||||
// It can be used to deliver actual timer events as well.
|
||||
type EventTime struct {
|
||||
when time.Time
|
||||
}
|
||||
|
||||
// When returns the time stamp when the event occurred.
|
||||
func (e *EventTime) When() time.Time {
|
||||
return e.when
|
||||
}
|
||||
|
||||
// SetEventTime sets the time of occurrence for the event.
|
||||
func (e *EventTime) SetEventTime(t time.Time) {
|
||||
e.when = t
|
||||
}
|
||||
|
||||
// SetEventNow sets the time of occurrence for the event to the current time.
|
||||
func (e *EventTime) SetEventNow() {
|
||||
e.SetEventTime(time.Now())
|
||||
}
|
||||
|
||||
// EventHandler is anything that handles events. If the handler has
|
||||
// consumed the event, it should return true. False otherwise.
|
||||
type EventHandler interface {
|
||||
HandleEvent(Event) bool
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
// Copyright 2015 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcell
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// EventInterrupt is a generic wakeup event. Its can be used to
|
||||
// to request a redraw. It can carry an arbitrary payload, as well.
|
||||
type EventInterrupt struct {
|
||||
t time.Time
|
||||
v interface{}
|
||||
}
|
||||
|
||||
// When returns the time when this event was created.
|
||||
func (ev *EventInterrupt) When() time.Time {
|
||||
return ev.t
|
||||
}
|
||||
|
||||
// Data is used to obtain the opaque event payload.
|
||||
func (ev *EventInterrupt) Data() interface{} {
|
||||
return ev.v
|
||||
}
|
||||
|
||||
// NewEventInterrupt creates an EventInterrupt with the given payload.
|
||||
func NewEventInterrupt(data interface{}) *EventInterrupt {
|
||||
return &EventInterrupt{t: time.Now(), v: data}
|
||||
}
|
@ -0,0 +1,470 @@
|
||||
// Copyright 2016 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// EventKey represents a key press. Usually this is a key press followed
|
||||
// by a key release, but since terminal programs don't have a way to report
|
||||
// key release events, we usually get just one event. If a key is held down
|
||||
// then the terminal may synthesize repeated key presses at some predefined
|
||||
// rate. We have no control over that, nor visibility into it.
|
||||
//
|
||||
// In some cases, we can have a modifier key, such as ModAlt, that can be
|
||||
// generated with a key press. (This usually is represented by having the
|
||||
// high bit set, or in some cases, by sending an ESC prior to the rune.)
|
||||
//
|
||||
// If the value of Key() is KeyRune, then the actual key value will be
|
||||
// available with the Rune() method. This will be the case for most keys.
|
||||
// In most situations, the modifiers will not be set. For example, if the
|
||||
// rune is 'A', this will be reported without the ModShift bit set, since
|
||||
// really can't tell if the Shift key was pressed (it might have been CAPSLOCK,
|
||||
// or a terminal that only can send capitals, or keyboard with separate
|
||||
// capital letters from lower case letters).
|
||||
//
|
||||
// Generally, terminal applications have far less visibility into keyboard
|
||||
// activity than graphical applications. Hence, they should avoid depending
|
||||
// overly much on availability of modifiers, or the availability of any
|
||||
// specific keys.
|
||||
type EventKey struct {
|
||||
t time.Time
|
||||
mod ModMask
|
||||
key Key
|
||||
ch rune
|
||||
}
|
||||
|
||||
// When returns the time when this Event was created, which should closely
|
||||
// match the time when the key was pressed.
|
||||
func (ev *EventKey) When() time.Time {
|
||||
return ev.t
|
||||
}
|
||||
|
||||
// Rune returns the rune corresponding to the key press, if it makes sense.
|
||||
// The result is only defined if the value of Key() is KeyRune.
|
||||
func (ev *EventKey) Rune() rune {
|
||||
return ev.ch
|
||||
}
|
||||
|
||||
// Key returns a virtual key code. We use this to identify specific key
|
||||
// codes, such as KeyEnter, etc. Most control and function keys are reported
|
||||
// with unique Key values. Normal alphanumeric and punctuation keys will
|
||||
// generally return KeyRune here; the specific key can be further decoded
|
||||
// using the Rune() function.
|
||||
func (ev *EventKey) Key() Key {
|
||||
return ev.key
|
||||
}
|
||||
|
||||
// Modifiers returns the modifiers that were present with the key press. Note
|
||||
// that not all platforms and terminals support this equally well, and some
|
||||
// cases we will not not know for sure. Hence, applications should avoid
|
||||
// using this in most circumstances.
|
||||
func (ev *EventKey) Modifiers() ModMask {
|
||||
return ev.mod
|
||||
}
|
||||
|
||||
// KeyNames holds the written names of special keys. Useful to echo back a key
|
||||
// name, or to look up a key from a string value.
|
||||
var KeyNames = map[Key]string{
|
||||
KeyEnter: "Enter",
|
||||
KeyBackspace: "Backspace",
|
||||
KeyTab: "Tab",
|
||||
KeyBacktab: "Backtab",
|
||||
KeyEsc: "Esc",
|
||||
KeyBackspace2: "Backspace2",
|
||||
KeyDelete: "Delete",
|
||||
KeyInsert: "Insert",
|
||||
KeyUp: "Up",
|
||||
KeyDown: "Down",
|
||||
KeyLeft: "Left",
|
||||
KeyRight: "Right",
|
||||
KeyHome: "Home",
|
||||
KeyEnd: "End",
|
||||
KeyUpLeft: "UpLeft",
|
||||
KeyUpRight: "UpRight",
|
||||
KeyDownLeft: "DownLeft",
|
||||
KeyDownRight: "DownRight",
|
||||
KeyCenter: "Center",
|
||||
KeyPgDn: "PgDn",
|
||||
KeyPgUp: "PgUp",
|
||||
KeyClear: "Clear",
|
||||
KeyExit: "Exit",
|
||||
KeyCancel: "Cancel",
|
||||
KeyPause: "Pause",
|
||||
KeyPrint: "Print",
|
||||
KeyF1: "F1",
|
||||
KeyF2: "F2",
|
||||
KeyF3: "F3",
|
||||
KeyF4: "F4",
|
||||
KeyF5: "F5",
|
||||
KeyF6: "F6",
|
||||
KeyF7: "F7",
|
||||
KeyF8: "F8",
|
||||
KeyF9: "F9",
|
||||
KeyF10: "F10",
|
||||
KeyF11: "F11",
|
||||
KeyF12: "F12",
|
||||
KeyF13: "F13",
|
||||
KeyF14: "F14",
|
||||
KeyF15: "F15",
|
||||
KeyF16: "F16",
|
||||
KeyF17: "F17",
|
||||
KeyF18: "F18",
|
||||
KeyF19: "F19",
|
||||
KeyF20: "F20",
|
||||
KeyF21: "F21",
|
||||
KeyF22: "F22",
|
||||
KeyF23: "F23",
|
||||
KeyF24: "F24",
|
||||
KeyF25: "F25",
|
||||
KeyF26: "F26",
|
||||
KeyF27: "F27",
|
||||
KeyF28: "F28",
|
||||
KeyF29: "F29",
|
||||
KeyF30: "F30",
|
||||
KeyF31: "F31",
|
||||
KeyF32: "F32",
|
||||
KeyF33: "F33",
|
||||
KeyF34: "F34",
|
||||
KeyF35: "F35",
|
||||
KeyF36: "F36",
|
||||
KeyF37: "F37",
|
||||
KeyF38: "F38",
|
||||
KeyF39: "F39",
|
||||
KeyF40: "F40",
|
||||
KeyF41: "F41",
|
||||
KeyF42: "F42",
|
||||
KeyF43: "F43",
|
||||
KeyF44: "F44",
|
||||
KeyF45: "F45",
|
||||
KeyF46: "F46",
|
||||
KeyF47: "F47",
|
||||
KeyF48: "F48",
|
||||
KeyF49: "F49",
|
||||
KeyF50: "F50",
|
||||
KeyF51: "F51",
|
||||
KeyF52: "F52",
|
||||
KeyF53: "F53",
|
||||
KeyF54: "F54",
|
||||
KeyF55: "F55",
|
||||
KeyF56: "F56",
|
||||
KeyF57: "F57",
|
||||
KeyF58: "F58",
|
||||
KeyF59: "F59",
|
||||
KeyF60: "F60",
|
||||
KeyF61: "F61",
|
||||
KeyF62: "F62",
|
||||
KeyF63: "F63",
|
||||
KeyF64: "F64",
|
||||
KeyCtrlA: "Ctrl-A",
|
||||
KeyCtrlB: "Ctrl-B",
|
||||
KeyCtrlC: "Ctrl-C",
|
||||
KeyCtrlD: "Ctrl-D",
|
||||
KeyCtrlE: "Ctrl-E",
|
||||
KeyCtrlF: "Ctrl-F",
|
||||
KeyCtrlG: "Ctrl-G",
|
||||
KeyCtrlJ: "Ctrl-J",
|
||||
KeyCtrlK: "Ctrl-K",
|
||||
KeyCtrlL: "Ctrl-L",
|
||||
KeyCtrlN: "Ctrl-N",
|
||||
KeyCtrlO: "Ctrl-O",
|
||||
KeyCtrlP: "Ctrl-P",
|
||||
KeyCtrlQ: "Ctrl-Q",
|
||||
KeyCtrlR: "Ctrl-R",
|
||||
KeyCtrlS: "Ctrl-S",
|
||||
KeyCtrlT: "Ctrl-T",
|
||||
KeyCtrlU: "Ctrl-U",
|
||||
KeyCtrlV: "Ctrl-V",
|
||||
KeyCtrlW: "Ctrl-W",
|
||||
KeyCtrlX: "Ctrl-X",
|
||||
KeyCtrlY: "Ctrl-Y",
|
||||
KeyCtrlZ: "Ctrl-Z",
|
||||
KeyCtrlSpace: "Ctrl-Space",
|
||||
KeyCtrlUnderscore: "Ctrl-_",
|
||||
KeyCtrlRightSq: "Ctrl-]",
|
||||
KeyCtrlBackslash: "Ctrl-\\",
|
||||
KeyCtrlCarat: "Ctrl-^",
|
||||
}
|
||||
|
||||
// Name returns a printable value or the key stroke. This can be used
|
||||
// when printing the event, for example.
|
||||
func (ev *EventKey) Name() string {
|
||||
s := ""
|
||||
m := []string{}
|
||||
if ev.mod&ModShift != 0 {
|
||||
m = append(m, "Shift")
|
||||
}
|
||||
if ev.mod&ModAlt != 0 {
|
||||
m = append(m, "Alt")
|
||||
}
|
||||
if ev.mod&ModMeta != 0 {
|
||||
m = append(m, "Meta")
|
||||
}
|
||||
if ev.mod&ModCtrl != 0 {
|
||||
m = append(m, "Ctrl")
|
||||
}
|
||||
|
||||
ok := false
|
||||
if s, ok = KeyNames[ev.key]; !ok {
|
||||
if ev.key == KeyRune {
|
||||
s = "Rune[" + string(ev.ch) + "]"
|
||||
} else {
|
||||
s = fmt.Sprintf("Key[%d,%d]", ev.key, int(ev.ch))
|
||||
}
|
||||
}
|
||||
if len(m) != 0 {
|
||||
if ev.mod&ModCtrl != 0 && strings.HasPrefix(s, "Ctrl-") {
|
||||
s = s[5:]
|
||||
}
|
||||
return fmt.Sprintf("%s+%s", strings.Join(m, "+"), s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// NewEventKey attempts to create a suitable event. It parses the various
|
||||
// ASCII control sequences if KeyRune is passed for Key, but if the caller
|
||||
// has more precise information it should set that specifically. Callers
|
||||
// that aren't sure about modifier state (most) should just pass ModNone.
|
||||
func NewEventKey(k Key, ch rune, mod ModMask) *EventKey {
|
||||
if k == KeyRune && (ch < ' ' || ch == 0x7f) {
|
||||
// Turn specials into proper key codes. This is for
|
||||
// control characters and the DEL.
|
||||
k = Key(ch)
|
||||
if mod == ModNone && ch < ' ' {
|
||||
switch Key(ch) {
|
||||
case KeyBackspace, KeyTab, KeyEsc, KeyEnter:
|
||||
// these keys are directly typeable without CTRL
|
||||
default:
|
||||
// most likely entered with a CTRL keypress
|
||||
mod = ModCtrl
|
||||
}
|
||||
}
|
||||
}
|
||||
return &EventKey{t: time.Now(), key: k, ch: ch, mod: mod}
|
||||
}
|
||||
|
||||
// ModMask is a mask of modifier keys. Note that it will not always be
|
||||
// possible to report modifier keys.
|
||||
type ModMask int16
|
||||
|
||||
// These are the modifiers keys that can be sent either with a key press,
|
||||
// or a mouse event. Note that as of now, due to the confusion associated
|
||||
// with Meta, and the lack of support for it on many/most platforms, the
|
||||
// current implementations never use it. Instead, they use ModAlt, even for
|
||||
// events that could possibly have been distinguished from ModAlt.
|
||||
const (
|
||||
ModShift ModMask = 1 << iota
|
||||
ModCtrl
|
||||
ModAlt
|
||||
ModMeta
|
||||
ModNone ModMask = 0
|
||||
)
|
||||
|
||||
// Key is a generic value for representing keys, and especially special
|
||||
// keys (function keys, cursor movement keys, etc.) For normal keys, like
|
||||
// ASCII letters, we use KeyRune, and then expect the application to
|
||||
// inspect the Rune() member of the EventKey.
|
||||
type Key int16
|
||||
|
||||
// This is the list of named keys. KeyRune is special however, in that it is
|
||||
// a place holder key indicating that a printable character was sent. The
|
||||
// actual value of the rune will be transported in the Rune of the associated
|
||||
// EventKey.
|
||||
const (
|
||||
KeyRune Key = iota + 256
|
||||
KeyUp
|
||||
KeyDown
|
||||
KeyRight
|
||||
KeyLeft
|
||||
KeyUpLeft
|
||||
KeyUpRight
|
||||
KeyDownLeft
|
||||
KeyDownRight
|
||||
KeyCenter
|
||||
KeyPgUp
|
||||
KeyPgDn
|
||||
KeyHome
|
||||
KeyEnd
|
||||
KeyInsert
|
||||
KeyDelete
|
||||
KeyHelp
|
||||
KeyExit
|
||||
KeyClear
|
||||
KeyCancel
|
||||
KeyPrint
|
||||
KeyPause
|
||||
KeyBacktab
|
||||
KeyF1
|
||||
KeyF2
|
||||
KeyF3
|
||||
KeyF4
|
||||
KeyF5
|
||||
KeyF6
|
||||
KeyF7
|
||||
KeyF8
|
||||
KeyF9
|
||||
KeyF10
|
||||
KeyF11
|
||||
KeyF12
|
||||
KeyF13
|
||||
KeyF14
|
||||
KeyF15
|
||||
KeyF16
|
||||
KeyF17
|
||||
KeyF18
|
||||
KeyF19
|
||||
KeyF20
|
||||
KeyF21
|
||||
KeyF22
|
||||
KeyF23
|
||||
KeyF24
|
||||
KeyF25
|
||||
KeyF26
|
||||
KeyF27
|
||||
KeyF28
|
||||
KeyF29
|
||||
KeyF30
|
||||
KeyF31
|
||||
KeyF32
|
||||
KeyF33
|
||||
KeyF34
|
||||
KeyF35
|
||||
KeyF36
|
||||
KeyF37
|
||||
KeyF38
|
||||
KeyF39
|
||||
KeyF40
|
||||
KeyF41
|
||||
KeyF42
|
||||
KeyF43
|
||||
KeyF44
|
||||
KeyF45
|
||||
KeyF46
|
||||
KeyF47
|
||||
KeyF48
|
||||
KeyF49
|
||||
KeyF50
|
||||
KeyF51
|
||||
KeyF52
|
||||
KeyF53
|
||||
KeyF54
|
||||
KeyF55
|
||||
KeyF56
|
||||
KeyF57
|
||||
KeyF58
|
||||
KeyF59
|
||||
KeyF60
|
||||
KeyF61
|
||||
KeyF62
|
||||
KeyF63
|
||||
KeyF64
|
||||
)
|
||||
|
||||
const (
|
||||
// These key codes are used internally, and will never appear to applications.
|
||||
keyPasteStart Key = iota + 16384
|
||||
keyPasteEnd
|
||||
)
|
||||
|
||||
// These are the control keys. Note that they overlap with other keys,
|
||||
// perhaps. For example, KeyCtrlH is the same as KeyBackspace.
|
||||
const (
|
||||
KeyCtrlSpace Key = iota
|
||||
KeyCtrlA
|
||||
KeyCtrlB
|
||||
KeyCtrlC
|
||||
KeyCtrlD
|
||||
KeyCtrlE
|
||||
KeyCtrlF
|
||||
KeyCtrlG
|
||||
KeyCtrlH
|
||||
KeyCtrlI
|
||||
KeyCtrlJ
|
||||
KeyCtrlK
|
||||
KeyCtrlL
|
||||
KeyCtrlM
|
||||
KeyCtrlN
|
||||
KeyCtrlO
|
||||
KeyCtrlP
|
||||
KeyCtrlQ
|
||||
KeyCtrlR
|
||||
KeyCtrlS
|
||||
KeyCtrlT
|
||||
KeyCtrlU
|
||||
KeyCtrlV
|
||||
KeyCtrlW
|
||||
KeyCtrlX
|
||||
KeyCtrlY
|
||||
KeyCtrlZ
|
||||
KeyCtrlLeftSq // Escape
|
||||
KeyCtrlBackslash
|
||||
KeyCtrlRightSq
|
||||
KeyCtrlCarat
|
||||
KeyCtrlUnderscore
|
||||
)
|
||||
|
||||
// Special values - these are fixed in an attempt to make it more likely
|
||||
// that aliases will encode the same way.
|
||||
|
||||
// These are the defined ASCII values for key codes. They generally match
|
||||
// with KeyCtrl values.
|
||||
const (
|
||||
KeyNUL Key = iota
|
||||
KeySOH
|
||||
KeySTX
|
||||
KeyETX
|
||||
KeyEOT
|
||||
KeyENQ
|
||||
KeyACK
|
||||
KeyBEL
|
||||
KeyBS
|
||||
KeyTAB
|
||||
KeyLF
|
||||
KeyVT
|
||||
KeyFF
|
||||
KeyCR
|
||||
KeySO
|
||||
KeySI
|
||||
KeyDLE
|
||||
KeyDC1
|
||||
KeyDC2
|
||||
KeyDC3
|
||||
KeyDC4
|
||||
KeyNAK
|
||||
KeySYN
|
||||
KeyETB
|
||||
KeyCAN
|
||||
KeyEM
|
||||
KeySUB
|
||||
KeyESC
|
||||
KeyFS
|
||||
KeyGS
|
||||
KeyRS
|
||||
KeyUS
|
||||
KeyDEL Key = 0x7F
|
||||
)
|
||||
|
||||
// These keys are aliases for other names.
|
||||
const (
|
||||
KeyBackspace = KeyBS
|
||||
KeyTab = KeyTAB
|
||||
KeyEsc = KeyESC
|
||||
KeyEscape = KeyESC
|
||||
KeyEnter = KeyCR
|
||||
KeyBackspace2 = KeyDEL
|
||||
)
|
@ -0,0 +1,103 @@
|
||||
// Copyright 2020 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcell
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// EventMouse is a mouse event. It is sent on either mouse up or mouse down
|
||||
// events. It is also sent on mouse motion events - if the terminal supports
|
||||
// it. We make every effort to ensure that mouse release events are delivered.
|
||||
// Hence, click drag can be identified by a motion event with the mouse down,
|
||||
// without any intervening button release. On some terminals only the initiating
|
||||
// press and terminating release event will be delivered.
|
||||
//
|
||||
// Mouse wheel events, when reported, may appear on their own as individual
|
||||
// impulses; that is, there will normally not be a release event delivered
|
||||
// for mouse wheel movements.
|
||||
//
|
||||
// Most terminals cannot report the state of more than one button at a time --
|
||||
// and some cannot report motion events unless a button is pressed.
|
||||
//
|
||||
// Applications can inspect the time between events to resolve double or
|
||||
// triple clicks.
|
||||
type EventMouse struct {
|
||||
t time.Time
|
||||
btn ButtonMask
|
||||
mod ModMask
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
// When returns the time when this EventMouse was created.
|
||||
func (ev *EventMouse) When() time.Time {
|
||||
return ev.t
|
||||
}
|
||||
|
||||
// Buttons returns the list of buttons that were pressed or wheel motions.
|
||||
func (ev *EventMouse) Buttons() ButtonMask {
|
||||
return ev.btn
|
||||
}
|
||||
|
||||
// Modifiers returns a list of keyboard modifiers that were pressed
|
||||
// with the mouse button(s).
|
||||
func (ev *EventMouse) Modifiers() ModMask {
|
||||
return ev.mod
|
||||
}
|
||||
|
||||
// Position returns the mouse position in character cells. The origin
|
||||
// 0, 0 is at the upper left corner.
|
||||
func (ev *EventMouse) Position() (int, int) {
|
||||
return ev.x, ev.y
|
||||
}
|
||||
|
||||
// NewEventMouse is used to create a new mouse event. Applications
|
||||
// shouldn't need to use this; its mostly for screen implementors.
|
||||
func NewEventMouse(x, y int, btn ButtonMask, mod ModMask) *EventMouse {
|
||||
return &EventMouse{t: time.Now(), x: x, y: y, btn: btn, mod: mod}
|
||||
}
|
||||
|
||||
// ButtonMask is a mask of mouse buttons and wheel events. Mouse button presses
|
||||
// are normally delivered as both press and release events. Mouse wheel events
|
||||
// are normally just single impulse events. Windows supports up to eight
|
||||
// separate buttons plus all four wheel directions, but XTerm can only support
|
||||
// mouse buttons 1-3 and wheel up/down. Its not unheard of for terminals
|
||||
// to support only one or two buttons (think Macs). Old terminals, and true
|
||||
// emulations (such as vt100) won't support mice at all, of course.
|
||||
type ButtonMask int16
|
||||
|
||||
// These are the actual button values. Note that tcell version 1.x reversed buttons
|
||||
// two and three on *nix based terminals. We use button 1 as the primary, and
|
||||
// button 2 as the secondary, and button 3 (which is often missing) as the middle.
|
||||
const (
|
||||
Button1 ButtonMask = 1 << iota // Usually the left (primary) mouse button.
|
||||
Button2 // Usually the right (secondary) mouse button.
|
||||
Button3 // Usually the middle mouse button.
|
||||
Button4 // Often a side button (thumb/next).
|
||||
Button5 // Often a side button (thumb/prev).
|
||||
Button6
|
||||
Button7
|
||||
Button8
|
||||
WheelUp // Wheel motion up/away from user.
|
||||
WheelDown // Wheel motion down/towards user.
|
||||
WheelLeft // Wheel motion to left.
|
||||
WheelRight // Wheel motion to right.
|
||||
ButtonNone ButtonMask = 0 // No button or wheel events.
|
||||
|
||||
ButtonPrimary = Button1
|
||||
ButtonSecondary = Button2
|
||||
ButtonMiddle = Button3
|
||||
)
|
@ -0,0 +1,42 @@
|
||||
// Copyright 2021 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build darwin dragonfly freebsd netbsd openbsd
|
||||
|
||||
package tcell
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// BSD systems use TIOC style ioctls.
|
||||
|
||||
// tcSetBufParams is used by the tty driver on UNIX systems to configure the
|
||||
// buffering parameters (minimum character count and minimum wait time in msec.)
|
||||
// This also waits for output to drain first.
|
||||
func tcSetBufParams(fd int, vMin uint8, vTime uint8) error {
|
||||
_ = syscall.SetNonblock(fd, true)
|
||||
tio, err := unix.IoctlGetTermios(fd, unix.TIOCGETA)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tio.Cc[unix.VMIN] = vMin
|
||||
tio.Cc[unix.VTIME] = vTime
|
||||
if err = unix.IoctlSetTermios(fd, unix.TIOCSETAW, tio); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
// Copyright 2021 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build linux aix zos solaris
|
||||
|
||||
package tcell
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// tcSetBufParams is used by the tty driver on UNIX systems to configure the
|
||||
// buffering parameters (minimum character count and minimum wait time in msec.)
|
||||
// This also waits for output to drain first.
|
||||
func tcSetBufParams(fd int, vMin uint8, vTime uint8) error {
|
||||
_ = syscall.SetNonblock(fd, true)
|
||||
tio, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tio.Cc[unix.VMIN] = vMin
|
||||
tio.Cc[unix.VTIME] = vTime
|
||||
if err = unix.IoctlSetTermios(fd, unix.TCSETSW, tio); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue