mirror of
https://github.com/rclone/rclone
synced 2024-11-26 04:07:22 +01:00
vendor: github.com/nsf/termbox-go and dependencies for rclone ncdu
This commit is contained in:
parent
e069fc439e
commit
e31fc877e2
14
Gopkg.lock
generated
14
Gopkg.lock
generated
@ -97,6 +97,12 @@
|
||||
packages = ["."]
|
||||
revision = "2788f0dbd16903de03cb8186e5c7d97b69ad387b"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-runewidth"
|
||||
packages = ["."]
|
||||
revision = "9e777a8366cce605130a531d2cd6363d07ad7317"
|
||||
version = "v0.0.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/ncw/dropbox-sdk-go-unofficial"
|
||||
@ -115,6 +121,12 @@
|
||||
packages = ["."]
|
||||
revision = "8e9b10220613abdbc2896808ee6b43e411a4fa6c"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/nsf/termbox-go"
|
||||
packages = ["."]
|
||||
revision = "4163cd39dda1c0dda883a713640bc01e08951c24"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/pkg/errors"
|
||||
@ -250,6 +262,6 @@
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "e0227ed773a9f6c56d1bfac9de1d87c2a74ce142e418b661b74931d2e2b20945"
|
||||
inputs-digest = "0d9d9076ed37a1be89629d9d43c5291394ed374e91c775ce3993d354e1e74a25"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
8
vendor/github.com/mattn/go-runewidth/.travis.yml
generated
vendored
Normal file
8
vendor/github.com/mattn/go-runewidth/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
language: go
|
||||
go:
|
||||
- tip
|
||||
before_install:
|
||||
- go get github.com/mattn/goveralls
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
script:
|
||||
- $HOME/gopath/bin/goveralls -repotoken lAKAWPzcGsD3A8yBX3BGGtRUdJ6CaGERL
|
21
vendor/github.com/mattn/go-runewidth/LICENSE
generated
vendored
Normal file
21
vendor/github.com/mattn/go-runewidth/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Yasuhiro Matsumoto
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
27
vendor/github.com/mattn/go-runewidth/README.mkd
generated
vendored
Normal file
27
vendor/github.com/mattn/go-runewidth/README.mkd
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
go-runewidth
|
||||
============
|
||||
|
||||
[![Build Status](https://travis-ci.org/mattn/go-runewidth.png?branch=master)](https://travis-ci.org/mattn/go-runewidth)
|
||||
[![Coverage Status](https://coveralls.io/repos/mattn/go-runewidth/badge.png?branch=HEAD)](https://coveralls.io/r/mattn/go-runewidth?branch=HEAD)
|
||||
[![GoDoc](https://godoc.org/github.com/mattn/go-runewidth?status.svg)](http://godoc.org/github.com/mattn/go-runewidth)
|
||||
[![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-runewidth)](https://goreportcard.com/report/github.com/mattn/go-runewidth)
|
||||
|
||||
Provides functions to get fixed width of the character or string.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
```go
|
||||
runewidth.StringWidth("つのだ☆HIRO") == 12
|
||||
```
|
||||
|
||||
|
||||
Author
|
||||
------
|
||||
|
||||
Yasuhiro Matsumoto
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
under the MIT License: http://mattn.mit-license.org/2013
|
1223
vendor/github.com/mattn/go-runewidth/runewidth.go
generated
vendored
Normal file
1223
vendor/github.com/mattn/go-runewidth/runewidth.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8
vendor/github.com/mattn/go-runewidth/runewidth_js.go
generated
vendored
Normal file
8
vendor/github.com/mattn/go-runewidth/runewidth_js.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
// +build js
|
||||
|
||||
package runewidth
|
||||
|
||||
func IsEastAsian() bool {
|
||||
// TODO: Implement this for the web. Detect east asian in a compatible way, and return true.
|
||||
return false
|
||||
}
|
77
vendor/github.com/mattn/go-runewidth/runewidth_posix.go
generated
vendored
Normal file
77
vendor/github.com/mattn/go-runewidth/runewidth_posix.go
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
// +build !windows,!js
|
||||
|
||||
package runewidth
|
||||
|
||||
import (
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`)
|
||||
|
||||
var mblenTable = map[string]int{
|
||||
"utf-8": 6,
|
||||
"utf8": 6,
|
||||
"jis": 8,
|
||||
"eucjp": 3,
|
||||
"euckr": 2,
|
||||
"euccn": 2,
|
||||
"sjis": 2,
|
||||
"cp932": 2,
|
||||
"cp51932": 2,
|
||||
"cp936": 2,
|
||||
"cp949": 2,
|
||||
"cp950": 2,
|
||||
"big5": 2,
|
||||
"gbk": 2,
|
||||
"gb2312": 2,
|
||||
}
|
||||
|
||||
func isEastAsian(locale string) bool {
|
||||
charset := strings.ToLower(locale)
|
||||
r := reLoc.FindStringSubmatch(locale)
|
||||
if len(r) == 2 {
|
||||
charset = strings.ToLower(r[1])
|
||||
}
|
||||
|
||||
if strings.HasSuffix(charset, "@cjk_narrow") {
|
||||
return false
|
||||
}
|
||||
|
||||
for pos, b := range []byte(charset) {
|
||||
if b == '@' {
|
||||
charset = charset[:pos]
|
||||
break
|
||||
}
|
||||
}
|
||||
max := 1
|
||||
if m, ok := mblenTable[charset]; ok {
|
||||
max = m
|
||||
}
|
||||
if max > 1 && (charset[0] != 'u' ||
|
||||
strings.HasPrefix(locale, "ja") ||
|
||||
strings.HasPrefix(locale, "ko") ||
|
||||
strings.HasPrefix(locale, "zh")) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsEastAsian return true if the current locale is CJK
|
||||
func IsEastAsian() bool {
|
||||
locale := os.Getenv("LC_CTYPE")
|
||||
if locale == "" {
|
||||
locale = os.Getenv("LANG")
|
||||
}
|
||||
|
||||
// ignore C locale
|
||||
if locale == "POSIX" || locale == "C" {
|
||||
return false
|
||||
}
|
||||
if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') {
|
||||
return false
|
||||
}
|
||||
|
||||
return isEastAsian(locale)
|
||||
}
|
275
vendor/github.com/mattn/go-runewidth/runewidth_test.go
generated
vendored
Normal file
275
vendor/github.com/mattn/go-runewidth/runewidth_test.go
generated
vendored
Normal file
@ -0,0 +1,275 @@
|
||||
package runewidth
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var _ sort.Interface = (*table)(nil)
|
||||
|
||||
func (t table) Len() int {
|
||||
return len(t)
|
||||
}
|
||||
|
||||
func (t table) Less(i, j int) bool {
|
||||
return t[i].first < t[j].first
|
||||
}
|
||||
|
||||
func (t *table) Swap(i, j int) {
|
||||
(*t)[i], (*t)[j] = (*t)[j], (*t)[i]
|
||||
}
|
||||
|
||||
var tables = []table{
|
||||
private,
|
||||
nonprint,
|
||||
combining,
|
||||
doublewidth,
|
||||
ambiguous,
|
||||
emoji,
|
||||
notassigned,
|
||||
neutral,
|
||||
}
|
||||
|
||||
func TestSorted(t *testing.T) {
|
||||
for _, tbl := range tables {
|
||||
if !sort.IsSorted(&tbl) {
|
||||
t.Errorf("not sorted")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var runewidthtests = []struct {
|
||||
in rune
|
||||
out int
|
||||
eaout int
|
||||
}{
|
||||
{'世', 2, 2},
|
||||
{'界', 2, 2},
|
||||
{'セ', 1, 1},
|
||||
{'カ', 1, 1},
|
||||
{'イ', 1, 1},
|
||||
{'☆', 1, 2}, // double width in ambiguous
|
||||
{'\x00', 0, 0},
|
||||
{'\x01', 0, 0},
|
||||
{'\u0300', 0, 0},
|
||||
}
|
||||
|
||||
func TestRuneWidth(t *testing.T) {
|
||||
c := NewCondition()
|
||||
for _, tt := range runewidthtests {
|
||||
if out := c.RuneWidth(tt.in); out != tt.out {
|
||||
t.Errorf("RuneWidth(%q) = %d, want %d", tt.in, out, tt.out)
|
||||
}
|
||||
}
|
||||
c.EastAsianWidth = true
|
||||
for _, tt := range runewidthtests {
|
||||
if out := c.RuneWidth(tt.in); out != tt.eaout {
|
||||
t.Errorf("RuneWidth(%q) = %d, want %d", tt.in, out, tt.eaout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var isambiguouswidthtests = []struct {
|
||||
in rune
|
||||
out bool
|
||||
}{
|
||||
{'世', false},
|
||||
{'■', true},
|
||||
{'界', false},
|
||||
{'○', true},
|
||||
{'㈱', false},
|
||||
{'①', true},
|
||||
{'②', true},
|
||||
{'③', true},
|
||||
{'④', true},
|
||||
{'⑤', true},
|
||||
{'⑥', true},
|
||||
{'⑦', true},
|
||||
{'⑧', true},
|
||||
{'⑨', true},
|
||||
{'⑩', true},
|
||||
{'⑪', true},
|
||||
{'⑫', true},
|
||||
{'⑬', true},
|
||||
{'⑭', true},
|
||||
{'⑮', true},
|
||||
{'⑯', true},
|
||||
{'⑰', true},
|
||||
{'⑱', true},
|
||||
{'⑲', true},
|
||||
{'⑳', true},
|
||||
{'☆', true},
|
||||
}
|
||||
|
||||
func TestIsAmbiguousWidth(t *testing.T) {
|
||||
for _, tt := range isambiguouswidthtests {
|
||||
if out := IsAmbiguousWidth(tt.in); out != tt.out {
|
||||
t.Errorf("IsAmbiguousWidth(%q) = %v, want %v", tt.in, out, tt.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var stringwidthtests = []struct {
|
||||
in string
|
||||
out int
|
||||
eaout int
|
||||
}{
|
||||
{"■㈱の世界①", 10, 12},
|
||||
{"スター☆", 7, 8},
|
||||
{"つのだ☆HIRO", 11, 12},
|
||||
}
|
||||
|
||||
func TestStringWidth(t *testing.T) {
|
||||
c := NewCondition()
|
||||
for _, tt := range stringwidthtests {
|
||||
if out := c.StringWidth(tt.in); out != tt.out {
|
||||
t.Errorf("StringWidth(%q) = %q, want %q", tt.in, out, tt.out)
|
||||
}
|
||||
}
|
||||
c.EastAsianWidth = true
|
||||
for _, tt := range stringwidthtests {
|
||||
if out := c.StringWidth(tt.in); out != tt.eaout {
|
||||
t.Errorf("StringWidth(%q) = %q, want %q", tt.in, out, tt.eaout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringWidthInvalid(t *testing.T) {
|
||||
s := "こんにちわ\x00世界"
|
||||
if out := StringWidth(s); out != 14 {
|
||||
t.Errorf("StringWidth(%q) = %q, want %q", s, out, 14)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTruncateSmaller(t *testing.T) {
|
||||
s := "あいうえお"
|
||||
expected := "あいうえお"
|
||||
|
||||
if out := Truncate(s, 10, "..."); out != expected {
|
||||
t.Errorf("Truncate(%q) = %q, want %q", s, out, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTruncate(t *testing.T) {
|
||||
s := "あいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおおおおお"
|
||||
expected := "あいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおお..."
|
||||
out := Truncate(s, 80, "...")
|
||||
if out != expected {
|
||||
t.Errorf("Truncate(%q) = %q, want %q", s, out, expected)
|
||||
}
|
||||
width := StringWidth(out)
|
||||
if width != 79 {
|
||||
t.Errorf("width of Truncate(%q) should be %d, but %d", s, 79, width)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTruncateFit(t *testing.T) {
|
||||
s := "aあいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおおおおお"
|
||||
expected := "aあいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおお..."
|
||||
|
||||
out := Truncate(s, 80, "...")
|
||||
if out != expected {
|
||||
t.Errorf("Truncate(%q) = %q, want %q", s, out, expected)
|
||||
}
|
||||
width := StringWidth(out)
|
||||
if width != 80 {
|
||||
t.Errorf("width of Truncate(%q) should be %d, but %d", s, 80, width)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTruncateJustFit(t *testing.T) {
|
||||
s := "あいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおおおお"
|
||||
expected := "あいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおおおお"
|
||||
|
||||
out := Truncate(s, 80, "...")
|
||||
if out != expected {
|
||||
t.Errorf("Truncate(%q) = %q, want %q", s, out, expected)
|
||||
}
|
||||
width := StringWidth(out)
|
||||
if width != 80 {
|
||||
t.Errorf("width of Truncate(%q) should be %d, but %d", s, 80, width)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrap(t *testing.T) {
|
||||
s := `東京特許許可局局長はよく柿喰う客だ/東京特許許可局局長はよく柿喰う客だ
|
||||
123456789012345678901234567890
|
||||
|
||||
END`
|
||||
expected := `東京特許許可局局長はよく柿喰う
|
||||
客だ/東京特許許可局局長はよく
|
||||
柿喰う客だ
|
||||
123456789012345678901234567890
|
||||
|
||||
END`
|
||||
|
||||
if out := Wrap(s, 30); out != expected {
|
||||
t.Errorf("Wrap(%q) = %q, want %q", s, out, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTruncateNoNeeded(t *testing.T) {
|
||||
s := "あいうえおあい"
|
||||
expected := "あいうえおあい"
|
||||
|
||||
if out := Truncate(s, 80, "..."); out != expected {
|
||||
t.Errorf("Truncate(%q) = %q, want %q", s, out, expected)
|
||||
}
|
||||
}
|
||||
|
||||
var isneutralwidthtests = []struct {
|
||||
in rune
|
||||
out bool
|
||||
}{
|
||||
{'→', false},
|
||||
{'┊', false},
|
||||
{'┈', false},
|
||||
{'~', false},
|
||||
{'└', false},
|
||||
{'⣀', true},
|
||||
{'⣀', true},
|
||||
}
|
||||
|
||||
func TestIsNeutralWidth(t *testing.T) {
|
||||
for _, tt := range isneutralwidthtests {
|
||||
if out := IsNeutralWidth(tt.in); out != tt.out {
|
||||
t.Errorf("IsNeutralWidth(%q) = %v, want %v", tt.in, out, tt.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFillLeft(t *testing.T) {
|
||||
s := "あxいうえお"
|
||||
expected := " あxいうえお"
|
||||
|
||||
if out := FillLeft(s, 15); out != expected {
|
||||
t.Errorf("FillLeft(%q) = %q, want %q", s, out, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFillLeftFit(t *testing.T) {
|
||||
s := "あいうえお"
|
||||
expected := "あいうえお"
|
||||
|
||||
if out := FillLeft(s, 10); out != expected {
|
||||
t.Errorf("FillLeft(%q) = %q, want %q", s, out, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFillRight(t *testing.T) {
|
||||
s := "あxいうえお"
|
||||
expected := "あxいうえお "
|
||||
|
||||
if out := FillRight(s, 15); out != expected {
|
||||
t.Errorf("FillRight(%q) = %q, want %q", s, out, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFillRightFit(t *testing.T) {
|
||||
s := "あいうえお"
|
||||
expected := "あいうえお"
|
||||
|
||||
if out := FillRight(s, 10); out != expected {
|
||||
t.Errorf("FillRight(%q) = %q, want %q", s, out, expected)
|
||||
}
|
||||
}
|
25
vendor/github.com/mattn/go-runewidth/runewidth_windows.go
generated
vendored
Normal file
25
vendor/github.com/mattn/go-runewidth/runewidth_windows.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
package runewidth
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
kernel32 = syscall.NewLazyDLL("kernel32")
|
||||
procGetConsoleOutputCP = kernel32.NewProc("GetConsoleOutputCP")
|
||||
)
|
||||
|
||||
// IsEastAsian return true if the current locale is CJK
|
||||
func IsEastAsian() bool {
|
||||
r1, _, _ := procGetConsoleOutputCP.Call()
|
||||
if r1 == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
switch int(r1) {
|
||||
case 932, 51932, 936, 949, 950:
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
4
vendor/github.com/nsf/termbox-go/AUTHORS
generated
vendored
Normal file
4
vendor/github.com/nsf/termbox-go/AUTHORS
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# Please keep this file sorted.
|
||||
|
||||
Georg Reinke <guelfey@googlemail.com>
|
||||
nsf <no.smile.face@gmail.com>
|
19
vendor/github.com/nsf/termbox-go/LICENSE
generated
vendored
Normal file
19
vendor/github.com/nsf/termbox-go/LICENSE
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (C) 2012 termbox-go authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
35
vendor/github.com/nsf/termbox-go/README.md
generated
vendored
Normal file
35
vendor/github.com/nsf/termbox-go/README.md
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
## Termbox
|
||||
Termbox is a library that provides a minimalistic API which allows the programmer to write text-based user interfaces. The library is crossplatform and has both terminal-based implementations on *nix operating systems and a winapi console based implementation for windows operating systems. The basic idea is an abstraction of the greatest common subset of features available on all major terminals and other terminal-like APIs in a minimalistic fashion. Small API means it is easy to implement, test, maintain and learn it, that's what makes the termbox a distinct library in its area.
|
||||
|
||||
### Installation
|
||||
Install and update this go package with `go get -u github.com/nsf/termbox-go`
|
||||
|
||||
### Examples
|
||||
For examples of what can be done take a look at demos in the _demos directory. You can try them with go run: `go run _demos/keyboard.go`
|
||||
|
||||
There are also some interesting projects using termbox-go:
|
||||
- [godit](https://github.com/nsf/godit) is an emacsish lightweight text editor written using termbox.
|
||||
- [gomatrix](https://github.com/GeertJohan/gomatrix) connects to The Matrix and displays its data streams in your terminal.
|
||||
- [gotetris](https://github.com/jjinux/gotetris) is an implementation of Tetris.
|
||||
- [sokoban-go](https://github.com/rn2dy/sokoban-go) is an implementation of sokoban game.
|
||||
- [hecate](https://github.com/evanmiller/hecate) is a hex editor designed by Satan.
|
||||
- [httopd](https://github.com/verdverm/httopd) is top for httpd logs.
|
||||
- [mop](https://github.com/michaeldv/mop) is stock market tracker for hackers.
|
||||
- [termui](https://github.com/gizak/termui) is a terminal dashboard.
|
||||
- [termloop](https://github.com/JoelOtter/termloop) is a terminal game engine.
|
||||
- [xterm-color-chart](https://github.com/kutuluk/xterm-color-chart) is a XTerm 256 color chart.
|
||||
- [gocui](https://github.com/jroimartin/gocui) is a minimalist Go library aimed at creating console user interfaces.
|
||||
- [dry](https://github.com/moncho/dry) is an interactive cli to manage Docker containers.
|
||||
- [pxl](https://github.com/ichinaski/pxl) displays images in the terminal.
|
||||
- [snake-game](https://github.com/DyegoCosta/snake-game) is an implementation of the Snake game.
|
||||
- [gone](https://github.com/guillaumebreton/gone) is a CLI pomodoro® timer.
|
||||
- [Spoof.go](https://github.com/sabey/spoofgo) controllable movement spoofing from the cli
|
||||
- [lf](https://github.com/gokcehan/lf) is a terminal file manager
|
||||
- [rat](https://github.com/ericfreese/rat) lets you compose shell commands to build terminal applications.
|
||||
- [httplab](https://github.com/gchaincl/httplab) An interactive web server.
|
||||
- [tetris](https://github.com/MichaelS11/tetris) Go Tetris with AI option
|
||||
- [wot](https://github.com/kyu-suke/wot) Wait time during command is completed.
|
||||
- [2048-go](https://github.com/1984weed/2048-go) is 2048 in Go
|
||||
|
||||
### API reference
|
||||
[godoc.org/github.com/nsf/termbox-go](http://godoc.org/github.com/nsf/termbox-go)
|
300
vendor/github.com/nsf/termbox-go/_demos/editbox.go
generated
vendored
Normal file
300
vendor/github.com/nsf/termbox-go/_demos/editbox.go
generated
vendored
Normal file
@ -0,0 +1,300 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/mattn/go-runewidth"
|
||||
"github.com/nsf/termbox-go"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
func tbprint(x, y int, fg, bg termbox.Attribute, msg string) {
|
||||
for _, c := range msg {
|
||||
termbox.SetCell(x, y, c, fg, bg)
|
||||
x += runewidth.RuneWidth(c)
|
||||
}
|
||||
}
|
||||
|
||||
func fill(x, y, w, h int, cell termbox.Cell) {
|
||||
for ly := 0; ly < h; ly++ {
|
||||
for lx := 0; lx < w; lx++ {
|
||||
termbox.SetCell(x+lx, y+ly, cell.Ch, cell.Fg, cell.Bg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func rune_advance_len(r rune, pos int) int {
|
||||
if r == '\t' {
|
||||
return tabstop_length - pos%tabstop_length
|
||||
}
|
||||
return runewidth.RuneWidth(r)
|
||||
}
|
||||
|
||||
func voffset_coffset(text []byte, boffset int) (voffset, coffset int) {
|
||||
text = text[:boffset]
|
||||
for len(text) > 0 {
|
||||
r, size := utf8.DecodeRune(text)
|
||||
text = text[size:]
|
||||
coffset += 1
|
||||
voffset += rune_advance_len(r, voffset)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func byte_slice_grow(s []byte, desired_cap int) []byte {
|
||||
if cap(s) < desired_cap {
|
||||
ns := make([]byte, len(s), desired_cap)
|
||||
copy(ns, s)
|
||||
return ns
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func byte_slice_remove(text []byte, from, to int) []byte {
|
||||
size := to - from
|
||||
copy(text[from:], text[to:])
|
||||
text = text[:len(text)-size]
|
||||
return text
|
||||
}
|
||||
|
||||
func byte_slice_insert(text []byte, offset int, what []byte) []byte {
|
||||
n := len(text) + len(what)
|
||||
text = byte_slice_grow(text, n)
|
||||
text = text[:n]
|
||||
copy(text[offset+len(what):], text[offset:])
|
||||
copy(text[offset:], what)
|
||||
return text
|
||||
}
|
||||
|
||||
const preferred_horizontal_threshold = 5
|
||||
const tabstop_length = 8
|
||||
|
||||
type EditBox struct {
|
||||
text []byte
|
||||
line_voffset int
|
||||
cursor_boffset int // cursor offset in bytes
|
||||
cursor_voffset int // visual cursor offset in termbox cells
|
||||
cursor_coffset int // cursor offset in unicode code points
|
||||
}
|
||||
|
||||
// Draws the EditBox in the given location, 'h' is not used at the moment
|
||||
func (eb *EditBox) Draw(x, y, w, h int) {
|
||||
eb.AdjustVOffset(w)
|
||||
|
||||
const coldef = termbox.ColorDefault
|
||||
fill(x, y, w, h, termbox.Cell{Ch: ' '})
|
||||
|
||||
t := eb.text
|
||||
lx := 0
|
||||
tabstop := 0
|
||||
for {
|
||||
rx := lx - eb.line_voffset
|
||||
if len(t) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if lx == tabstop {
|
||||
tabstop += tabstop_length
|
||||
}
|
||||
|
||||
if rx >= w {
|
||||
termbox.SetCell(x+w-1, y, '→',
|
||||
coldef, coldef)
|
||||
break
|
||||
}
|
||||
|
||||
r, size := utf8.DecodeRune(t)
|
||||
if r == '\t' {
|
||||
for ; lx < tabstop; lx++ {
|
||||
rx = lx - eb.line_voffset
|
||||
if rx >= w {
|
||||
goto next
|
||||
}
|
||||
|
||||
if rx >= 0 {
|
||||
termbox.SetCell(x+rx, y, ' ', coldef, coldef)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if rx >= 0 {
|
||||
termbox.SetCell(x+rx, y, r, coldef, coldef)
|
||||
}
|
||||
lx += runewidth.RuneWidth(r)
|
||||
}
|
||||
next:
|
||||
t = t[size:]
|
||||
}
|
||||
|
||||
if eb.line_voffset != 0 {
|
||||
termbox.SetCell(x, y, '←', coldef, coldef)
|
||||
}
|
||||
}
|
||||
|
||||
// Adjusts line visual offset to a proper value depending on width
|
||||
func (eb *EditBox) AdjustVOffset(width int) {
|
||||
ht := preferred_horizontal_threshold
|
||||
max_h_threshold := (width - 1) / 2
|
||||
if ht > max_h_threshold {
|
||||
ht = max_h_threshold
|
||||
}
|
||||
|
||||
threshold := width - 1
|
||||
if eb.line_voffset != 0 {
|
||||
threshold = width - ht
|
||||
}
|
||||
if eb.cursor_voffset-eb.line_voffset >= threshold {
|
||||
eb.line_voffset = eb.cursor_voffset + (ht - width + 1)
|
||||
}
|
||||
|
||||
if eb.line_voffset != 0 && eb.cursor_voffset-eb.line_voffset < ht {
|
||||
eb.line_voffset = eb.cursor_voffset - ht
|
||||
if eb.line_voffset < 0 {
|
||||
eb.line_voffset = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (eb *EditBox) MoveCursorTo(boffset int) {
|
||||
eb.cursor_boffset = boffset
|
||||
eb.cursor_voffset, eb.cursor_coffset = voffset_coffset(eb.text, boffset)
|
||||
}
|
||||
|
||||
func (eb *EditBox) RuneUnderCursor() (rune, int) {
|
||||
return utf8.DecodeRune(eb.text[eb.cursor_boffset:])
|
||||
}
|
||||
|
||||
func (eb *EditBox) RuneBeforeCursor() (rune, int) {
|
||||
return utf8.DecodeLastRune(eb.text[:eb.cursor_boffset])
|
||||
}
|
||||
|
||||
func (eb *EditBox) MoveCursorOneRuneBackward() {
|
||||
if eb.cursor_boffset == 0 {
|
||||
return
|
||||
}
|
||||
_, size := eb.RuneBeforeCursor()
|
||||
eb.MoveCursorTo(eb.cursor_boffset - size)
|
||||
}
|
||||
|
||||
func (eb *EditBox) MoveCursorOneRuneForward() {
|
||||
if eb.cursor_boffset == len(eb.text) {
|
||||
return
|
||||
}
|
||||
_, size := eb.RuneUnderCursor()
|
||||
eb.MoveCursorTo(eb.cursor_boffset + size)
|
||||
}
|
||||
|
||||
func (eb *EditBox) MoveCursorToBeginningOfTheLine() {
|
||||
eb.MoveCursorTo(0)
|
||||
}
|
||||
|
||||
func (eb *EditBox) MoveCursorToEndOfTheLine() {
|
||||
eb.MoveCursorTo(len(eb.text))
|
||||
}
|
||||
|
||||
func (eb *EditBox) DeleteRuneBackward() {
|
||||
if eb.cursor_boffset == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
eb.MoveCursorOneRuneBackward()
|
||||
_, size := eb.RuneUnderCursor()
|
||||
eb.text = byte_slice_remove(eb.text, eb.cursor_boffset, eb.cursor_boffset+size)
|
||||
}
|
||||
|
||||
func (eb *EditBox) DeleteRuneForward() {
|
||||
if eb.cursor_boffset == len(eb.text) {
|
||||
return
|
||||
}
|
||||
_, size := eb.RuneUnderCursor()
|
||||
eb.text = byte_slice_remove(eb.text, eb.cursor_boffset, eb.cursor_boffset+size)
|
||||
}
|
||||
|
||||
func (eb *EditBox) DeleteTheRestOfTheLine() {
|
||||
eb.text = eb.text[:eb.cursor_boffset]
|
||||
}
|
||||
|
||||
func (eb *EditBox) InsertRune(r rune) {
|
||||
var buf [utf8.UTFMax]byte
|
||||
n := utf8.EncodeRune(buf[:], r)
|
||||
eb.text = byte_slice_insert(eb.text, eb.cursor_boffset, buf[:n])
|
||||
eb.MoveCursorOneRuneForward()
|
||||
}
|
||||
|
||||
// Please, keep in mind that cursor depends on the value of line_voffset, which
|
||||
// is being set on Draw() call, so.. call this method after Draw() one.
|
||||
func (eb *EditBox) CursorX() int {
|
||||
return eb.cursor_voffset - eb.line_voffset
|
||||
}
|
||||
|
||||
var edit_box EditBox
|
||||
|
||||
const edit_box_width = 30
|
||||
|
||||
func redraw_all() {
|
||||
const coldef = termbox.ColorDefault
|
||||
termbox.Clear(coldef, coldef)
|
||||
w, h := termbox.Size()
|
||||
|
||||
midy := h / 2
|
||||
midx := (w - edit_box_width) / 2
|
||||
|
||||
// unicode box drawing chars around the edit box
|
||||
termbox.SetCell(midx-1, midy, '│', coldef, coldef)
|
||||
termbox.SetCell(midx+edit_box_width, midy, '│', coldef, coldef)
|
||||
termbox.SetCell(midx-1, midy-1, '┌', coldef, coldef)
|
||||
termbox.SetCell(midx-1, midy+1, '└', coldef, coldef)
|
||||
termbox.SetCell(midx+edit_box_width, midy-1, '┐', coldef, coldef)
|
||||
termbox.SetCell(midx+edit_box_width, midy+1, '┘', coldef, coldef)
|
||||
fill(midx, midy-1, edit_box_width, 1, termbox.Cell{Ch: '─'})
|
||||
fill(midx, midy+1, edit_box_width, 1, termbox.Cell{Ch: '─'})
|
||||
|
||||
edit_box.Draw(midx, midy, edit_box_width, 1)
|
||||
termbox.SetCursor(midx+edit_box.CursorX(), midy)
|
||||
|
||||
tbprint(midx+6, midy+3, coldef, coldef, "Press ESC to quit")
|
||||
termbox.Flush()
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := termbox.Init()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer termbox.Close()
|
||||
termbox.SetInputMode(termbox.InputEsc)
|
||||
|
||||
redraw_all()
|
||||
mainloop:
|
||||
for {
|
||||
switch ev := termbox.PollEvent(); ev.Type {
|
||||
case termbox.EventKey:
|
||||
switch ev.Key {
|
||||
case termbox.KeyEsc:
|
||||
break mainloop
|
||||
case termbox.KeyArrowLeft, termbox.KeyCtrlB:
|
||||
edit_box.MoveCursorOneRuneBackward()
|
||||
case termbox.KeyArrowRight, termbox.KeyCtrlF:
|
||||
edit_box.MoveCursorOneRuneForward()
|
||||
case termbox.KeyBackspace, termbox.KeyBackspace2:
|
||||
edit_box.DeleteRuneBackward()
|
||||
case termbox.KeyDelete, termbox.KeyCtrlD:
|
||||
edit_box.DeleteRuneForward()
|
||||
case termbox.KeyTab:
|
||||
edit_box.InsertRune('\t')
|
||||
case termbox.KeySpace:
|
||||
edit_box.InsertRune(' ')
|
||||
case termbox.KeyCtrlK:
|
||||
edit_box.DeleteTheRestOfTheLine()
|
||||
case termbox.KeyHome, termbox.KeyCtrlA:
|
||||
edit_box.MoveCursorToBeginningOfTheLine()
|
||||
case termbox.KeyEnd, termbox.KeyCtrlE:
|
||||
edit_box.MoveCursorToEndOfTheLine()
|
||||
default:
|
||||
if ev.Ch != 0 {
|
||||
edit_box.InsertRune(ev.Ch)
|
||||
}
|
||||
}
|
||||
case termbox.EventError:
|
||||
panic(ev.Err)
|
||||
}
|
||||
redraw_all()
|
||||
}
|
||||
}
|
69
vendor/github.com/nsf/termbox-go/_demos/interrupt.go
generated
vendored
Normal file
69
vendor/github.com/nsf/termbox-go/_demos/interrupt.go
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/nsf/termbox-go"
|
||||
"time"
|
||||
)
|
||||
|
||||
func tbPrint(x, y int, fg, bg termbox.Attribute, msg string) {
|
||||
for _, c := range msg {
|
||||
termbox.SetCell(x, y, c, fg, bg)
|
||||
x++
|
||||
}
|
||||
}
|
||||
|
||||
func draw(i int) {
|
||||
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
|
||||
defer termbox.Flush()
|
||||
|
||||
w, h := termbox.Size()
|
||||
s := fmt.Sprintf("count = %d", i)
|
||||
|
||||
tbPrint((w/2)-(len(s)/2), h/2, termbox.ColorRed, termbox.ColorDefault, s)
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := termbox.Init()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
termbox.SetInputMode(termbox.InputEsc)
|
||||
|
||||
go func() {
|
||||
time.Sleep(5 * time.Second)
|
||||
termbox.Interrupt()
|
||||
|
||||
// This should never run - the Interrupt(), above, should cause the event
|
||||
// loop below to exit, which then exits the process. If something goes
|
||||
// wrong, this panic will trigger and show what happened.
|
||||
time.Sleep(1 * time.Second)
|
||||
panic("this should never run")
|
||||
}()
|
||||
|
||||
var count int
|
||||
|
||||
draw(count)
|
||||
mainloop:
|
||||
for {
|
||||
switch ev := termbox.PollEvent(); ev.Type {
|
||||
case termbox.EventKey:
|
||||
if ev.Ch == '+' {
|
||||
count++
|
||||
} else if ev.Ch == '-' {
|
||||
count--
|
||||
}
|
||||
|
||||
case termbox.EventError:
|
||||
panic(ev.Err)
|
||||
|
||||
case termbox.EventInterrupt:
|
||||
break mainloop
|
||||
}
|
||||
|
||||
draw(count)
|
||||
}
|
||||
termbox.Close()
|
||||
|
||||
fmt.Println("Finished")
|
||||
}
|
722
vendor/github.com/nsf/termbox-go/_demos/keyboard.go
generated
vendored
Normal file
722
vendor/github.com/nsf/termbox-go/_demos/keyboard.go
generated
vendored
Normal file
@ -0,0 +1,722 @@
|
||||
package main
|
||||
|
||||
import "github.com/nsf/termbox-go"
|
||||
import "fmt"
|
||||
|
||||
type key struct {
|
||||
x int
|
||||
y int
|
||||
ch rune
|
||||
}
|
||||
|
||||
var K_ESC = []key{{1, 1, 'E'}, {2, 1, 'S'}, {3, 1, 'C'}}
|
||||
var K_F1 = []key{{6, 1, 'F'}, {7, 1, '1'}}
|
||||
var K_F2 = []key{{9, 1, 'F'}, {10, 1, '2'}}
|
||||
var K_F3 = []key{{12, 1, 'F'}, {13, 1, '3'}}
|
||||
var K_F4 = []key{{15, 1, 'F'}, {16, 1, '4'}}
|
||||
var K_F5 = []key{{19, 1, 'F'}, {20, 1, '5'}}
|
||||
var K_F6 = []key{{22, 1, 'F'}, {23, 1, '6'}}
|
||||
var K_F7 = []key{{25, 1, 'F'}, {26, 1, '7'}}
|
||||
var K_F8 = []key{{28, 1, 'F'}, {29, 1, '8'}}
|
||||
var K_F9 = []key{{33, 1, 'F'}, {34, 1, '9'}}
|
||||
var K_F10 = []key{{36, 1, 'F'}, {37, 1, '1'}, {38, 1, '0'}}
|
||||
var K_F11 = []key{{40, 1, 'F'}, {41, 1, '1'}, {42, 1, '1'}}
|
||||
var K_F12 = []key{{44, 1, 'F'}, {45, 1, '1'}, {46, 1, '2'}}
|
||||
var K_PRN = []key{{50, 1, 'P'}, {51, 1, 'R'}, {52, 1, 'N'}}
|
||||
var K_SCR = []key{{54, 1, 'S'}, {55, 1, 'C'}, {56, 1, 'R'}}
|
||||
var K_BRK = []key{{58, 1, 'B'}, {59, 1, 'R'}, {60, 1, 'K'}}
|
||||
var K_LED1 = []key{{66, 1, '-'}}
|
||||
var K_LED2 = []key{{70, 1, '-'}}
|
||||
var K_LED3 = []key{{74, 1, '-'}}
|
||||
var K_TILDE = []key{{1, 4, '`'}}
|
||||
var K_TILDE_SHIFT = []key{{1, 4, '~'}}
|
||||
var K_1 = []key{{4, 4, '1'}}
|
||||
var K_1_SHIFT = []key{{4, 4, '!'}}
|
||||
var K_2 = []key{{7, 4, '2'}}
|
||||
var K_2_SHIFT = []key{{7, 4, '@'}}
|
||||
var K_3 = []key{{10, 4, '3'}}
|
||||
var K_3_SHIFT = []key{{10, 4, '#'}}
|
||||
var K_4 = []key{{13, 4, '4'}}
|
||||
var K_4_SHIFT = []key{{13, 4, '$'}}
|
||||
var K_5 = []key{{16, 4, '5'}}
|
||||
var K_5_SHIFT = []key{{16, 4, '%'}}
|
||||
var K_6 = []key{{19, 4, '6'}}
|
||||
var K_6_SHIFT = []key{{19, 4, '^'}}
|
||||
var K_7 = []key{{22, 4, '7'}}
|
||||
var K_7_SHIFT = []key{{22, 4, '&'}}
|
||||
var K_8 = []key{{25, 4, '8'}}
|
||||
var K_8_SHIFT = []key{{25, 4, '*'}}
|
||||
var K_9 = []key{{28, 4, '9'}}
|
||||
var K_9_SHIFT = []key{{28, 4, '('}}
|
||||
var K_0 = []key{{31, 4, '0'}}
|
||||
var K_0_SHIFT = []key{{31, 4, ')'}}
|
||||
var K_MINUS = []key{{34, 4, '-'}}
|
||||
var K_MINUS_SHIFT = []key{{34, 4, '_'}}
|
||||
var K_EQUALS = []key{{37, 4, '='}}
|
||||
var K_EQUALS_SHIFT = []key{{37, 4, '+'}}
|
||||
var K_BACKSLASH = []key{{40, 4, '\\'}}
|
||||
var K_BACKSLASH_SHIFT = []key{{40, 4, '|'}}
|
||||
var K_BACKSPACE = []key{{44, 4, 0x2190}, {45, 4, 0x2500}, {46, 4, 0x2500}}
|
||||
var K_INS = []key{{50, 4, 'I'}, {51, 4, 'N'}, {52, 4, 'S'}}
|
||||
var K_HOM = []key{{54, 4, 'H'}, {55, 4, 'O'}, {56, 4, 'M'}}
|
||||
var K_PGU = []key{{58, 4, 'P'}, {59, 4, 'G'}, {60, 4, 'U'}}
|
||||
var K_K_NUMLOCK = []key{{65, 4, 'N'}}
|
||||
var K_K_SLASH = []key{{68, 4, '/'}}
|
||||
var K_K_STAR = []key{{71, 4, '*'}}
|
||||
var K_K_MINUS = []key{{74, 4, '-'}}
|
||||
var K_TAB = []key{{1, 6, 'T'}, {2, 6, 'A'}, {3, 6, 'B'}}
|
||||
var K_q = []key{{6, 6, 'q'}}
|
||||
var K_Q = []key{{6, 6, 'Q'}}
|
||||
var K_w = []key{{9, 6, 'w'}}
|
||||
var K_W = []key{{9, 6, 'W'}}
|
||||
var K_e = []key{{12, 6, 'e'}}
|
||||
var K_E = []key{{12, 6, 'E'}}
|
||||
var K_r = []key{{15, 6, 'r'}}
|
||||
var K_R = []key{{15, 6, 'R'}}
|
||||
var K_t = []key{{18, 6, 't'}}
|
||||
var K_T = []key{{18, 6, 'T'}}
|
||||
var K_y = []key{{21, 6, 'y'}}
|
||||
var K_Y = []key{{21, 6, 'Y'}}
|
||||
var K_u = []key{{24, 6, 'u'}}
|
||||
var K_U = []key{{24, 6, 'U'}}
|
||||
var K_i = []key{{27, 6, 'i'}}
|
||||
var K_I = []key{{27, 6, 'I'}}
|
||||
var K_o = []key{{30, 6, 'o'}}
|
||||
var K_O = []key{{30, 6, 'O'}}
|
||||
var K_p = []key{{33, 6, 'p'}}
|
||||
var K_P = []key{{33, 6, 'P'}}
|
||||
var K_LSQB = []key{{36, 6, '['}}
|
||||
var K_LCUB = []key{{36, 6, '{'}}
|
||||
var K_RSQB = []key{{39, 6, ']'}}
|
||||
var K_RCUB = []key{{39, 6, '}'}}
|
||||
var K_ENTER = []key{
|
||||
{43, 6, 0x2591}, {44, 6, 0x2591}, {45, 6, 0x2591}, {46, 6, 0x2591},
|
||||
{43, 7, 0x2591}, {44, 7, 0x2591}, {45, 7, 0x21B5}, {46, 7, 0x2591},
|
||||
{41, 8, 0x2591}, {42, 8, 0x2591}, {43, 8, 0x2591}, {44, 8, 0x2591},
|
||||
{45, 8, 0x2591}, {46, 8, 0x2591},
|
||||
}
|
||||
var K_DEL = []key{{50, 6, 'D'}, {51, 6, 'E'}, {52, 6, 'L'}}
|
||||
var K_END = []key{{54, 6, 'E'}, {55, 6, 'N'}, {56, 6, 'D'}}
|
||||
var K_PGD = []key{{58, 6, 'P'}, {59, 6, 'G'}, {60, 6, 'D'}}
|
||||
var K_K_7 = []key{{65, 6, '7'}}
|
||||
var K_K_8 = []key{{68, 6, '8'}}
|
||||
var K_K_9 = []key{{71, 6, '9'}}
|
||||
var K_K_PLUS = []key{{74, 6, ' '}, {74, 7, '+'}, {74, 8, ' '}}
|
||||
var K_CAPS = []key{{1, 8, 'C'}, {2, 8, 'A'}, {3, 8, 'P'}, {4, 8, 'S'}}
|
||||
var K_a = []key{{7, 8, 'a'}}
|
||||
var K_A = []key{{7, 8, 'A'}}
|
||||
var K_s = []key{{10, 8, 's'}}
|
||||
var K_S = []key{{10, 8, 'S'}}
|
||||
var K_d = []key{{13, 8, 'd'}}
|
||||
var K_D = []key{{13, 8, 'D'}}
|
||||
var K_f = []key{{16, 8, 'f'}}
|
||||
var K_F = []key{{16, 8, 'F'}}
|
||||
var K_g = []key{{19, 8, 'g'}}
|
||||
var K_G = []key{{19, 8, 'G'}}
|
||||
var K_h = []key{{22, 8, 'h'}}
|
||||
var K_H = []key{{22, 8, 'H'}}
|
||||
var K_j = []key{{25, 8, 'j'}}
|
||||
var K_J = []key{{25, 8, 'J'}}
|
||||
var K_k = []key{{28, 8, 'k'}}
|
||||
var K_K = []key{{28, 8, 'K'}}
|
||||
var K_l = []key{{31, 8, 'l'}}
|
||||
var K_L = []key{{31, 8, 'L'}}
|
||||
var K_SEMICOLON = []key{{34, 8, ';'}}
|
||||
var K_PARENTHESIS = []key{{34, 8, ':'}}
|
||||
var K_QUOTE = []key{{37, 8, '\''}}
|
||||
var K_DOUBLEQUOTE = []key{{37, 8, '"'}}
|
||||
var K_K_4 = []key{{65, 8, '4'}}
|
||||
var K_K_5 = []key{{68, 8, '5'}}
|
||||
var K_K_6 = []key{{71, 8, '6'}}
|
||||
var K_LSHIFT = []key{{1, 10, 'S'}, {2, 10, 'H'}, {3, 10, 'I'}, {4, 10, 'F'}, {5, 10, 'T'}}
|
||||
var K_z = []key{{9, 10, 'z'}}
|
||||
var K_Z = []key{{9, 10, 'Z'}}
|
||||
var K_x = []key{{12, 10, 'x'}}
|
||||
var K_X = []key{{12, 10, 'X'}}
|
||||
var K_c = []key{{15, 10, 'c'}}
|
||||
var K_C = []key{{15, 10, 'C'}}
|
||||
var K_v = []key{{18, 10, 'v'}}
|
||||
var K_V = []key{{18, 10, 'V'}}
|
||||
var K_b = []key{{21, 10, 'b'}}
|
||||
var K_B = []key{{21, 10, 'B'}}
|
||||
var K_n = []key{{24, 10, 'n'}}
|
||||
var K_N = []key{{24, 10, 'N'}}
|
||||
var K_m = []key{{27, 10, 'm'}}
|
||||
var K_M = []key{{27, 10, 'M'}}
|
||||
var K_COMMA = []key{{30, 10, ','}}
|
||||
var K_LANB = []key{{30, 10, '<'}}
|
||||
var K_PERIOD = []key{{33, 10, '.'}}
|
||||
var K_RANB = []key{{33, 10, '>'}}
|
||||
var K_SLASH = []key{{36, 10, '/'}}
|
||||
var K_QUESTION = []key{{36, 10, '?'}}
|
||||
var K_RSHIFT = []key{{42, 10, 'S'}, {43, 10, 'H'}, {44, 10, 'I'}, {45, 10, 'F'}, {46, 10, 'T'}}
|
||||
var K_ARROW_UP = []key{{54, 10, '('}, {55, 10, 0x2191}, {56, 10, ')'}}
|
||||
var K_K_1 = []key{{65, 10, '1'}}
|
||||
var K_K_2 = []key{{68, 10, '2'}}
|
||||
var K_K_3 = []key{{71, 10, '3'}}
|
||||
var K_K_ENTER = []key{{74, 10, 0x2591}, {74, 11, 0x2591}, {74, 12, 0x2591}}
|
||||
var K_LCTRL = []key{{1, 12, 'C'}, {2, 12, 'T'}, {3, 12, 'R'}, {4, 12, 'L'}}
|
||||
var K_LWIN = []key{{6, 12, 'W'}, {7, 12, 'I'}, {8, 12, 'N'}}
|
||||
var K_LALT = []key{{10, 12, 'A'}, {11, 12, 'L'}, {12, 12, 'T'}}
|
||||
var K_SPACE = []key{
|
||||
{14, 12, ' '}, {15, 12, ' '}, {16, 12, ' '}, {17, 12, ' '}, {18, 12, ' '},
|
||||
{19, 12, 'S'}, {20, 12, 'P'}, {21, 12, 'A'}, {22, 12, 'C'}, {23, 12, 'E'},
|
||||
{24, 12, ' '}, {25, 12, ' '}, {26, 12, ' '}, {27, 12, ' '}, {28, 12, ' '},
|
||||
}
|
||||
var K_RALT = []key{{30, 12, 'A'}, {31, 12, 'L'}, {32, 12, 'T'}}
|
||||
var K_RWIN = []key{{34, 12, 'W'}, {35, 12, 'I'}, {36, 12, 'N'}}
|
||||
var K_RPROP = []key{{38, 12, 'P'}, {39, 12, 'R'}, {40, 12, 'O'}, {41, 12, 'P'}}
|
||||
var K_RCTRL = []key{{43, 12, 'C'}, {44, 12, 'T'}, {45, 12, 'R'}, {46, 12, 'L'}}
|
||||
var K_ARROW_LEFT = []key{{50, 12, '('}, {51, 12, 0x2190}, {52, 12, ')'}}
|
||||
var K_ARROW_DOWN = []key{{54, 12, '('}, {55, 12, 0x2193}, {56, 12, ')'}}
|
||||
var K_ARROW_RIGHT = []key{{58, 12, '('}, {59, 12, 0x2192}, {60, 12, ')'}}
|
||||
var K_K_0 = []key{{65, 12, ' '}, {66, 12, '0'}, {67, 12, ' '}, {68, 12, ' '}}
|
||||
var K_K_PERIOD = []key{{71, 12, '.'}}
|
||||
|
||||
type combo struct {
|
||||
keys [][]key
|
||||
}
|
||||
|
||||
var combos = []combo{
|
||||
{[][]key{K_TILDE, K_2, K_SPACE, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_A, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_B, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_C, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_D, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_E, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_F, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_G, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_H, K_BACKSPACE, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_I, K_TAB, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_J, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_K, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_L, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_M, K_ENTER, K_K_ENTER, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_N, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_O, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_P, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_Q, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_R, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_S, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_T, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_U, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_V, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_W, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_X, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_Y, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_Z, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_LSQB, K_ESC, K_3, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_4, K_BACKSLASH, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_RSQB, K_5, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_6, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_7, K_SLASH, K_MINUS_SHIFT, K_LCTRL, K_RCTRL}},
|
||||
{[][]key{K_SPACE}},
|
||||
{[][]key{K_1_SHIFT, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_DOUBLEQUOTE, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_3_SHIFT, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_4_SHIFT, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_5_SHIFT, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_7_SHIFT, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_QUOTE}},
|
||||
{[][]key{K_9_SHIFT, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_0_SHIFT, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_8_SHIFT, K_K_STAR, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_EQUALS_SHIFT, K_K_PLUS, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_COMMA}},
|
||||
{[][]key{K_MINUS, K_K_MINUS}},
|
||||
{[][]key{K_PERIOD, K_K_PERIOD}},
|
||||
{[][]key{K_SLASH, K_K_SLASH}},
|
||||
{[][]key{K_0, K_K_0}},
|
||||
{[][]key{K_1, K_K_1}},
|
||||
{[][]key{K_2, K_K_2}},
|
||||
{[][]key{K_3, K_K_3}},
|
||||
{[][]key{K_4, K_K_4}},
|
||||
{[][]key{K_5, K_K_5}},
|
||||
{[][]key{K_6, K_K_6}},
|
||||
{[][]key{K_7, K_K_7}},
|
||||
{[][]key{K_8, K_K_8}},
|
||||
{[][]key{K_9, K_K_9}},
|
||||
{[][]key{K_PARENTHESIS, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_SEMICOLON}},
|
||||
{[][]key{K_LANB, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_EQUALS}},
|
||||
{[][]key{K_RANB, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_QUESTION, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_2_SHIFT, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_A, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_B, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_C, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_D, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_E, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_F, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_G, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_H, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_I, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_J, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_K, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_L, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_M, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_N, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_O, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_P, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_Q, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_R, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_S, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_T, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_U, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_V, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_W, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_X, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_Y, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_Z, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_LSQB}},
|
||||
{[][]key{K_BACKSLASH}},
|
||||
{[][]key{K_RSQB}},
|
||||
{[][]key{K_6_SHIFT, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_MINUS_SHIFT, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_TILDE}},
|
||||
{[][]key{K_a}},
|
||||
{[][]key{K_b}},
|
||||
{[][]key{K_c}},
|
||||
{[][]key{K_d}},
|
||||
{[][]key{K_e}},
|
||||
{[][]key{K_f}},
|
||||
{[][]key{K_g}},
|
||||
{[][]key{K_h}},
|
||||
{[][]key{K_i}},
|
||||
{[][]key{K_j}},
|
||||
{[][]key{K_k}},
|
||||
{[][]key{K_l}},
|
||||
{[][]key{K_m}},
|
||||
{[][]key{K_n}},
|
||||
{[][]key{K_o}},
|
||||
{[][]key{K_p}},
|
||||
{[][]key{K_q}},
|
||||
{[][]key{K_r}},
|
||||
{[][]key{K_s}},
|
||||
{[][]key{K_t}},
|
||||
{[][]key{K_u}},
|
||||
{[][]key{K_v}},
|
||||
{[][]key{K_w}},
|
||||
{[][]key{K_x}},
|
||||
{[][]key{K_y}},
|
||||
{[][]key{K_z}},
|
||||
{[][]key{K_LCUB, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_BACKSLASH_SHIFT, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_RCUB, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_TILDE_SHIFT, K_LSHIFT, K_RSHIFT}},
|
||||
{[][]key{K_8, K_BACKSPACE, K_LCTRL, K_RCTRL}},
|
||||
}
|
||||
|
||||
var func_combos = []combo{
|
||||
{[][]key{K_F1}},
|
||||
{[][]key{K_F2}},
|
||||
{[][]key{K_F3}},
|
||||
{[][]key{K_F4}},
|
||||
{[][]key{K_F5}},
|
||||
{[][]key{K_F6}},
|
||||
{[][]key{K_F7}},
|
||||
{[][]key{K_F8}},
|
||||
{[][]key{K_F9}},
|
||||
{[][]key{K_F10}},
|
||||
{[][]key{K_F11}},
|
||||
{[][]key{K_F12}},
|
||||
{[][]key{K_INS}},
|
||||
{[][]key{K_DEL}},
|
||||
{[][]key{K_HOM}},
|
||||
{[][]key{K_END}},
|
||||
{[][]key{K_PGU}},
|
||||
{[][]key{K_PGD}},
|
||||
{[][]key{K_ARROW_UP}},
|
||||
{[][]key{K_ARROW_DOWN}},
|
||||
{[][]key{K_ARROW_LEFT}},
|
||||
{[][]key{K_ARROW_RIGHT}},
|
||||
}
|
||||
|
||||
func print_tb(x, y int, fg, bg termbox.Attribute, msg string) {
|
||||
for _, c := range msg {
|
||||
termbox.SetCell(x, y, c, fg, bg)
|
||||
x++
|
||||
}
|
||||
}
|
||||
|
||||
func printf_tb(x, y int, fg, bg termbox.Attribute, format string, args ...interface{}) {
|
||||
s := fmt.Sprintf(format, args...)
|
||||
print_tb(x, y, fg, bg, s)
|
||||
}
|
||||
|
||||
func draw_key(k []key, fg, bg termbox.Attribute) {
|
||||
for _, k := range k {
|
||||
termbox.SetCell(k.x+2, k.y+4, k.ch, fg, bg)
|
||||
}
|
||||
}
|
||||
|
||||
func draw_keyboard() {
|
||||
termbox.SetCell(0, 0, 0x250C, termbox.ColorWhite, termbox.ColorBlack)
|
||||
termbox.SetCell(79, 0, 0x2510, termbox.ColorWhite, termbox.ColorBlack)
|
||||
termbox.SetCell(0, 23, 0x2514, termbox.ColorWhite, termbox.ColorBlack)
|
||||
termbox.SetCell(79, 23, 0x2518, termbox.ColorWhite, termbox.ColorBlack)
|
||||
|
||||
for i := 1; i < 79; i++ {
|
||||
termbox.SetCell(i, 0, 0x2500, termbox.ColorWhite, termbox.ColorBlack)
|
||||
termbox.SetCell(i, 23, 0x2500, termbox.ColorWhite, termbox.ColorBlack)
|
||||
termbox.SetCell(i, 17, 0x2500, termbox.ColorWhite, termbox.ColorBlack)
|
||||
termbox.SetCell(i, 4, 0x2500, termbox.ColorWhite, termbox.ColorBlack)
|
||||
}
|
||||
for i := 1; i < 23; i++ {
|
||||
termbox.SetCell(0, i, 0x2502, termbox.ColorWhite, termbox.ColorBlack)
|
||||
termbox.SetCell(79, i, 0x2502, termbox.ColorWhite, termbox.ColorBlack)
|
||||
}
|
||||
termbox.SetCell(0, 17, 0x251C, termbox.ColorWhite, termbox.ColorBlack)
|
||||
termbox.SetCell(79, 17, 0x2524, termbox.ColorWhite, termbox.ColorBlack)
|
||||
termbox.SetCell(0, 4, 0x251C, termbox.ColorWhite, termbox.ColorBlack)
|
||||
termbox.SetCell(79, 4, 0x2524, termbox.ColorWhite, termbox.ColorBlack)
|
||||
for i := 5; i < 17; i++ {
|
||||
termbox.SetCell(1, i, 0x2588, termbox.ColorYellow, termbox.ColorYellow)
|
||||
termbox.SetCell(78, i, 0x2588, termbox.ColorYellow, termbox.ColorYellow)
|
||||
}
|
||||
|
||||
draw_key(K_ESC, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_F1, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_F2, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_F3, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_F4, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_F5, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_F6, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_F7, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_F8, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_F9, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_F10, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_F11, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_F12, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_PRN, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_SCR, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_BRK, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_LED1, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_LED2, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_LED3, termbox.ColorWhite, termbox.ColorBlue)
|
||||
|
||||
draw_key(K_TILDE, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_1, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_2, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_3, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_4, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_5, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_6, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_7, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_8, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_9, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_0, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_MINUS, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_EQUALS, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_BACKSLASH, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_BACKSPACE, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_INS, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_HOM, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_PGU, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_NUMLOCK, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_SLASH, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_STAR, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_MINUS, termbox.ColorWhite, termbox.ColorBlue)
|
||||
|
||||
draw_key(K_TAB, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_q, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_w, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_e, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_r, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_t, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_y, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_u, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_i, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_o, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_p, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_LSQB, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_RSQB, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_ENTER, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_DEL, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_END, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_PGD, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_7, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_8, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_9, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_PLUS, termbox.ColorWhite, termbox.ColorBlue)
|
||||
|
||||
draw_key(K_CAPS, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_a, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_s, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_d, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_f, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_g, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_h, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_j, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_k, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_l, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_SEMICOLON, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_QUOTE, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_4, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_5, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_6, termbox.ColorWhite, termbox.ColorBlue)
|
||||
|
||||
draw_key(K_LSHIFT, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_z, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_x, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_c, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_v, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_b, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_n, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_m, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_COMMA, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_PERIOD, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_SLASH, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_RSHIFT, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_ARROW_UP, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_1, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_2, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_3, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_ENTER, termbox.ColorWhite, termbox.ColorBlue)
|
||||
|
||||
draw_key(K_LCTRL, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_LWIN, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_LALT, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_SPACE, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_RCTRL, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_RPROP, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_RWIN, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_RALT, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_ARROW_LEFT, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_ARROW_DOWN, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_ARROW_RIGHT, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_0, termbox.ColorWhite, termbox.ColorBlue)
|
||||
draw_key(K_K_PERIOD, termbox.ColorWhite, termbox.ColorBlue)
|
||||
|
||||
printf_tb(33, 1, termbox.ColorMagenta|termbox.AttrBold, termbox.ColorBlack, "Keyboard demo!")
|
||||
printf_tb(21, 2, termbox.ColorMagenta, termbox.ColorBlack, "(press CTRL+X and then CTRL+Q to exit)")
|
||||
printf_tb(15, 3, termbox.ColorMagenta, termbox.ColorBlack, "(press CTRL+X and then CTRL+C to change input mode)")
|
||||
|
||||
inputmode := termbox.SetInputMode(termbox.InputCurrent)
|
||||
inputmode_str := ""
|
||||
switch {
|
||||
case inputmode&termbox.InputEsc != 0:
|
||||
inputmode_str = "termbox.InputEsc"
|
||||
case inputmode&termbox.InputAlt != 0:
|
||||
inputmode_str = "termbox.InputAlt"
|
||||
}
|
||||
|
||||
if inputmode&termbox.InputMouse != 0 {
|
||||
inputmode_str += " | termbox.InputMouse"
|
||||
}
|
||||
printf_tb(3, 18, termbox.ColorWhite, termbox.ColorBlack, "Input mode: %s", inputmode_str)
|
||||
}
|
||||
|
||||
var fcmap = []string{
|
||||
"CTRL+2, CTRL+~",
|
||||
"CTRL+A",
|
||||
"CTRL+B",
|
||||
"CTRL+C",
|
||||
"CTRL+D",
|
||||
"CTRL+E",
|
||||
"CTRL+F",
|
||||
"CTRL+G",
|
||||
"CTRL+H, BACKSPACE",
|
||||
"CTRL+I, TAB",
|
||||
"CTRL+J",
|
||||
"CTRL+K",
|
||||
"CTRL+L",
|
||||
"CTRL+M, ENTER",
|
||||
"CTRL+N",
|
||||
"CTRL+O",
|
||||
"CTRL+P",
|
||||
"CTRL+Q",
|
||||
"CTRL+R",
|
||||
"CTRL+S",
|
||||
"CTRL+T",
|
||||
"CTRL+U",
|
||||
"CTRL+V",
|
||||
"CTRL+W",
|
||||
"CTRL+X",
|
||||
"CTRL+Y",
|
||||
"CTRL+Z",
|
||||
"CTRL+3, ESC, CTRL+[",
|
||||
"CTRL+4, CTRL+\\",
|
||||
"CTRL+5, CTRL+]",
|
||||
"CTRL+6",
|
||||
"CTRL+7, CTRL+/, CTRL+_",
|
||||
"SPACE",
|
||||
}
|
||||
|
||||
var fkmap = []string{
|
||||
"F1",
|
||||
"F2",
|
||||
"F3",
|
||||
"F4",
|
||||
"F5",
|
||||
"F6",
|
||||
"F7",
|
||||
"F8",
|
||||
"F9",
|
||||
"F10",
|
||||
"F11",
|
||||
"F12",
|
||||
"INSERT",
|
||||
"DELETE",
|
||||
"HOME",
|
||||
"END",
|
||||
"PGUP",
|
||||
"PGDN",
|
||||
"ARROW UP",
|
||||
"ARROW DOWN",
|
||||
"ARROW LEFT",
|
||||
"ARROW RIGHT",
|
||||
}
|
||||
|
||||
func funckeymap(k termbox.Key) string {
|
||||
if k == termbox.KeyCtrl8 {
|
||||
return "CTRL+8, BACKSPACE 2" /* 0x7F */
|
||||
} else if k >= termbox.KeyArrowRight && k <= 0xFFFF {
|
||||
return fkmap[0xFFFF-k]
|
||||
} else if k <= termbox.KeySpace {
|
||||
return fcmap[k]
|
||||
}
|
||||
return "UNKNOWN"
|
||||
}
|
||||
|
||||
func pretty_print_press(ev *termbox.Event) {
|
||||
printf_tb(3, 19, termbox.ColorWhite, termbox.ColorBlack, "Key: ")
|
||||
printf_tb(8, 19, termbox.ColorYellow, termbox.ColorBlack, "decimal: %d", ev.Key)
|
||||
printf_tb(8, 20, termbox.ColorGreen, termbox.ColorBlack, "hex: 0x%X", ev.Key)
|
||||
printf_tb(8, 21, termbox.ColorCyan, termbox.ColorBlack, "octal: 0%o", ev.Key)
|
||||
printf_tb(8, 22, termbox.ColorRed, termbox.ColorBlack, "string: %s", funckeymap(ev.Key))
|
||||
|
||||
printf_tb(54, 19, termbox.ColorWhite, termbox.ColorBlack, "Char: ")
|
||||
printf_tb(60, 19, termbox.ColorYellow, termbox.ColorBlack, "decimal: %d", ev.Ch)
|
||||
printf_tb(60, 20, termbox.ColorGreen, termbox.ColorBlack, "hex: 0x%X", ev.Ch)
|
||||
printf_tb(60, 21, termbox.ColorCyan, termbox.ColorBlack, "octal: 0%o", ev.Ch)
|
||||
printf_tb(60, 22, termbox.ColorRed, termbox.ColorBlack, "string: %s", string(ev.Ch))
|
||||
|
||||
modifier := "none"
|
||||
if ev.Mod != 0 {
|
||||
modifier = "termbox.ModAlt"
|
||||
}
|
||||
printf_tb(54, 18, termbox.ColorWhite, termbox.ColorBlack, "Modifier: %s", modifier)
|
||||
}
|
||||
|
||||
func pretty_print_resize(ev *termbox.Event) {
|
||||
printf_tb(3, 19, termbox.ColorWhite, termbox.ColorBlack, "Resize event: %d x %d", ev.Width, ev.Height)
|
||||
}
|
||||
|
||||
var counter = 0
|
||||
|
||||
func pretty_print_mouse(ev *termbox.Event) {
|
||||
printf_tb(3, 19, termbox.ColorWhite, termbox.ColorBlack, "Mouse event: %d x %d", ev.MouseX, ev.MouseY)
|
||||
button := ""
|
||||
switch ev.Key {
|
||||
case termbox.MouseLeft:
|
||||
button = "MouseLeft: %d"
|
||||
case termbox.MouseMiddle:
|
||||
button = "MouseMiddle: %d"
|
||||
case termbox.MouseRight:
|
||||
button = "MouseRight: %d"
|
||||
case termbox.MouseWheelUp:
|
||||
button = "MouseWheelUp: %d"
|
||||
case termbox.MouseWheelDown:
|
||||
button = "MouseWheelDown: %d"
|
||||
case termbox.MouseRelease:
|
||||
button = "MouseRelease: %d"
|
||||
}
|
||||
if ev.Mod&termbox.ModMotion != 0 {
|
||||
button += "*"
|
||||
}
|
||||
counter++
|
||||
printf_tb(43, 19, termbox.ColorWhite, termbox.ColorBlack, "Key: ")
|
||||
printf_tb(48, 19, termbox.ColorYellow, termbox.ColorBlack, button, counter)
|
||||
}
|
||||
|
||||
func dispatch_press(ev *termbox.Event) {
|
||||
if ev.Mod&termbox.ModAlt != 0 {
|
||||
draw_key(K_LALT, termbox.ColorWhite, termbox.ColorRed)
|
||||
draw_key(K_RALT, termbox.ColorWhite, termbox.ColorRed)
|
||||
}
|
||||
|
||||
var k *combo
|
||||
if ev.Key >= termbox.KeyArrowRight {
|
||||
k = &func_combos[0xFFFF-ev.Key]
|
||||
} else if ev.Ch < 128 {
|
||||
if ev.Ch == 0 && ev.Key < 128 {
|
||||
k = &combos[ev.Key]
|
||||
} else {
|
||||
k = &combos[ev.Ch]
|
||||
}
|
||||
}
|
||||
if k == nil {
|
||||
return
|
||||
}
|
||||
|
||||
keys := k.keys
|
||||
for _, k := range keys {
|
||||
draw_key(k, termbox.ColorWhite, termbox.ColorRed)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := termbox.Init()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer termbox.Close()
|
||||
|
||||
termbox.SetInputMode(termbox.InputEsc | termbox.InputMouse)
|
||||
|
||||
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
|
||||
draw_keyboard()
|
||||
termbox.Flush()
|
||||
inputmode := 0
|
||||
ctrlxpressed := false
|
||||
loop:
|
||||
for {
|
||||
switch ev := termbox.PollEvent(); ev.Type {
|
||||
case termbox.EventKey:
|
||||
if ev.Key == termbox.KeyCtrlS && ctrlxpressed {
|
||||
termbox.Sync()
|
||||
}
|
||||
if ev.Key == termbox.KeyCtrlQ && ctrlxpressed {
|
||||
break loop
|
||||
}
|
||||
if ev.Key == termbox.KeyCtrlC && ctrlxpressed {
|
||||
chmap := []termbox.InputMode{
|
||||
termbox.InputEsc | termbox.InputMouse,
|
||||
termbox.InputAlt | termbox.InputMouse,
|
||||
termbox.InputEsc,
|
||||
termbox.InputAlt,
|
||||
}
|
||||
inputmode++
|
||||
if inputmode >= len(chmap) {
|
||||
inputmode = 0
|
||||
}
|
||||
termbox.SetInputMode(chmap[inputmode])
|
||||
}
|
||||
if ev.Key == termbox.KeyCtrlX {
|
||||
ctrlxpressed = true
|
||||
} else {
|
||||
ctrlxpressed = false
|
||||
}
|
||||
|
||||
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
|
||||
draw_keyboard()
|
||||
dispatch_press(&ev)
|
||||
pretty_print_press(&ev)
|
||||
termbox.Flush()
|
||||
case termbox.EventResize:
|
||||
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
|
||||
draw_keyboard()
|
||||
pretty_print_resize(&ev)
|
||||
termbox.Flush()
|
||||
case termbox.EventMouse:
|
||||
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
|
||||
draw_keyboard()
|
||||
pretty_print_mouse(&ev)
|
||||
termbox.Flush()
|
||||
case termbox.EventError:
|
||||
panic(ev.Err)
|
||||
}
|
||||
}
|
||||
}
|
228
vendor/github.com/nsf/termbox-go/_demos/output.go
generated
vendored
Normal file
228
vendor/github.com/nsf/termbox-go/_demos/output.go
generated
vendored
Normal file
@ -0,0 +1,228 @@
|
||||
package main
|
||||
|
||||
import "github.com/mattn/go-runewidth"
|
||||
import "github.com/nsf/termbox-go"
|
||||
|
||||
const chars = "nnnnnnnnnbbbbbbbbbuuuuuuuuuBBBBBBBBB"
|
||||
|
||||
var output_mode = termbox.OutputNormal
|
||||
|
||||
func next_char(current int) int {
|
||||
current++
|
||||
if current >= len(chars) {
|
||||
return 0
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
||||
func print_combinations_table(sx, sy int, attrs []termbox.Attribute) {
|
||||
var bg termbox.Attribute
|
||||
current_char := 0
|
||||
y := sy
|
||||
|
||||
all_attrs := []termbox.Attribute{
|
||||
0,
|
||||
termbox.AttrBold,
|
||||
termbox.AttrUnderline,
|
||||
termbox.AttrBold | termbox.AttrUnderline,
|
||||
}
|
||||
|
||||
draw_line := func() {
|
||||
x := sx
|
||||
for _, a := range all_attrs {
|
||||
for c := termbox.ColorDefault; c <= termbox.ColorWhite; c++ {
|
||||
fg := a | c
|
||||
termbox.SetCell(x, y, rune(chars[current_char]), fg, bg)
|
||||
current_char = next_char(current_char)
|
||||
x++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, a := range attrs {
|
||||
for c := termbox.ColorDefault; c <= termbox.ColorWhite; c++ {
|
||||
bg = a | c
|
||||
draw_line()
|
||||
y++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func print_wide(x, y int, s string) {
|
||||
red := false
|
||||
for _, r := range s {
|
||||
c := termbox.ColorDefault
|
||||
if red {
|
||||
c = termbox.ColorRed
|
||||
}
|
||||
termbox.SetCell(x, y, r, termbox.ColorDefault, c)
|
||||
w := runewidth.RuneWidth(r)
|
||||
if w == 0 || (w == 2 && runewidth.IsAmbiguousWidth(r)) {
|
||||
w = 1
|
||||
}
|
||||
x += w
|
||||
|
||||
red = !red
|
||||
}
|
||||
}
|
||||
|
||||
const hello_world = "こんにちは世界"
|
||||
|
||||
func draw_all() {
|
||||
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
|
||||
|
||||
switch output_mode {
|
||||
|
||||
case termbox.OutputNormal:
|
||||
print_combinations_table(1, 1, []termbox.Attribute{
|
||||
0,
|
||||
termbox.AttrBold,
|
||||
})
|
||||
print_combinations_table(2+len(chars), 1, []termbox.Attribute{
|
||||
termbox.AttrReverse,
|
||||
})
|
||||
print_wide(2+len(chars), 11, hello_world)
|
||||
|
||||
case termbox.OutputGrayscale:
|
||||
for y := 0; y < 26; y++ {
|
||||
for x := 0; x < 26; x++ {
|
||||
termbox.SetCell(x, y, 'n',
|
||||
termbox.Attribute(x+1),
|
||||
termbox.Attribute(y+1))
|
||||
termbox.SetCell(x+27, y, 'b',
|
||||
termbox.Attribute(x+1)|termbox.AttrBold,
|
||||
termbox.Attribute(26-y))
|
||||
termbox.SetCell(x+54, y, 'u',
|
||||
termbox.Attribute(x+1)|termbox.AttrUnderline,
|
||||
termbox.Attribute(y+1))
|
||||
}
|
||||
termbox.SetCell(82, y, 'd',
|
||||
termbox.Attribute(y+1),
|
||||
termbox.ColorDefault)
|
||||
termbox.SetCell(83, y, 'd',
|
||||
termbox.ColorDefault,
|
||||
termbox.Attribute(26-y))
|
||||
}
|
||||
|
||||
case termbox.Output216:
|
||||
for r := 0; r < 6; r++ {
|
||||
for g := 0; g < 6; g++ {
|
||||
for b := 0; b < 6; b++ {
|
||||
y := r
|
||||
x := g + 6*b
|
||||
c1 := termbox.Attribute(1 + r*36 + g*6 + b)
|
||||
bg := termbox.Attribute(1 + g*36 + b*6 + r)
|
||||
c2 := termbox.Attribute(1 + b*36 + r*6 + g)
|
||||
bc1 := c1 | termbox.AttrBold
|
||||
uc1 := c1 | termbox.AttrUnderline
|
||||
bc2 := c2 | termbox.AttrBold
|
||||
uc2 := c2 | termbox.AttrUnderline
|
||||
termbox.SetCell(x, y, 'n', c1, bg)
|
||||
termbox.SetCell(x, y+6, 'b', bc1, bg)
|
||||
termbox.SetCell(x, y+12, 'u', uc1, bg)
|
||||
termbox.SetCell(x, y+18, 'B', bc1|uc1, bg)
|
||||
termbox.SetCell(x+37, y, 'n', c2, bg)
|
||||
termbox.SetCell(x+37, y+6, 'b', bc2, bg)
|
||||
termbox.SetCell(x+37, y+12, 'u', uc2, bg)
|
||||
termbox.SetCell(x+37, y+18, 'B', bc2|uc2, bg)
|
||||
}
|
||||
c1 := termbox.Attribute(1 + g*6 + r*36)
|
||||
c2 := termbox.Attribute(6 + g*6 + r*36)
|
||||
termbox.SetCell(74+g, r, 'd', c1, termbox.ColorDefault)
|
||||
termbox.SetCell(74+g, r+6, 'd', c2, termbox.ColorDefault)
|
||||
termbox.SetCell(74+g, r+12, 'd', termbox.ColorDefault, c1)
|
||||
termbox.SetCell(74+g, r+18, 'd', termbox.ColorDefault, c2)
|
||||
}
|
||||
}
|
||||
|
||||
case termbox.Output256:
|
||||
for y := 0; y < 4; y++ {
|
||||
for x := 0; x < 8; x++ {
|
||||
for z := 0; z < 8; z++ {
|
||||
bg := termbox.Attribute(1 + y*64 + x*8 + z)
|
||||
c1 := termbox.Attribute(256 - y*64 - x*8 - z)
|
||||
c2 := termbox.Attribute(1 + y*64 + z*8 + x)
|
||||
c3 := termbox.Attribute(256 - y*64 - z*8 - x)
|
||||
c4 := termbox.Attribute(1 + y*64 + x*4 + z*4)
|
||||
bold := c2 | termbox.AttrBold
|
||||
under := c3 | termbox.AttrUnderline
|
||||
both := c1 | termbox.AttrBold | termbox.AttrUnderline
|
||||
termbox.SetCell(z+8*x, y, ' ', 0, bg)
|
||||
termbox.SetCell(z+8*x, y+5, 'n', c4, bg)
|
||||
termbox.SetCell(z+8*x, y+10, 'b', bold, bg)
|
||||
termbox.SetCell(z+8*x, y+15, 'u', under, bg)
|
||||
termbox.SetCell(z+8*x, y+20, 'B', both, bg)
|
||||
}
|
||||
}
|
||||
}
|
||||
for x := 0; x < 12; x++ {
|
||||
for y := 0; y < 2; y++ {
|
||||
c1 := termbox.Attribute(233 + y*12 + x)
|
||||
termbox.SetCell(66+x, y, 'd', c1, termbox.ColorDefault)
|
||||
termbox.SetCell(66+x, 2+y, 'd', termbox.ColorDefault, c1)
|
||||
}
|
||||
}
|
||||
for x := 0; x < 6; x++ {
|
||||
for y := 0; y < 6; y++ {
|
||||
c1 := termbox.Attribute(17 + x*6 + y*36)
|
||||
c2 := termbox.Attribute(17 + 5 + x*6 + y*36)
|
||||
termbox.SetCell(66+x, 6+y, 'd', c1, termbox.ColorDefault)
|
||||
termbox.SetCell(66+x, 12+y, 'd', c2, termbox.ColorDefault)
|
||||
termbox.SetCell(72+x, 6+y, 'd', termbox.ColorDefault, c1)
|
||||
termbox.SetCell(72+x, 12+y, 'd', termbox.ColorDefault, c2)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
termbox.Flush()
|
||||
}
|
||||
|
||||
var available_modes = []termbox.OutputMode{
|
||||
termbox.OutputNormal,
|
||||
termbox.OutputGrayscale,
|
||||
termbox.Output216,
|
||||
termbox.Output256,
|
||||
}
|
||||
|
||||
var output_mode_index = 0
|
||||
|
||||
func switch_output_mode(direction int) {
|
||||
output_mode_index += direction
|
||||
if output_mode_index < 0 {
|
||||
output_mode_index = len(available_modes) - 1
|
||||
} else if output_mode_index >= len(available_modes) {
|
||||
output_mode_index = 0
|
||||
}
|
||||
output_mode = termbox.SetOutputMode(available_modes[output_mode_index])
|
||||
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
|
||||
termbox.Sync()
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := termbox.Init()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer termbox.Close()
|
||||
|
||||
draw_all()
|
||||
loop:
|
||||
for {
|
||||
switch ev := termbox.PollEvent(); ev.Type {
|
||||
case termbox.EventKey:
|
||||
switch ev.Key {
|
||||
case termbox.KeyEsc:
|
||||
break loop
|
||||
case termbox.KeyArrowUp, termbox.KeyArrowRight:
|
||||
switch_output_mode(1)
|
||||
draw_all()
|
||||
case termbox.KeyArrowDown, termbox.KeyArrowLeft:
|
||||
switch_output_mode(-1)
|
||||
draw_all()
|
||||
}
|
||||
case termbox.EventResize:
|
||||
draw_all()
|
||||
}
|
||||
}
|
||||
}
|
105
vendor/github.com/nsf/termbox-go/_demos/paint.go
generated
vendored
Normal file
105
vendor/github.com/nsf/termbox-go/_demos/paint.go
generated
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
var curCol = 0
|
||||
var curRune = 0
|
||||
var backbuf []termbox.Cell
|
||||
var bbw, bbh int
|
||||
|
||||
var runes = []rune{' ', '░', '▒', '▓', '█'}
|
||||
var colors = []termbox.Attribute{
|
||||
termbox.ColorBlack,
|
||||
termbox.ColorRed,
|
||||
termbox.ColorGreen,
|
||||
termbox.ColorYellow,
|
||||
termbox.ColorBlue,
|
||||
termbox.ColorMagenta,
|
||||
termbox.ColorCyan,
|
||||
termbox.ColorWhite,
|
||||
}
|
||||
|
||||
type attrFunc func(int) (rune, termbox.Attribute, termbox.Attribute)
|
||||
|
||||
func updateAndDrawButtons(current *int, x, y int, mx, my int, n int, attrf attrFunc) {
|
||||
lx, ly := x, y
|
||||
for i := 0; i < n; i++ {
|
||||
if lx <= mx && mx <= lx+3 && ly <= my && my <= ly+1 {
|
||||
*current = i
|
||||
}
|
||||
r, fg, bg := attrf(i)
|
||||
termbox.SetCell(lx+0, ly+0, r, fg, bg)
|
||||
termbox.SetCell(lx+1, ly+0, r, fg, bg)
|
||||
termbox.SetCell(lx+2, ly+0, r, fg, bg)
|
||||
termbox.SetCell(lx+3, ly+0, r, fg, bg)
|
||||
termbox.SetCell(lx+0, ly+1, r, fg, bg)
|
||||
termbox.SetCell(lx+1, ly+1, r, fg, bg)
|
||||
termbox.SetCell(lx+2, ly+1, r, fg, bg)
|
||||
termbox.SetCell(lx+3, ly+1, r, fg, bg)
|
||||
lx += 4
|
||||
}
|
||||
lx, ly = x, y
|
||||
for i := 0; i < n; i++ {
|
||||
if *current == i {
|
||||
fg := termbox.ColorRed | termbox.AttrBold
|
||||
bg := termbox.ColorDefault
|
||||
termbox.SetCell(lx+0, ly+2, '^', fg, bg)
|
||||
termbox.SetCell(lx+1, ly+2, '^', fg, bg)
|
||||
termbox.SetCell(lx+2, ly+2, '^', fg, bg)
|
||||
termbox.SetCell(lx+3, ly+2, '^', fg, bg)
|
||||
}
|
||||
lx += 4
|
||||
}
|
||||
}
|
||||
|
||||
func update_and_redraw_all(mx, my int) {
|
||||
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
|
||||
if mx != -1 && my != -1 {
|
||||
backbuf[bbw*my+mx] = termbox.Cell{Ch: runes[curRune], Fg: colors[curCol]}
|
||||
}
|
||||
copy(termbox.CellBuffer(), backbuf)
|
||||
_, h := termbox.Size()
|
||||
updateAndDrawButtons(&curRune, 0, 0, mx, my, len(runes), func(i int) (rune, termbox.Attribute, termbox.Attribute) {
|
||||
return runes[i], termbox.ColorDefault, termbox.ColorDefault
|
||||
})
|
||||
updateAndDrawButtons(&curCol, 0, h-3, mx, my, len(colors), func(i int) (rune, termbox.Attribute, termbox.Attribute) {
|
||||
return ' ', termbox.ColorDefault, colors[i]
|
||||
})
|
||||
termbox.Flush()
|
||||
}
|
||||
|
||||
func reallocBackBuffer(w, h int) {
|
||||
bbw, bbh = w, h
|
||||
backbuf = make([]termbox.Cell, w*h)
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := termbox.Init()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer termbox.Close()
|
||||
termbox.SetInputMode(termbox.InputEsc | termbox.InputMouse)
|
||||
reallocBackBuffer(termbox.Size())
|
||||
update_and_redraw_all(-1, -1)
|
||||
|
||||
mainloop:
|
||||
for {
|
||||
mx, my := -1, -1
|
||||
switch ev := termbox.PollEvent(); ev.Type {
|
||||
case termbox.EventKey:
|
||||
if ev.Key == termbox.KeyEsc {
|
||||
break mainloop
|
||||
}
|
||||
case termbox.EventMouse:
|
||||
if ev.Key == termbox.MouseLeft {
|
||||
mx, my = ev.MouseX, ev.MouseY
|
||||
}
|
||||
case termbox.EventResize:
|
||||
reallocBackBuffer(ev.Width, ev.Height)
|
||||
}
|
||||
update_and_redraw_all(mx, my)
|
||||
}
|
||||
}
|
46
vendor/github.com/nsf/termbox-go/_demos/random_output.go
generated
vendored
Normal file
46
vendor/github.com/nsf/termbox-go/_demos/random_output.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
package main
|
||||
|
||||
import "github.com/nsf/termbox-go"
|
||||
import "math/rand"
|
||||
import "time"
|
||||
|
||||
func draw() {
|
||||
w, h := termbox.Size()
|
||||
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
|
||||
for y := 0; y < h; y++ {
|
||||
for x := 0; x < w; x++ {
|
||||
termbox.SetCell(x, y, ' ', termbox.ColorDefault,
|
||||
termbox.Attribute(rand.Int()%8)+1)
|
||||
}
|
||||
}
|
||||
termbox.Flush()
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := termbox.Init()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer termbox.Close()
|
||||
|
||||
event_queue := make(chan termbox.Event)
|
||||
go func() {
|
||||
for {
|
||||
event_queue <- termbox.PollEvent()
|
||||
}
|
||||
}()
|
||||
|
||||
draw()
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case ev := <-event_queue:
|
||||
if ev.Type == termbox.EventKey && ev.Key == termbox.KeyEsc {
|
||||
break loop
|
||||
}
|
||||
default:
|
||||
draw()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}
|
109
vendor/github.com/nsf/termbox-go/_demos/raw_input.go
generated
vendored
Normal file
109
vendor/github.com/nsf/termbox-go/_demos/raw_input.go
generated
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/nsf/termbox-go"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func tbprint(x, y int, fg, bg termbox.Attribute, msg string) {
|
||||
for _, c := range msg {
|
||||
termbox.SetCell(x, y, c, fg, bg)
|
||||
x++
|
||||
}
|
||||
}
|
||||
|
||||
var current string
|
||||
var curev termbox.Event
|
||||
|
||||
func mouse_button_str(k termbox.Key) string {
|
||||
switch k {
|
||||
case termbox.MouseLeft:
|
||||
return "MouseLeft"
|
||||
case termbox.MouseMiddle:
|
||||
return "MouseMiddle"
|
||||
case termbox.MouseRight:
|
||||
return "MouseRight"
|
||||
case termbox.MouseRelease:
|
||||
return "MouseRelease"
|
||||
case termbox.MouseWheelUp:
|
||||
return "MouseWheelUp"
|
||||
case termbox.MouseWheelDown:
|
||||
return "MouseWheelDown"
|
||||
}
|
||||
return "Key"
|
||||
}
|
||||
|
||||
func mod_str(m termbox.Modifier) string {
|
||||
var out []string
|
||||
if m&termbox.ModAlt != 0 {
|
||||
out = append(out, "ModAlt")
|
||||
}
|
||||
if m&termbox.ModMotion != 0 {
|
||||
out = append(out, "ModMotion")
|
||||
}
|
||||
return strings.Join(out, " | ")
|
||||
}
|
||||
|
||||
func redraw_all() {
|
||||
const coldef = termbox.ColorDefault
|
||||
termbox.Clear(coldef, coldef)
|
||||
tbprint(0, 0, termbox.ColorMagenta, coldef, "Press 'q' to quit")
|
||||
tbprint(0, 1, coldef, coldef, current)
|
||||
switch curev.Type {
|
||||
case termbox.EventKey:
|
||||
tbprint(0, 2, coldef, coldef,
|
||||
fmt.Sprintf("EventKey: k: %d, c: %c, mod: %s", curev.Key, curev.Ch, mod_str(curev.Mod)))
|
||||
case termbox.EventMouse:
|
||||
tbprint(0, 2, coldef, coldef,
|
||||
fmt.Sprintf("EventMouse: x: %d, y: %d, b: %s, mod: %s",
|
||||
curev.MouseX, curev.MouseY, mouse_button_str(curev.Key), mod_str(curev.Mod)))
|
||||
case termbox.EventNone:
|
||||
tbprint(0, 2, coldef, coldef, "EventNone")
|
||||
}
|
||||
tbprint(0, 3, coldef, coldef, fmt.Sprintf("%d", curev.N))
|
||||
termbox.Flush()
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := termbox.Init()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer termbox.Close()
|
||||
termbox.SetInputMode(termbox.InputAlt | termbox.InputMouse)
|
||||
redraw_all()
|
||||
|
||||
data := make([]byte, 0, 64)
|
||||
mainloop:
|
||||
for {
|
||||
if cap(data)-len(data) < 32 {
|
||||
newdata := make([]byte, len(data), len(data)+32)
|
||||
copy(newdata, data)
|
||||
data = newdata
|
||||
}
|
||||
beg := len(data)
|
||||
d := data[beg : beg+32]
|
||||
switch ev := termbox.PollRawEvent(d); ev.Type {
|
||||
case termbox.EventRaw:
|
||||
data = data[:beg+ev.N]
|
||||
current = fmt.Sprintf("%q", data)
|
||||
if current == `"q"` {
|
||||
break mainloop
|
||||
}
|
||||
|
||||
for {
|
||||
ev := termbox.ParseEvent(data)
|
||||
if ev.N == 0 {
|
||||
break
|
||||
}
|
||||
curev = ev
|
||||
copy(data, data[curev.N:])
|
||||
data = data[:len(data)-curev.N]
|
||||
}
|
||||
case termbox.EventError:
|
||||
panic(ev.Err)
|
||||
}
|
||||
redraw_all()
|
||||
}
|
||||
}
|
457
vendor/github.com/nsf/termbox-go/api.go
generated
vendored
Normal file
457
vendor/github.com/nsf/termbox-go/api.go
generated
vendored
Normal file
@ -0,0 +1,457 @@
|
||||
// +build !windows
|
||||
|
||||
package termbox
|
||||
|
||||
import "github.com/mattn/go-runewidth"
|
||||
import "fmt"
|
||||
import "os"
|
||||
import "os/signal"
|
||||
import "syscall"
|
||||
import "runtime"
|
||||
|
||||
// public API
|
||||
|
||||
// Initializes termbox library. This function should be called before any other functions.
|
||||
// After successful initialization, the library must be finalized using 'Close' function.
|
||||
//
|
||||
// Example usage:
|
||||
// err := termbox.Init()
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// defer termbox.Close()
|
||||
func Init() error {
|
||||
var err error
|
||||
|
||||
out, err = os.OpenFile("/dev/tty", syscall.O_WRONLY, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
in, err = syscall.Open("/dev/tty", syscall.O_RDONLY, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = setup_term()
|
||||
if err != nil {
|
||||
return fmt.Errorf("termbox: error while reading terminfo data: %v", err)
|
||||
}
|
||||
|
||||
signal.Notify(sigwinch, syscall.SIGWINCH)
|
||||
signal.Notify(sigio, syscall.SIGIO)
|
||||
|
||||
_, err = fcntl(in, syscall.F_SETFL, syscall.O_ASYNC|syscall.O_NONBLOCK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = fcntl(in, syscall.F_SETOWN, syscall.Getpid())
|
||||
if runtime.GOOS != "darwin" && err != nil {
|
||||
return err
|
||||
}
|
||||
err = tcgetattr(out.Fd(), &orig_tios)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tios := orig_tios
|
||||
tios.Iflag &^= syscall_IGNBRK | syscall_BRKINT | syscall_PARMRK |
|
||||
syscall_ISTRIP | syscall_INLCR | syscall_IGNCR |
|
||||
syscall_ICRNL | syscall_IXON
|
||||
tios.Lflag &^= syscall_ECHO | syscall_ECHONL | syscall_ICANON |
|
||||
syscall_ISIG | syscall_IEXTEN
|
||||
tios.Cflag &^= syscall_CSIZE | syscall_PARENB
|
||||
tios.Cflag |= syscall_CS8
|
||||
tios.Cc[syscall_VMIN] = 1
|
||||
tios.Cc[syscall_VTIME] = 0
|
||||
|
||||
err = tcsetattr(out.Fd(), &tios)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.WriteString(funcs[t_enter_ca])
|
||||
out.WriteString(funcs[t_enter_keypad])
|
||||
out.WriteString(funcs[t_hide_cursor])
|
||||
out.WriteString(funcs[t_clear_screen])
|
||||
|
||||
termw, termh = get_term_size(out.Fd())
|
||||
back_buffer.init(termw, termh)
|
||||
front_buffer.init(termw, termh)
|
||||
back_buffer.clear()
|
||||
front_buffer.clear()
|
||||
|
||||
go func() {
|
||||
buf := make([]byte, 128)
|
||||
for {
|
||||
select {
|
||||
case <-sigio:
|
||||
for {
|
||||
n, err := syscall.Read(in, buf)
|
||||
if err == syscall.EAGAIN || err == syscall.EWOULDBLOCK {
|
||||
break
|
||||
}
|
||||
select {
|
||||
case input_comm <- input_event{buf[:n], err}:
|
||||
ie := <-input_comm
|
||||
buf = ie.data[:128]
|
||||
case <-quit:
|
||||
return
|
||||
}
|
||||
}
|
||||
case <-quit:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
IsInit = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// Interrupt an in-progress call to PollEvent by causing it to return
|
||||
// EventInterrupt. Note that this function will block until the PollEvent
|
||||
// function has successfully been interrupted.
|
||||
func Interrupt() {
|
||||
interrupt_comm <- struct{}{}
|
||||
}
|
||||
|
||||
// Finalizes termbox library, should be called after successful initialization
|
||||
// when termbox's functionality isn't required anymore.
|
||||
func Close() {
|
||||
quit <- 1
|
||||
out.WriteString(funcs[t_show_cursor])
|
||||
out.WriteString(funcs[t_sgr0])
|
||||
out.WriteString(funcs[t_clear_screen])
|
||||
out.WriteString(funcs[t_exit_ca])
|
||||
out.WriteString(funcs[t_exit_keypad])
|
||||
out.WriteString(funcs[t_exit_mouse])
|
||||
tcsetattr(out.Fd(), &orig_tios)
|
||||
|
||||
out.Close()
|
||||
syscall.Close(in)
|
||||
|
||||
// reset the state, so that on next Init() it will work again
|
||||
termw = 0
|
||||
termh = 0
|
||||
input_mode = InputEsc
|
||||
out = nil
|
||||
in = 0
|
||||
lastfg = attr_invalid
|
||||
lastbg = attr_invalid
|
||||
lastx = coord_invalid
|
||||
lasty = coord_invalid
|
||||
cursor_x = cursor_hidden
|
||||
cursor_y = cursor_hidden
|
||||
foreground = ColorDefault
|
||||
background = ColorDefault
|
||||
IsInit = false
|
||||
}
|
||||
|
||||
// Synchronizes the internal back buffer with the terminal.
|
||||
func Flush() error {
|
||||
// invalidate cursor position
|
||||
lastx = coord_invalid
|
||||
lasty = coord_invalid
|
||||
|
||||
update_size_maybe()
|
||||
|
||||
for y := 0; y < front_buffer.height; y++ {
|
||||
line_offset := y * front_buffer.width
|
||||
for x := 0; x < front_buffer.width; {
|
||||
cell_offset := line_offset + x
|
||||
back := &back_buffer.cells[cell_offset]
|
||||
front := &front_buffer.cells[cell_offset]
|
||||
if back.Ch < ' ' {
|
||||
back.Ch = ' '
|
||||
}
|
||||
w := runewidth.RuneWidth(back.Ch)
|
||||
if w == 0 || w == 2 && runewidth.IsAmbiguousWidth(back.Ch) {
|
||||
w = 1
|
||||
}
|
||||
if *back == *front {
|
||||
x += w
|
||||
continue
|
||||
}
|
||||
*front = *back
|
||||
send_attr(back.Fg, back.Bg)
|
||||
|
||||
if w == 2 && x == front_buffer.width-1 {
|
||||
// there's not enough space for 2-cells rune,
|
||||
// let's just put a space in there
|
||||
send_char(x, y, ' ')
|
||||
} else {
|
||||
send_char(x, y, back.Ch)
|
||||
if w == 2 {
|
||||
next := cell_offset + 1
|
||||
front_buffer.cells[next] = Cell{
|
||||
Ch: 0,
|
||||
Fg: back.Fg,
|
||||
Bg: back.Bg,
|
||||
}
|
||||
}
|
||||
}
|
||||
x += w
|
||||
}
|
||||
}
|
||||
if !is_cursor_hidden(cursor_x, cursor_y) {
|
||||
write_cursor(cursor_x, cursor_y)
|
||||
}
|
||||
return flush()
|
||||
}
|
||||
|
||||
// Sets the position of the cursor. See also HideCursor().
|
||||
func SetCursor(x, y int) {
|
||||
if is_cursor_hidden(cursor_x, cursor_y) && !is_cursor_hidden(x, y) {
|
||||
outbuf.WriteString(funcs[t_show_cursor])
|
||||
}
|
||||
|
||||
if !is_cursor_hidden(cursor_x, cursor_y) && is_cursor_hidden(x, y) {
|
||||
outbuf.WriteString(funcs[t_hide_cursor])
|
||||
}
|
||||
|
||||
cursor_x, cursor_y = x, y
|
||||
if !is_cursor_hidden(cursor_x, cursor_y) {
|
||||
write_cursor(cursor_x, cursor_y)
|
||||
}
|
||||
}
|
||||
|
||||
// The shortcut for SetCursor(-1, -1).
|
||||
func HideCursor() {
|
||||
SetCursor(cursor_hidden, cursor_hidden)
|
||||
}
|
||||
|
||||
// Changes cell's parameters in the internal back buffer at the specified
|
||||
// position.
|
||||
func SetCell(x, y int, ch rune, fg, bg Attribute) {
|
||||
if x < 0 || x >= back_buffer.width {
|
||||
return
|
||||
}
|
||||
if y < 0 || y >= back_buffer.height {
|
||||
return
|
||||
}
|
||||
|
||||
back_buffer.cells[y*back_buffer.width+x] = Cell{ch, fg, bg}
|
||||
}
|
||||
|
||||
// Returns a slice into the termbox's back buffer. You can get its dimensions
|
||||
// using 'Size' function. The slice remains valid as long as no 'Clear' or
|
||||
// 'Flush' function calls were made after call to this function.
|
||||
func CellBuffer() []Cell {
|
||||
return back_buffer.cells
|
||||
}
|
||||
|
||||
// After getting a raw event from PollRawEvent function call, you can parse it
|
||||
// again into an ordinary one using termbox logic. That is parse an event as
|
||||
// termbox would do it. Returned event in addition to usual Event struct fields
|
||||
// sets N field to the amount of bytes used within 'data' slice. If the length
|
||||
// of 'data' slice is zero or event cannot be parsed for some other reason, the
|
||||
// function will return a special event type: EventNone.
|
||||
//
|
||||
// IMPORTANT: EventNone may contain a non-zero N, which means you should skip
|
||||
// these bytes, because termbox cannot recognize them.
|
||||
//
|
||||
// NOTE: This API is experimental and may change in future.
|
||||
func ParseEvent(data []byte) Event {
|
||||
event := Event{Type: EventKey}
|
||||
ok := extract_event(data, &event)
|
||||
if !ok {
|
||||
return Event{Type: EventNone, N: event.N}
|
||||
}
|
||||
return event
|
||||
}
|
||||
|
||||
// Wait for an event and return it. This is a blocking function call. Instead
|
||||
// of EventKey and EventMouse it returns EventRaw events. Raw event is written
|
||||
// into `data` slice and Event's N field is set to the amount of bytes written.
|
||||
// The minimum required length of the 'data' slice is 1. This requirement may
|
||||
// vary on different platforms.
|
||||
//
|
||||
// NOTE: This API is experimental and may change in future.
|
||||
func PollRawEvent(data []byte) Event {
|
||||
if len(data) == 0 {
|
||||
panic("len(data) >= 1 is a requirement")
|
||||
}
|
||||
|
||||
var event Event
|
||||
if extract_raw_event(data, &event) {
|
||||
return event
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case ev := <-input_comm:
|
||||
if ev.err != nil {
|
||||
return Event{Type: EventError, Err: ev.err}
|
||||
}
|
||||
|
||||
inbuf = append(inbuf, ev.data...)
|
||||
input_comm <- ev
|
||||
if extract_raw_event(data, &event) {
|
||||
return event
|
||||
}
|
||||
case <-interrupt_comm:
|
||||
event.Type = EventInterrupt
|
||||
return event
|
||||
|
||||
case <-sigwinch:
|
||||
event.Type = EventResize
|
||||
event.Width, event.Height = get_term_size(out.Fd())
|
||||
return event
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for an event and return it. This is a blocking function call.
|
||||
func PollEvent() Event {
|
||||
var event Event
|
||||
|
||||
// try to extract event from input buffer, return on success
|
||||
event.Type = EventKey
|
||||
ok := extract_event(inbuf, &event)
|
||||
if event.N != 0 {
|
||||
copy(inbuf, inbuf[event.N:])
|
||||
inbuf = inbuf[:len(inbuf)-event.N]
|
||||
}
|
||||
if ok {
|
||||
return event
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case ev := <-input_comm:
|
||||
if ev.err != nil {
|
||||
return Event{Type: EventError, Err: ev.err}
|
||||
}
|
||||
|
||||
inbuf = append(inbuf, ev.data...)
|
||||
input_comm <- ev
|
||||
ok := extract_event(inbuf, &event)
|
||||
if event.N != 0 {
|
||||
copy(inbuf, inbuf[event.N:])
|
||||
inbuf = inbuf[:len(inbuf)-event.N]
|
||||
}
|
||||
if ok {
|
||||
return event
|
||||
}
|
||||
case <-interrupt_comm:
|
||||
event.Type = EventInterrupt
|
||||
return event
|
||||
|
||||
case <-sigwinch:
|
||||
event.Type = EventResize
|
||||
event.Width, event.Height = get_term_size(out.Fd())
|
||||
return event
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the size of the internal back buffer (which is mostly the same as
|
||||
// terminal's window size in characters). But it doesn't always match the size
|
||||
// of the terminal window, after the terminal size has changed, the internal
|
||||
// back buffer will get in sync only after Clear or Flush function calls.
|
||||
func Size() (width int, height int) {
|
||||
return termw, termh
|
||||
}
|
||||
|
||||
// Clears the internal back buffer.
|
||||
func Clear(fg, bg Attribute) error {
|
||||
foreground, background = fg, bg
|
||||
err := update_size_maybe()
|
||||
back_buffer.clear()
|
||||
return err
|
||||
}
|
||||
|
||||
// Sets termbox input mode. Termbox has two input modes:
|
||||
//
|
||||
// 1. Esc input mode. When ESC sequence is in the buffer and it doesn't match
|
||||
// any known sequence. ESC means KeyEsc. This is the default input mode.
|
||||
//
|
||||
// 2. Alt input mode. When ESC sequence is in the buffer and it doesn't match
|
||||
// any known sequence. ESC enables ModAlt modifier for the next keyboard event.
|
||||
//
|
||||
// Both input modes can be OR'ed with Mouse mode. Setting Mouse mode bit up will
|
||||
// enable mouse button press/release and drag events.
|
||||
//
|
||||
// If 'mode' is InputCurrent, returns the current input mode. See also Input*
|
||||
// constants.
|
||||
func SetInputMode(mode InputMode) InputMode {
|
||||
if mode == InputCurrent {
|
||||
return input_mode
|
||||
}
|
||||
if mode&(InputEsc|InputAlt) == 0 {
|
||||
mode |= InputEsc
|
||||
}
|
||||
if mode&(InputEsc|InputAlt) == InputEsc|InputAlt {
|
||||
mode &^= InputAlt
|
||||
}
|
||||
if mode&InputMouse != 0 {
|
||||
out.WriteString(funcs[t_enter_mouse])
|
||||
} else {
|
||||
out.WriteString(funcs[t_exit_mouse])
|
||||
}
|
||||
|
||||
input_mode = mode
|
||||
return input_mode
|
||||
}
|
||||
|
||||
// Sets the termbox output mode. Termbox has four output options:
|
||||
//
|
||||
// 1. OutputNormal => [1..8]
|
||||
// This mode provides 8 different colors:
|
||||
// black, red, green, yellow, blue, magenta, cyan, white
|
||||
// Shortcut: ColorBlack, ColorRed, ...
|
||||
// Attributes: AttrBold, AttrUnderline, AttrReverse
|
||||
//
|
||||
// Example usage:
|
||||
// SetCell(x, y, '@', ColorBlack | AttrBold, ColorRed);
|
||||
//
|
||||
// 2. Output256 => [1..256]
|
||||
// In this mode you can leverage the 256 terminal mode:
|
||||
// 0x01 - 0x08: the 8 colors as in OutputNormal
|
||||
// 0x09 - 0x10: Color* | AttrBold
|
||||
// 0x11 - 0xe8: 216 different colors
|
||||
// 0xe9 - 0x1ff: 24 different shades of grey
|
||||
//
|
||||
// Example usage:
|
||||
// SetCell(x, y, '@', 184, 240);
|
||||
// SetCell(x, y, '@', 0xb8, 0xf0);
|
||||
//
|
||||
// 3. Output216 => [1..216]
|
||||
// This mode supports the 3rd range of the 256 mode only.
|
||||
// But you dont need to provide an offset.
|
||||
//
|
||||
// 4. OutputGrayscale => [1..26]
|
||||
// This mode supports the 4th range of the 256 mode
|
||||
// and black and white colors from 3th range of the 256 mode
|
||||
// But you dont need to provide an offset.
|
||||
//
|
||||
// In all modes, 0x00 represents the default color.
|
||||
//
|
||||
// `go run _demos/output.go` to see its impact on your terminal.
|
||||
//
|
||||
// If 'mode' is OutputCurrent, it returns the current output mode.
|
||||
//
|
||||
// Note that this may return a different OutputMode than the one requested,
|
||||
// as the requested mode may not be available on the target platform.
|
||||
func SetOutputMode(mode OutputMode) OutputMode {
|
||||
if mode == OutputCurrent {
|
||||
return output_mode
|
||||
}
|
||||
|
||||
output_mode = mode
|
||||
return output_mode
|
||||
}
|
||||
|
||||
// Sync comes handy when something causes desync between termbox's understanding
|
||||
// of a terminal buffer and the reality. Such as a third party process. Sync
|
||||
// forces a complete resync between the termbox and a terminal, it may not be
|
||||
// visually pretty though.
|
||||
func Sync() error {
|
||||
front_buffer.clear()
|
||||
err := send_clear()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return Flush()
|
||||
}
|
187
vendor/github.com/nsf/termbox-go/api_common.go
generated
vendored
Normal file
187
vendor/github.com/nsf/termbox-go/api_common.go
generated
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
// termbox is a library for creating cross-platform text-based interfaces
|
||||
package termbox
|
||||
|
||||
// public API, common OS agnostic part
|
||||
|
||||
type (
|
||||
InputMode int
|
||||
OutputMode int
|
||||
EventType uint8
|
||||
Modifier uint8
|
||||
Key uint16
|
||||
Attribute uint16
|
||||
)
|
||||
|
||||
// This type represents a termbox event. The 'Mod', 'Key' and 'Ch' fields are
|
||||
// valid if 'Type' is EventKey. The 'Width' and 'Height' fields are valid if
|
||||
// 'Type' is EventResize. The 'Err' field is valid if 'Type' is EventError.
|
||||
type Event struct {
|
||||
Type EventType // one of Event* constants
|
||||
Mod Modifier // one of Mod* constants or 0
|
||||
Key Key // one of Key* constants, invalid if 'Ch' is not 0
|
||||
Ch rune // a unicode character
|
||||
Width int // width of the screen
|
||||
Height int // height of the screen
|
||||
Err error // error in case if input failed
|
||||
MouseX int // x coord of mouse
|
||||
MouseY int // y coord of mouse
|
||||
N int // number of bytes written when getting a raw event
|
||||
}
|
||||
|
||||
// A cell, single conceptual entity on the screen. The screen is basically a 2d
|
||||
// array of cells. 'Ch' is a unicode character, 'Fg' and 'Bg' are foreground
|
||||
// and background attributes respectively.
|
||||
type Cell struct {
|
||||
Ch rune
|
||||
Fg Attribute
|
||||
Bg Attribute
|
||||
}
|
||||
|
||||
// To know if termbox has been initialized or not
|
||||
var (
|
||||
IsInit bool = false
|
||||
)
|
||||
|
||||
// Key constants, see Event.Key field.
|
||||
const (
|
||||
KeyF1 Key = 0xFFFF - iota
|
||||
KeyF2
|
||||
KeyF3
|
||||
KeyF4
|
||||
KeyF5
|
||||
KeyF6
|
||||
KeyF7
|
||||
KeyF8
|
||||
KeyF9
|
||||
KeyF10
|
||||
KeyF11
|
||||
KeyF12
|
||||
KeyInsert
|
||||
KeyDelete
|
||||
KeyHome
|
||||
KeyEnd
|
||||
KeyPgup
|
||||
KeyPgdn
|
||||
KeyArrowUp
|
||||
KeyArrowDown
|
||||
KeyArrowLeft
|
||||
KeyArrowRight
|
||||
key_min // see terminfo
|
||||
MouseLeft
|
||||
MouseMiddle
|
||||
MouseRight
|
||||
MouseRelease
|
||||
MouseWheelUp
|
||||
MouseWheelDown
|
||||
)
|
||||
|
||||
const (
|
||||
KeyCtrlTilde Key = 0x00
|
||||
KeyCtrl2 Key = 0x00
|
||||
KeyCtrlSpace Key = 0x00
|
||||
KeyCtrlA Key = 0x01
|
||||
KeyCtrlB Key = 0x02
|
||||
KeyCtrlC Key = 0x03
|
||||
KeyCtrlD Key = 0x04
|
||||
KeyCtrlE Key = 0x05
|
||||
KeyCtrlF Key = 0x06
|
||||
KeyCtrlG Key = 0x07
|
||||
KeyBackspace Key = 0x08
|
||||
KeyCtrlH Key = 0x08
|
||||
KeyTab Key = 0x09
|
||||
KeyCtrlI Key = 0x09
|
||||
KeyCtrlJ Key = 0x0A
|
||||
KeyCtrlK Key = 0x0B
|
||||
KeyCtrlL Key = 0x0C
|
||||
KeyEnter Key = 0x0D
|
||||
KeyCtrlM Key = 0x0D
|
||||
KeyCtrlN Key = 0x0E
|
||||
KeyCtrlO Key = 0x0F
|
||||
KeyCtrlP Key = 0x10
|
||||
KeyCtrlQ Key = 0x11
|
||||
KeyCtrlR Key = 0x12
|
||||
KeyCtrlS Key = 0x13
|
||||
KeyCtrlT Key = 0x14
|
||||
KeyCtrlU Key = 0x15
|
||||
KeyCtrlV Key = 0x16
|
||||
KeyCtrlW Key = 0x17
|
||||
KeyCtrlX Key = 0x18
|
||||
KeyCtrlY Key = 0x19
|
||||
KeyCtrlZ Key = 0x1A
|
||||
KeyEsc Key = 0x1B
|
||||
KeyCtrlLsqBracket Key = 0x1B
|
||||
KeyCtrl3 Key = 0x1B
|
||||
KeyCtrl4 Key = 0x1C
|
||||
KeyCtrlBackslash Key = 0x1C
|
||||
KeyCtrl5 Key = 0x1D
|
||||
KeyCtrlRsqBracket Key = 0x1D
|
||||
KeyCtrl6 Key = 0x1E
|
||||
KeyCtrl7 Key = 0x1F
|
||||
KeyCtrlSlash Key = 0x1F
|
||||
KeyCtrlUnderscore Key = 0x1F
|
||||
KeySpace Key = 0x20
|
||||
KeyBackspace2 Key = 0x7F
|
||||
KeyCtrl8 Key = 0x7F
|
||||
)
|
||||
|
||||
// Alt modifier constant, see Event.Mod field and SetInputMode function.
|
||||
const (
|
||||
ModAlt Modifier = 1 << iota
|
||||
ModMotion
|
||||
)
|
||||
|
||||
// Cell colors, you can combine a color with multiple attributes using bitwise
|
||||
// OR ('|').
|
||||
const (
|
||||
ColorDefault Attribute = iota
|
||||
ColorBlack
|
||||
ColorRed
|
||||
ColorGreen
|
||||
ColorYellow
|
||||
ColorBlue
|
||||
ColorMagenta
|
||||
ColorCyan
|
||||
ColorWhite
|
||||
)
|
||||
|
||||
// Cell attributes, it is possible to use multiple attributes by combining them
|
||||
// using bitwise OR ('|'). Although, colors cannot be combined. But you can
|
||||
// combine attributes and a single color.
|
||||
//
|
||||
// It's worth mentioning that some platforms don't support certain attibutes.
|
||||
// For example windows console doesn't support AttrUnderline. And on some
|
||||
// terminals applying AttrBold to background may result in blinking text. Use
|
||||
// them with caution and test your code on various terminals.
|
||||
const (
|
||||
AttrBold Attribute = 1 << (iota + 9)
|
||||
AttrUnderline
|
||||
AttrReverse
|
||||
)
|
||||
|
||||
// Input mode. See SetInputMode function.
|
||||
const (
|
||||
InputEsc InputMode = 1 << iota
|
||||
InputAlt
|
||||
InputMouse
|
||||
InputCurrent InputMode = 0
|
||||
)
|
||||
|
||||
// Output mode. See SetOutputMode function.
|
||||
const (
|
||||
OutputCurrent OutputMode = iota
|
||||
OutputNormal
|
||||
Output256
|
||||
Output216
|
||||
OutputGrayscale
|
||||
)
|
||||
|
||||
// Event type. See Event.Type field.
|
||||
const (
|
||||
EventKey EventType = iota
|
||||
EventResize
|
||||
EventMouse
|
||||
EventError
|
||||
EventInterrupt
|
||||
EventRaw
|
||||
EventNone
|
||||
)
|
239
vendor/github.com/nsf/termbox-go/api_windows.go
generated
vendored
Normal file
239
vendor/github.com/nsf/termbox-go/api_windows.go
generated
vendored
Normal file
@ -0,0 +1,239 @@
|
||||
package termbox
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// public API
|
||||
|
||||
// Initializes termbox library. This function should be called before any other functions.
|
||||
// After successful initialization, the library must be finalized using 'Close' function.
|
||||
//
|
||||
// Example usage:
|
||||
// err := termbox.Init()
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// defer termbox.Close()
|
||||
func Init() error {
|
||||
var err error
|
||||
|
||||
interrupt, err = create_event()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
in, err = syscall.Open("CONIN$", syscall.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out, err = syscall.Open("CONOUT$", syscall.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = get_console_mode(in, &orig_mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = set_console_mode(in, enable_window_input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
orig_size = get_term_size(out)
|
||||
win_size := get_win_size(out)
|
||||
|
||||
err = set_console_screen_buffer_size(out, win_size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = get_console_cursor_info(out, &orig_cursor_info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
show_cursor(false)
|
||||
term_size = get_term_size(out)
|
||||
back_buffer.init(int(term_size.x), int(term_size.y))
|
||||
front_buffer.init(int(term_size.x), int(term_size.y))
|
||||
back_buffer.clear()
|
||||
front_buffer.clear()
|
||||
clear()
|
||||
|
||||
diffbuf = make([]diff_msg, 0, 32)
|
||||
|
||||
go input_event_producer()
|
||||
IsInit = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// Finalizes termbox library, should be called after successful initialization
|
||||
// when termbox's functionality isn't required anymore.
|
||||
func Close() {
|
||||
// we ignore errors here, because we can't really do anything about them
|
||||
Clear(0, 0)
|
||||
Flush()
|
||||
|
||||
// stop event producer
|
||||
cancel_comm <- true
|
||||
set_event(interrupt)
|
||||
select {
|
||||
case <-input_comm:
|
||||
default:
|
||||
}
|
||||
<-cancel_done_comm
|
||||
|
||||
set_console_cursor_info(out, &orig_cursor_info)
|
||||
set_console_cursor_position(out, coord{})
|
||||
set_console_screen_buffer_size(out, orig_size)
|
||||
set_console_mode(in, orig_mode)
|
||||
syscall.Close(in)
|
||||
syscall.Close(out)
|
||||
syscall.Close(interrupt)
|
||||
IsInit = false
|
||||
}
|
||||
|
||||
// Interrupt an in-progress call to PollEvent by causing it to return
|
||||
// EventInterrupt. Note that this function will block until the PollEvent
|
||||
// function has successfully been interrupted.
|
||||
func Interrupt() {
|
||||
interrupt_comm <- struct{}{}
|
||||
}
|
||||
|
||||
// Synchronizes the internal back buffer with the terminal.
|
||||
func Flush() error {
|
||||
update_size_maybe()
|
||||
prepare_diff_messages()
|
||||
for _, diff := range diffbuf {
|
||||
r := small_rect{
|
||||
left: 0,
|
||||
top: diff.pos,
|
||||
right: term_size.x - 1,
|
||||
bottom: diff.pos + diff.lines - 1,
|
||||
}
|
||||
write_console_output(out, diff.chars, r)
|
||||
}
|
||||
if !is_cursor_hidden(cursor_x, cursor_y) {
|
||||
move_cursor(cursor_x, cursor_y)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sets the position of the cursor. See also HideCursor().
|
||||
func SetCursor(x, y int) {
|
||||
if is_cursor_hidden(cursor_x, cursor_y) && !is_cursor_hidden(x, y) {
|
||||
show_cursor(true)
|
||||
}
|
||||
|
||||
if !is_cursor_hidden(cursor_x, cursor_y) && is_cursor_hidden(x, y) {
|
||||
show_cursor(false)
|
||||
}
|
||||
|
||||
cursor_x, cursor_y = x, y
|
||||
if !is_cursor_hidden(cursor_x, cursor_y) {
|
||||
move_cursor(cursor_x, cursor_y)
|
||||
}
|
||||
}
|
||||
|
||||
// The shortcut for SetCursor(-1, -1).
|
||||
func HideCursor() {
|
||||
SetCursor(cursor_hidden, cursor_hidden)
|
||||
}
|
||||
|
||||
// Changes cell's parameters in the internal back buffer at the specified
|
||||
// position.
|
||||
func SetCell(x, y int, ch rune, fg, bg Attribute) {
|
||||
if x < 0 || x >= back_buffer.width {
|
||||
return
|
||||
}
|
||||
if y < 0 || y >= back_buffer.height {
|
||||
return
|
||||
}
|
||||
|
||||
back_buffer.cells[y*back_buffer.width+x] = Cell{ch, fg, bg}
|
||||
}
|
||||
|
||||
// Returns a slice into the termbox's back buffer. You can get its dimensions
|
||||
// using 'Size' function. The slice remains valid as long as no 'Clear' or
|
||||
// 'Flush' function calls were made after call to this function.
|
||||
func CellBuffer() []Cell {
|
||||
return back_buffer.cells
|
||||
}
|
||||
|
||||
// Wait for an event and return it. This is a blocking function call.
|
||||
func PollEvent() Event {
|
||||
select {
|
||||
case ev := <-input_comm:
|
||||
return ev
|
||||
case <-interrupt_comm:
|
||||
return Event{Type: EventInterrupt}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the size of the internal back buffer (which is mostly the same as
|
||||
// console's window size in characters). But it doesn't always match the size
|
||||
// of the console window, after the console size has changed, the internal back
|
||||
// buffer will get in sync only after Clear or Flush function calls.
|
||||
func Size() (int, int) {
|
||||
return int(term_size.x), int(term_size.y)
|
||||
}
|
||||
|
||||
// Clears the internal back buffer.
|
||||
func Clear(fg, bg Attribute) error {
|
||||
foreground, background = fg, bg
|
||||
update_size_maybe()
|
||||
back_buffer.clear()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sets termbox input mode. Termbox has two input modes:
|
||||
//
|
||||
// 1. Esc input mode. When ESC sequence is in the buffer and it doesn't match
|
||||
// any known sequence. ESC means KeyEsc. This is the default input mode.
|
||||
//
|
||||
// 2. Alt input mode. When ESC sequence is in the buffer and it doesn't match
|
||||
// any known sequence. ESC enables ModAlt modifier for the next keyboard event.
|
||||
//
|
||||
// Both input modes can be OR'ed with Mouse mode. Setting Mouse mode bit up will
|
||||
// enable mouse button press/release and drag events.
|
||||
//
|
||||
// If 'mode' is InputCurrent, returns the current input mode. See also Input*
|
||||
// constants.
|
||||
func SetInputMode(mode InputMode) InputMode {
|
||||
if mode == InputCurrent {
|
||||
return input_mode
|
||||
}
|
||||
if mode&InputMouse != 0 {
|
||||
err := set_console_mode(in, enable_window_input|enable_mouse_input|enable_extended_flags)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
err := set_console_mode(in, enable_window_input)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
input_mode = mode
|
||||
return input_mode
|
||||
}
|
||||
|
||||
// Sets the termbox output mode.
|
||||
//
|
||||
// Windows console does not support extra colour modes,
|
||||
// so this will always set and return OutputNormal.
|
||||
func SetOutputMode(mode OutputMode) OutputMode {
|
||||
return OutputNormal
|
||||
}
|
||||
|
||||
// Sync comes handy when something causes desync between termbox's understanding
|
||||
// of a terminal buffer and the reality. Such as a third party process. Sync
|
||||
// forces a complete resync between the termbox and a terminal, it may not be
|
||||
// visually pretty though. At the moment on Windows it does nothing.
|
||||
func Sync() error {
|
||||
return nil
|
||||
}
|
110
vendor/github.com/nsf/termbox-go/collect_terminfo.py
generated
vendored
Executable file
110
vendor/github.com/nsf/termbox-go/collect_terminfo.py
generated
vendored
Executable file
@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys, os, subprocess
|
||||
|
||||
def escaped(s):
|
||||
return repr(s)[1:-1]
|
||||
|
||||
def tput(term, name):
|
||||
try:
|
||||
return subprocess.check_output(['tput', '-T%s' % term, name]).decode()
|
||||
except subprocess.CalledProcessError as e:
|
||||
return e.output.decode()
|
||||
|
||||
|
||||
def w(s):
|
||||
if s == None:
|
||||
return
|
||||
sys.stdout.write(s)
|
||||
|
||||
terminals = {
|
||||
'xterm' : 'xterm',
|
||||
'rxvt-256color' : 'rxvt_256color',
|
||||
'rxvt-unicode' : 'rxvt_unicode',
|
||||
'linux' : 'linux',
|
||||
'Eterm' : 'eterm',
|
||||
'screen' : 'screen'
|
||||
}
|
||||
|
||||
keys = [
|
||||
"F1", "kf1",
|
||||
"F2", "kf2",
|
||||
"F3", "kf3",
|
||||
"F4", "kf4",
|
||||
"F5", "kf5",
|
||||
"F6", "kf6",
|
||||
"F7", "kf7",
|
||||
"F8", "kf8",
|
||||
"F9", "kf9",
|
||||
"F10", "kf10",
|
||||
"F11", "kf11",
|
||||
"F12", "kf12",
|
||||
"INSERT", "kich1",
|
||||
"DELETE", "kdch1",
|
||||
"HOME", "khome",
|
||||
"END", "kend",
|
||||
"PGUP", "kpp",
|
||||
"PGDN", "knp",
|
||||
"KEY_UP", "kcuu1",
|
||||
"KEY_DOWN", "kcud1",
|
||||
"KEY_LEFT", "kcub1",
|
||||
"KEY_RIGHT", "kcuf1"
|
||||
]
|
||||
|
||||
funcs = [
|
||||
"T_ENTER_CA", "smcup",
|
||||
"T_EXIT_CA", "rmcup",
|
||||
"T_SHOW_CURSOR", "cnorm",
|
||||
"T_HIDE_CURSOR", "civis",
|
||||
"T_CLEAR_SCREEN", "clear",
|
||||
"T_SGR0", "sgr0",
|
||||
"T_UNDERLINE", "smul",
|
||||
"T_BOLD", "bold",
|
||||
"T_BLINK", "blink",
|
||||
"T_REVERSE", "rev",
|
||||
"T_ENTER_KEYPAD", "smkx",
|
||||
"T_EXIT_KEYPAD", "rmkx"
|
||||
]
|
||||
|
||||
def iter_pairs(iterable):
|
||||
iterable = iter(iterable)
|
||||
while True:
|
||||
yield (next(iterable), next(iterable))
|
||||
|
||||
def do_term(term, nick):
|
||||
w("// %s\n" % term)
|
||||
w("var %s_keys = []string{\n\t" % nick)
|
||||
for k, v in iter_pairs(keys):
|
||||
w('"')
|
||||
w(escaped(tput(term, v)))
|
||||
w('",')
|
||||
w("\n}\n")
|
||||
w("var %s_funcs = []string{\n\t" % nick)
|
||||
for k,v in iter_pairs(funcs):
|
||||
w('"')
|
||||
if v == "sgr":
|
||||
w("\\033[3%d;4%dm")
|
||||
elif v == "cup":
|
||||
w("\\033[%d;%dH")
|
||||
else:
|
||||
w(escaped(tput(term, v)))
|
||||
w('", ')
|
||||
w("\n}\n\n")
|
||||
|
||||
def do_terms(d):
|
||||
w("var terms = []struct {\n")
|
||||
w("\tname string\n")
|
||||
w("\tkeys []string\n")
|
||||
w("\tfuncs []string\n")
|
||||
w("}{\n")
|
||||
for k, v in d.items():
|
||||
w('\t{"%s", %s_keys, %s_funcs},\n' % (k, v, v))
|
||||
w("}\n\n")
|
||||
|
||||
w("// +build !windows\n\npackage termbox\n\n")
|
||||
|
||||
for k,v in terminals.items():
|
||||
do_term(k, v)
|
||||
|
||||
do_terms(terminals)
|
||||
|
39
vendor/github.com/nsf/termbox-go/syscalls.go
generated
vendored
Normal file
39
vendor/github.com/nsf/termbox-go/syscalls.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
// +build ignore
|
||||
|
||||
package termbox
|
||||
|
||||
/*
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
type syscall_Termios C.struct_termios
|
||||
|
||||
const (
|
||||
syscall_IGNBRK = C.IGNBRK
|
||||
syscall_BRKINT = C.BRKINT
|
||||
syscall_PARMRK = C.PARMRK
|
||||
syscall_ISTRIP = C.ISTRIP
|
||||
syscall_INLCR = C.INLCR
|
||||
syscall_IGNCR = C.IGNCR
|
||||
syscall_ICRNL = C.ICRNL
|
||||
syscall_IXON = C.IXON
|
||||
syscall_OPOST = C.OPOST
|
||||
syscall_ECHO = C.ECHO
|
||||
syscall_ECHONL = C.ECHONL
|
||||
syscall_ICANON = C.ICANON
|
||||
syscall_ISIG = C.ISIG
|
||||
syscall_IEXTEN = C.IEXTEN
|
||||
syscall_CSIZE = C.CSIZE
|
||||
syscall_PARENB = C.PARENB
|
||||
syscall_CS8 = C.CS8
|
||||
syscall_VMIN = C.VMIN
|
||||
syscall_VTIME = C.VTIME
|
||||
|
||||
// on darwin change these to (on *bsd too?):
|
||||
// C.TIOCGETA
|
||||
// C.TIOCSETA
|
||||
syscall_TCGETS = C.TCGETS
|
||||
syscall_TCSETS = C.TCSETS
|
||||
)
|
41
vendor/github.com/nsf/termbox-go/syscalls_darwin.go
generated
vendored
Normal file
41
vendor/github.com/nsf/termbox-go/syscalls_darwin.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs syscalls.go
|
||||
|
||||
// +build !amd64
|
||||
|
||||
package termbox
|
||||
|
||||
type syscall_Termios struct {
|
||||
Iflag uint32
|
||||
Oflag uint32
|
||||
Cflag uint32
|
||||
Lflag uint32
|
||||
Cc [20]uint8
|
||||
Ispeed uint32
|
||||
Ospeed uint32
|
||||
}
|
||||
|
||||
const (
|
||||
syscall_IGNBRK = 0x1
|
||||
syscall_BRKINT = 0x2
|
||||
syscall_PARMRK = 0x8
|
||||
syscall_ISTRIP = 0x20
|
||||
syscall_INLCR = 0x40
|
||||
syscall_IGNCR = 0x80
|
||||
syscall_ICRNL = 0x100
|
||||
syscall_IXON = 0x200
|
||||
syscall_OPOST = 0x1
|
||||
syscall_ECHO = 0x8
|
||||
syscall_ECHONL = 0x10
|
||||
syscall_ICANON = 0x100
|
||||
syscall_ISIG = 0x80
|
||||
syscall_IEXTEN = 0x400
|
||||
syscall_CSIZE = 0x300
|
||||
syscall_PARENB = 0x1000
|
||||
syscall_CS8 = 0x300
|
||||
syscall_VMIN = 0x10
|
||||
syscall_VTIME = 0x11
|
||||
|
||||
syscall_TCGETS = 0x402c7413
|
||||
syscall_TCSETS = 0x802c7414
|
||||
)
|
40
vendor/github.com/nsf/termbox-go/syscalls_darwin_amd64.go
generated
vendored
Normal file
40
vendor/github.com/nsf/termbox-go/syscalls_darwin_amd64.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs syscalls.go
|
||||
|
||||
package termbox
|
||||
|
||||
type syscall_Termios struct {
|
||||
Iflag uint64
|
||||
Oflag uint64
|
||||
Cflag uint64
|
||||
Lflag uint64
|
||||
Cc [20]uint8
|
||||
Pad_cgo_0 [4]byte
|
||||
Ispeed uint64
|
||||
Ospeed uint64
|
||||
}
|
||||
|
||||
const (
|
||||
syscall_IGNBRK = 0x1
|
||||
syscall_BRKINT = 0x2
|
||||
syscall_PARMRK = 0x8
|
||||
syscall_ISTRIP = 0x20
|
||||
syscall_INLCR = 0x40
|
||||
syscall_IGNCR = 0x80
|
||||
syscall_ICRNL = 0x100
|
||||
syscall_IXON = 0x200
|
||||
syscall_OPOST = 0x1
|
||||
syscall_ECHO = 0x8
|
||||
syscall_ECHONL = 0x10
|
||||
syscall_ICANON = 0x100
|
||||
syscall_ISIG = 0x80
|
||||
syscall_IEXTEN = 0x400
|
||||
syscall_CSIZE = 0x300
|
||||
syscall_PARENB = 0x1000
|
||||
syscall_CS8 = 0x300
|
||||
syscall_VMIN = 0x10
|
||||
syscall_VTIME = 0x11
|
||||
|
||||
syscall_TCGETS = 0x40487413
|
||||
syscall_TCSETS = 0x80487414
|
||||
)
|
39
vendor/github.com/nsf/termbox-go/syscalls_dragonfly.go
generated
vendored
Normal file
39
vendor/github.com/nsf/termbox-go/syscalls_dragonfly.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs syscalls.go
|
||||
|
||||
package termbox
|
||||
|
||||
type syscall_Termios struct {
|
||||
Iflag uint32
|
||||
Oflag uint32
|
||||
Cflag uint32
|
||||
Lflag uint32
|
||||
Cc [20]uint8
|
||||
Ispeed uint32
|
||||
Ospeed uint32
|
||||
}
|
||||
|
||||
const (
|
||||
syscall_IGNBRK = 0x1
|
||||
syscall_BRKINT = 0x2
|
||||
syscall_PARMRK = 0x8
|
||||
syscall_ISTRIP = 0x20
|
||||
syscall_INLCR = 0x40
|
||||
syscall_IGNCR = 0x80
|
||||
syscall_ICRNL = 0x100
|
||||
syscall_IXON = 0x200
|
||||
syscall_OPOST = 0x1
|
||||
syscall_ECHO = 0x8
|
||||
syscall_ECHONL = 0x10
|
||||
syscall_ICANON = 0x100
|
||||
syscall_ISIG = 0x80
|
||||
syscall_IEXTEN = 0x400
|
||||
syscall_CSIZE = 0x300
|
||||
syscall_PARENB = 0x1000
|
||||
syscall_CS8 = 0x300
|
||||
syscall_VMIN = 0x10
|
||||
syscall_VTIME = 0x11
|
||||
|
||||
syscall_TCGETS = 0x402c7413
|
||||
syscall_TCSETS = 0x802c7414
|
||||
)
|
39
vendor/github.com/nsf/termbox-go/syscalls_freebsd.go
generated
vendored
Normal file
39
vendor/github.com/nsf/termbox-go/syscalls_freebsd.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs syscalls.go
|
||||
|
||||
package termbox
|
||||
|
||||
type syscall_Termios struct {
|
||||
Iflag uint32
|
||||
Oflag uint32
|
||||
Cflag uint32
|
||||
Lflag uint32
|
||||
Cc [20]uint8
|
||||
Ispeed uint32
|
||||
Ospeed uint32
|
||||
}
|
||||
|
||||
const (
|
||||
syscall_IGNBRK = 0x1
|
||||
syscall_BRKINT = 0x2
|
||||
syscall_PARMRK = 0x8
|
||||
syscall_ISTRIP = 0x20
|
||||
syscall_INLCR = 0x40
|
||||
syscall_IGNCR = 0x80
|
||||
syscall_ICRNL = 0x100
|
||||
syscall_IXON = 0x200
|
||||
syscall_OPOST = 0x1
|
||||
syscall_ECHO = 0x8
|
||||
syscall_ECHONL = 0x10
|
||||
syscall_ICANON = 0x100
|
||||
syscall_ISIG = 0x80
|
||||
syscall_IEXTEN = 0x400
|
||||
syscall_CSIZE = 0x300
|
||||
syscall_PARENB = 0x1000
|
||||
syscall_CS8 = 0x300
|
||||
syscall_VMIN = 0x10
|
||||
syscall_VTIME = 0x11
|
||||
|
||||
syscall_TCGETS = 0x402c7413
|
||||
syscall_TCSETS = 0x802c7414
|
||||
)
|
33
vendor/github.com/nsf/termbox-go/syscalls_linux.go
generated
vendored
Normal file
33
vendor/github.com/nsf/termbox-go/syscalls_linux.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs syscalls.go
|
||||
|
||||
package termbox
|
||||
|
||||
import "syscall"
|
||||
|
||||
type syscall_Termios syscall.Termios
|
||||
|
||||
const (
|
||||
syscall_IGNBRK = syscall.IGNBRK
|
||||
syscall_BRKINT = syscall.BRKINT
|
||||
syscall_PARMRK = syscall.PARMRK
|
||||
syscall_ISTRIP = syscall.ISTRIP
|
||||
syscall_INLCR = syscall.INLCR
|
||||
syscall_IGNCR = syscall.IGNCR
|
||||
syscall_ICRNL = syscall.ICRNL
|
||||
syscall_IXON = syscall.IXON
|
||||
syscall_OPOST = syscall.OPOST
|
||||
syscall_ECHO = syscall.ECHO
|
||||
syscall_ECHONL = syscall.ECHONL
|
||||
syscall_ICANON = syscall.ICANON
|
||||
syscall_ISIG = syscall.ISIG
|
||||
syscall_IEXTEN = syscall.IEXTEN
|
||||
syscall_CSIZE = syscall.CSIZE
|
||||
syscall_PARENB = syscall.PARENB
|
||||
syscall_CS8 = syscall.CS8
|
||||
syscall_VMIN = syscall.VMIN
|
||||
syscall_VTIME = syscall.VTIME
|
||||
|
||||
syscall_TCGETS = syscall.TCGETS
|
||||
syscall_TCSETS = syscall.TCSETS
|
||||
)
|
39
vendor/github.com/nsf/termbox-go/syscalls_netbsd.go
generated
vendored
Normal file
39
vendor/github.com/nsf/termbox-go/syscalls_netbsd.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs syscalls.go
|
||||
|
||||
package termbox
|
||||
|
||||
type syscall_Termios struct {
|
||||
Iflag uint32
|
||||
Oflag uint32
|
||||
Cflag uint32
|
||||
Lflag uint32
|
||||
Cc [20]uint8
|
||||
Ispeed int32
|
||||
Ospeed int32
|
||||
}
|
||||
|
||||
const (
|
||||
syscall_IGNBRK = 0x1
|
||||
syscall_BRKINT = 0x2
|
||||
syscall_PARMRK = 0x8
|
||||
syscall_ISTRIP = 0x20
|
||||
syscall_INLCR = 0x40
|
||||
syscall_IGNCR = 0x80
|
||||
syscall_ICRNL = 0x100
|
||||
syscall_IXON = 0x200
|
||||
syscall_OPOST = 0x1
|
||||
syscall_ECHO = 0x8
|
||||
syscall_ECHONL = 0x10
|
||||
syscall_ICANON = 0x100
|
||||
syscall_ISIG = 0x80
|
||||
syscall_IEXTEN = 0x400
|
||||
syscall_CSIZE = 0x300
|
||||
syscall_PARENB = 0x1000
|
||||
syscall_CS8 = 0x300
|
||||
syscall_VMIN = 0x10
|
||||
syscall_VTIME = 0x11
|
||||
|
||||
syscall_TCGETS = 0x402c7413
|
||||
syscall_TCSETS = 0x802c7414
|
||||
)
|
39
vendor/github.com/nsf/termbox-go/syscalls_openbsd.go
generated
vendored
Normal file
39
vendor/github.com/nsf/termbox-go/syscalls_openbsd.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs syscalls.go
|
||||
|
||||
package termbox
|
||||
|
||||
type syscall_Termios struct {
|
||||
Iflag uint32
|
||||
Oflag uint32
|
||||
Cflag uint32
|
||||
Lflag uint32
|
||||
Cc [20]uint8
|
||||
Ispeed int32
|
||||
Ospeed int32
|
||||
}
|
||||
|
||||
const (
|
||||
syscall_IGNBRK = 0x1
|
||||
syscall_BRKINT = 0x2
|
||||
syscall_PARMRK = 0x8
|
||||
syscall_ISTRIP = 0x20
|
||||
syscall_INLCR = 0x40
|
||||
syscall_IGNCR = 0x80
|
||||
syscall_ICRNL = 0x100
|
||||
syscall_IXON = 0x200
|
||||
syscall_OPOST = 0x1
|
||||
syscall_ECHO = 0x8
|
||||
syscall_ECHONL = 0x10
|
||||
syscall_ICANON = 0x100
|
||||
syscall_ISIG = 0x80
|
||||
syscall_IEXTEN = 0x400
|
||||
syscall_CSIZE = 0x300
|
||||
syscall_PARENB = 0x1000
|
||||
syscall_CS8 = 0x300
|
||||
syscall_VMIN = 0x10
|
||||
syscall_VTIME = 0x11
|
||||
|
||||
syscall_TCGETS = 0x402c7413
|
||||
syscall_TCSETS = 0x802c7414
|
||||
)
|
61
vendor/github.com/nsf/termbox-go/syscalls_windows.go
generated
vendored
Normal file
61
vendor/github.com/nsf/termbox-go/syscalls_windows.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs -- -DUNICODE syscalls.go
|
||||
|
||||
package termbox
|
||||
|
||||
const (
|
||||
foreground_blue = 0x1
|
||||
foreground_green = 0x2
|
||||
foreground_red = 0x4
|
||||
foreground_intensity = 0x8
|
||||
background_blue = 0x10
|
||||
background_green = 0x20
|
||||
background_red = 0x40
|
||||
background_intensity = 0x80
|
||||
std_input_handle = -0xa
|
||||
std_output_handle = -0xb
|
||||
key_event = 0x1
|
||||
mouse_event = 0x2
|
||||
window_buffer_size_event = 0x4
|
||||
enable_window_input = 0x8
|
||||
enable_mouse_input = 0x10
|
||||
enable_extended_flags = 0x80
|
||||
|
||||
vk_f1 = 0x70
|
||||
vk_f2 = 0x71
|
||||
vk_f3 = 0x72
|
||||
vk_f4 = 0x73
|
||||
vk_f5 = 0x74
|
||||
vk_f6 = 0x75
|
||||
vk_f7 = 0x76
|
||||
vk_f8 = 0x77
|
||||
vk_f9 = 0x78
|
||||
vk_f10 = 0x79
|
||||
vk_f11 = 0x7a
|
||||
vk_f12 = 0x7b
|
||||
vk_insert = 0x2d
|
||||
vk_delete = 0x2e
|
||||
vk_home = 0x24
|
||||
vk_end = 0x23
|
||||
vk_pgup = 0x21
|
||||
vk_pgdn = 0x22
|
||||
vk_arrow_up = 0x26
|
||||
vk_arrow_down = 0x28
|
||||
vk_arrow_left = 0x25
|
||||
vk_arrow_right = 0x27
|
||||
vk_backspace = 0x8
|
||||
vk_tab = 0x9
|
||||
vk_enter = 0xd
|
||||
vk_esc = 0x1b
|
||||
vk_space = 0x20
|
||||
|
||||
left_alt_pressed = 0x2
|
||||
left_ctrl_pressed = 0x8
|
||||
right_alt_pressed = 0x1
|
||||
right_ctrl_pressed = 0x4
|
||||
shift_pressed = 0x10
|
||||
|
||||
generic_read = 0x80000000
|
||||
generic_write = 0x40000000
|
||||
console_textmode_buffer = 0x1
|
||||
)
|
511
vendor/github.com/nsf/termbox-go/termbox.go
generated
vendored
Normal file
511
vendor/github.com/nsf/termbox-go/termbox.go
generated
vendored
Normal file
@ -0,0 +1,511 @@
|
||||
// +build !windows
|
||||
|
||||
package termbox
|
||||
|
||||
import "unicode/utf8"
|
||||
import "bytes"
|
||||
import "syscall"
|
||||
import "unsafe"
|
||||
import "strings"
|
||||
import "strconv"
|
||||
import "os"
|
||||
import "io"
|
||||
|
||||
// private API
|
||||
|
||||
const (
|
||||
t_enter_ca = iota
|
||||
t_exit_ca
|
||||
t_show_cursor
|
||||
t_hide_cursor
|
||||
t_clear_screen
|
||||
t_sgr0
|
||||
t_underline
|
||||
t_bold
|
||||
t_blink
|
||||
t_reverse
|
||||
t_enter_keypad
|
||||
t_exit_keypad
|
||||
t_enter_mouse
|
||||
t_exit_mouse
|
||||
t_max_funcs
|
||||
)
|
||||
|
||||
const (
|
||||
coord_invalid = -2
|
||||
attr_invalid = Attribute(0xFFFF)
|
||||
)
|
||||
|
||||
type input_event struct {
|
||||
data []byte
|
||||
err error
|
||||
}
|
||||
|
||||
var (
|
||||
// term specific sequences
|
||||
keys []string
|
||||
funcs []string
|
||||
|
||||
// termbox inner state
|
||||
orig_tios syscall_Termios
|
||||
back_buffer cellbuf
|
||||
front_buffer cellbuf
|
||||
termw int
|
||||
termh int
|
||||
input_mode = InputEsc
|
||||
output_mode = OutputNormal
|
||||
out *os.File
|
||||
in int
|
||||
lastfg = attr_invalid
|
||||
lastbg = attr_invalid
|
||||
lastx = coord_invalid
|
||||
lasty = coord_invalid
|
||||
cursor_x = cursor_hidden
|
||||
cursor_y = cursor_hidden
|
||||
foreground = ColorDefault
|
||||
background = ColorDefault
|
||||
inbuf = make([]byte, 0, 64)
|
||||
outbuf bytes.Buffer
|
||||
sigwinch = make(chan os.Signal, 1)
|
||||
sigio = make(chan os.Signal, 1)
|
||||
quit = make(chan int)
|
||||
input_comm = make(chan input_event)
|
||||
interrupt_comm = make(chan struct{})
|
||||
intbuf = make([]byte, 0, 16)
|
||||
|
||||
// grayscale indexes
|
||||
grayscale = []Attribute{
|
||||
0, 17, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244,
|
||||
245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 232,
|
||||
}
|
||||
)
|
||||
|
||||
func write_cursor(x, y int) {
|
||||
outbuf.WriteString("\033[")
|
||||
outbuf.Write(strconv.AppendUint(intbuf, uint64(y+1), 10))
|
||||
outbuf.WriteString(";")
|
||||
outbuf.Write(strconv.AppendUint(intbuf, uint64(x+1), 10))
|
||||
outbuf.WriteString("H")
|
||||
}
|
||||
|
||||
func write_sgr_fg(a Attribute) {
|
||||
switch output_mode {
|
||||
case Output256, Output216, OutputGrayscale:
|
||||
outbuf.WriteString("\033[38;5;")
|
||||
outbuf.Write(strconv.AppendUint(intbuf, uint64(a-1), 10))
|
||||
outbuf.WriteString("m")
|
||||
default:
|
||||
outbuf.WriteString("\033[3")
|
||||
outbuf.Write(strconv.AppendUint(intbuf, uint64(a-1), 10))
|
||||
outbuf.WriteString("m")
|
||||
}
|
||||
}
|
||||
|
||||
func write_sgr_bg(a Attribute) {
|
||||
switch output_mode {
|
||||
case Output256, Output216, OutputGrayscale:
|
||||
outbuf.WriteString("\033[48;5;")
|
||||
outbuf.Write(strconv.AppendUint(intbuf, uint64(a-1), 10))
|
||||
outbuf.WriteString("m")
|
||||
default:
|
||||
outbuf.WriteString("\033[4")
|
||||
outbuf.Write(strconv.AppendUint(intbuf, uint64(a-1), 10))
|
||||
outbuf.WriteString("m")
|
||||
}
|
||||
}
|
||||
|
||||
func write_sgr(fg, bg Attribute) {
|
||||
switch output_mode {
|
||||
case Output256, Output216, OutputGrayscale:
|
||||
outbuf.WriteString("\033[38;5;")
|
||||
outbuf.Write(strconv.AppendUint(intbuf, uint64(fg-1), 10))
|
||||
outbuf.WriteString("m")
|
||||
outbuf.WriteString("\033[48;5;")
|
||||
outbuf.Write(strconv.AppendUint(intbuf, uint64(bg-1), 10))
|
||||
outbuf.WriteString("m")
|
||||
default:
|
||||
outbuf.WriteString("\033[3")
|
||||
outbuf.Write(strconv.AppendUint(intbuf, uint64(fg-1), 10))
|
||||
outbuf.WriteString(";4")
|
||||
outbuf.Write(strconv.AppendUint(intbuf, uint64(bg-1), 10))
|
||||
outbuf.WriteString("m")
|
||||
}
|
||||
}
|
||||
|
||||
type winsize struct {
|
||||
rows uint16
|
||||
cols uint16
|
||||
xpixels uint16
|
||||
ypixels uint16
|
||||
}
|
||||
|
||||
func get_term_size(fd uintptr) (int, int) {
|
||||
var sz winsize
|
||||
_, _, _ = syscall.Syscall(syscall.SYS_IOCTL,
|
||||
fd, uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&sz)))
|
||||
return int(sz.cols), int(sz.rows)
|
||||
}
|
||||
|
||||
func send_attr(fg, bg Attribute) {
|
||||
if fg == lastfg && bg == lastbg {
|
||||
return
|
||||
}
|
||||
|
||||
outbuf.WriteString(funcs[t_sgr0])
|
||||
|
||||
var fgcol, bgcol Attribute
|
||||
|
||||
switch output_mode {
|
||||
case Output256:
|
||||
fgcol = fg & 0x1FF
|
||||
bgcol = bg & 0x1FF
|
||||
case Output216:
|
||||
fgcol = fg & 0xFF
|
||||
bgcol = bg & 0xFF
|
||||
if fgcol > 216 {
|
||||
fgcol = ColorDefault
|
||||
}
|
||||
if bgcol > 216 {
|
||||
bgcol = ColorDefault
|
||||
}
|
||||
if fgcol != ColorDefault {
|
||||
fgcol += 0x10
|
||||
}
|
||||
if bgcol != ColorDefault {
|
||||
bgcol += 0x10
|
||||
}
|
||||
case OutputGrayscale:
|
||||
fgcol = fg & 0x1F
|
||||
bgcol = bg & 0x1F
|
||||
if fgcol > 26 {
|
||||
fgcol = ColorDefault
|
||||
}
|
||||
if bgcol > 26 {
|
||||
bgcol = ColorDefault
|
||||
}
|
||||
if fgcol != ColorDefault {
|
||||
fgcol = grayscale[fgcol]
|
||||
}
|
||||
if bgcol != ColorDefault {
|
||||
bgcol = grayscale[bgcol]
|
||||
}
|
||||
default:
|
||||
fgcol = fg & 0x0F
|
||||
bgcol = bg & 0x0F
|
||||
}
|
||||
|
||||
if fgcol != ColorDefault {
|
||||
if bgcol != ColorDefault {
|
||||
write_sgr(fgcol, bgcol)
|
||||
} else {
|
||||
write_sgr_fg(fgcol)
|
||||
}
|
||||
} else if bgcol != ColorDefault {
|
||||
write_sgr_bg(bgcol)
|
||||
}
|
||||
|
||||
if fg&AttrBold != 0 {
|
||||
outbuf.WriteString(funcs[t_bold])
|
||||
}
|
||||
if bg&AttrBold != 0 {
|
||||
outbuf.WriteString(funcs[t_blink])
|
||||
}
|
||||
if fg&AttrUnderline != 0 {
|
||||
outbuf.WriteString(funcs[t_underline])
|
||||
}
|
||||
if fg&AttrReverse|bg&AttrReverse != 0 {
|
||||
outbuf.WriteString(funcs[t_reverse])
|
||||
}
|
||||
|
||||
lastfg, lastbg = fg, bg
|
||||
}
|
||||
|
||||
func send_char(x, y int, ch rune) {
|
||||
var buf [8]byte
|
||||
n := utf8.EncodeRune(buf[:], ch)
|
||||
if x-1 != lastx || y != lasty {
|
||||
write_cursor(x, y)
|
||||
}
|
||||
lastx, lasty = x, y
|
||||
outbuf.Write(buf[:n])
|
||||
}
|
||||
|
||||
func flush() error {
|
||||
_, err := io.Copy(out, &outbuf)
|
||||
outbuf.Reset()
|
||||
return err
|
||||
}
|
||||
|
||||
func send_clear() error {
|
||||
send_attr(foreground, background)
|
||||
outbuf.WriteString(funcs[t_clear_screen])
|
||||
if !is_cursor_hidden(cursor_x, cursor_y) {
|
||||
write_cursor(cursor_x, cursor_y)
|
||||
}
|
||||
|
||||
// we need to invalidate cursor position too and these two vars are
|
||||
// used only for simple cursor positioning optimization, cursor
|
||||
// actually may be in the correct place, but we simply discard
|
||||
// optimization once and it gives us simple solution for the case when
|
||||
// cursor moved
|
||||
lastx = coord_invalid
|
||||
lasty = coord_invalid
|
||||
|
||||
return flush()
|
||||
}
|
||||
|
||||
func update_size_maybe() error {
|
||||
w, h := get_term_size(out.Fd())
|
||||
if w != termw || h != termh {
|
||||
termw, termh = w, h
|
||||
back_buffer.resize(termw, termh)
|
||||
front_buffer.resize(termw, termh)
|
||||
front_buffer.clear()
|
||||
return send_clear()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func tcsetattr(fd uintptr, termios *syscall_Termios) error {
|
||||
r, _, e := syscall.Syscall(syscall.SYS_IOCTL,
|
||||
fd, uintptr(syscall_TCSETS), uintptr(unsafe.Pointer(termios)))
|
||||
if r != 0 {
|
||||
return os.NewSyscallError("SYS_IOCTL", e)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func tcgetattr(fd uintptr, termios *syscall_Termios) error {
|
||||
r, _, e := syscall.Syscall(syscall.SYS_IOCTL,
|
||||
fd, uintptr(syscall_TCGETS), uintptr(unsafe.Pointer(termios)))
|
||||
if r != 0 {
|
||||
return os.NewSyscallError("SYS_IOCTL", e)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parse_mouse_event(event *Event, buf string) (int, bool) {
|
||||
if strings.HasPrefix(buf, "\033[M") && len(buf) >= 6 {
|
||||
// X10 mouse encoding, the simplest one
|
||||
// \033 [ M Cb Cx Cy
|
||||
b := buf[3] - 32
|
||||
switch b & 3 {
|
||||
case 0:
|
||||
if b&64 != 0 {
|
||||
event.Key = MouseWheelUp
|
||||
} else {
|
||||
event.Key = MouseLeft
|
||||
}
|
||||
case 1:
|
||||
if b&64 != 0 {
|
||||
event.Key = MouseWheelDown
|
||||
} else {
|
||||
event.Key = MouseMiddle
|
||||
}
|
||||
case 2:
|
||||
event.Key = MouseRight
|
||||
case 3:
|
||||
event.Key = MouseRelease
|
||||
default:
|
||||
return 6, false
|
||||
}
|
||||
event.Type = EventMouse // KeyEvent by default
|
||||
if b&32 != 0 {
|
||||
event.Mod |= ModMotion
|
||||
}
|
||||
|
||||
// the coord is 1,1 for upper left
|
||||
event.MouseX = int(buf[4]) - 1 - 32
|
||||
event.MouseY = int(buf[5]) - 1 - 32
|
||||
return 6, true
|
||||
} else if strings.HasPrefix(buf, "\033[<") || strings.HasPrefix(buf, "\033[") {
|
||||
// xterm 1006 extended mode or urxvt 1015 extended mode
|
||||
// xterm: \033 [ < Cb ; Cx ; Cy (M or m)
|
||||
// urxvt: \033 [ Cb ; Cx ; Cy M
|
||||
|
||||
// find the first M or m, that's where we stop
|
||||
mi := strings.IndexAny(buf, "Mm")
|
||||
if mi == -1 {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// whether it's a capital M or not
|
||||
isM := buf[mi] == 'M'
|
||||
|
||||
// whether it's urxvt or not
|
||||
isU := false
|
||||
|
||||
// buf[2] is safe here, because having M or m found means we have at
|
||||
// least 3 bytes in a string
|
||||
if buf[2] == '<' {
|
||||
buf = buf[3:mi]
|
||||
} else {
|
||||
isU = true
|
||||
buf = buf[2:mi]
|
||||
}
|
||||
|
||||
s1 := strings.Index(buf, ";")
|
||||
s2 := strings.LastIndex(buf, ";")
|
||||
// not found or only one ';'
|
||||
if s1 == -1 || s2 == -1 || s1 == s2 {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
n1, err := strconv.ParseInt(buf[0:s1], 10, 64)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
n2, err := strconv.ParseInt(buf[s1+1:s2], 10, 64)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
n3, err := strconv.ParseInt(buf[s2+1:], 10, 64)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// on urxvt, first number is encoded exactly as in X10, but we need to
|
||||
// make it zero-based, on xterm it is zero-based already
|
||||
if isU {
|
||||
n1 -= 32
|
||||
}
|
||||
switch n1 & 3 {
|
||||
case 0:
|
||||
if n1&64 != 0 {
|
||||
event.Key = MouseWheelUp
|
||||
} else {
|
||||
event.Key = MouseLeft
|
||||
}
|
||||
case 1:
|
||||
if n1&64 != 0 {
|
||||
event.Key = MouseWheelDown
|
||||
} else {
|
||||
event.Key = MouseMiddle
|
||||
}
|
||||
case 2:
|
||||
event.Key = MouseRight
|
||||
case 3:
|
||||
event.Key = MouseRelease
|
||||
default:
|
||||
return mi + 1, false
|
||||
}
|
||||
if !isM {
|
||||
// on xterm mouse release is signaled by lowercase m
|
||||
event.Key = MouseRelease
|
||||
}
|
||||
|
||||
event.Type = EventMouse // KeyEvent by default
|
||||
if n1&32 != 0 {
|
||||
event.Mod |= ModMotion
|
||||
}
|
||||
|
||||
event.MouseX = int(n2) - 1
|
||||
event.MouseY = int(n3) - 1
|
||||
return mi + 1, true
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func parse_escape_sequence(event *Event, buf []byte) (int, bool) {
|
||||
bufstr := string(buf)
|
||||
for i, key := range keys {
|
||||
if strings.HasPrefix(bufstr, key) {
|
||||
event.Ch = 0
|
||||
event.Key = Key(0xFFFF - i)
|
||||
return len(key), true
|
||||
}
|
||||
}
|
||||
|
||||
// if none of the keys match, let's try mouse seqences
|
||||
return parse_mouse_event(event, bufstr)
|
||||
}
|
||||
|
||||
func extract_raw_event(data []byte, event *Event) bool {
|
||||
if len(inbuf) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
n := len(data)
|
||||
if n == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
n = copy(data, inbuf)
|
||||
copy(inbuf, inbuf[n:])
|
||||
inbuf = inbuf[:len(inbuf)-n]
|
||||
|
||||
event.N = n
|
||||
event.Type = EventRaw
|
||||
return true
|
||||
}
|
||||
|
||||
func extract_event(inbuf []byte, event *Event) bool {
|
||||
if len(inbuf) == 0 {
|
||||
event.N = 0
|
||||
return false
|
||||
}
|
||||
|
||||
if inbuf[0] == '\033' {
|
||||
// possible escape sequence
|
||||
if n, ok := parse_escape_sequence(event, inbuf); n != 0 {
|
||||
event.N = n
|
||||
return ok
|
||||
}
|
||||
|
||||
// it's not escape sequence, then it's Alt or Esc, check input_mode
|
||||
switch {
|
||||
case input_mode&InputEsc != 0:
|
||||
// if we're in escape mode, fill Esc event, pop buffer, return success
|
||||
event.Ch = 0
|
||||
event.Key = KeyEsc
|
||||
event.Mod = 0
|
||||
event.N = 1
|
||||
return true
|
||||
case input_mode&InputAlt != 0:
|
||||
// if we're in alt mode, set Alt modifier to event and redo parsing
|
||||
event.Mod = ModAlt
|
||||
ok := extract_event(inbuf[1:], event)
|
||||
if ok {
|
||||
event.N++
|
||||
} else {
|
||||
event.N = 0
|
||||
}
|
||||
return ok
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
// if we're here, this is not an escape sequence and not an alt sequence
|
||||
// so, it's a FUNCTIONAL KEY or a UNICODE character
|
||||
|
||||
// first of all check if it's a functional key
|
||||
if Key(inbuf[0]) <= KeySpace || Key(inbuf[0]) == KeyBackspace2 {
|
||||
// fill event, pop buffer, return success
|
||||
event.Ch = 0
|
||||
event.Key = Key(inbuf[0])
|
||||
event.N = 1
|
||||
return true
|
||||
}
|
||||
|
||||
// the only possible option is utf8 rune
|
||||
if r, n := utf8.DecodeRune(inbuf); r != utf8.RuneError {
|
||||
event.Ch = r
|
||||
event.Key = 0
|
||||
event.N = n
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func fcntl(fd int, cmd int, arg int) (val int, err error) {
|
||||
r, _, e := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), uintptr(cmd),
|
||||
uintptr(arg))
|
||||
val = int(r)
|
||||
if e != 0 {
|
||||
err = e
|
||||
}
|
||||
return
|
||||
}
|
59
vendor/github.com/nsf/termbox-go/termbox_common.go
generated
vendored
Normal file
59
vendor/github.com/nsf/termbox-go/termbox_common.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
package termbox
|
||||
|
||||
// private API, common OS agnostic part
|
||||
|
||||
type cellbuf struct {
|
||||
width int
|
||||
height int
|
||||
cells []Cell
|
||||
}
|
||||
|
||||
func (this *cellbuf) init(width, height int) {
|
||||
this.width = width
|
||||
this.height = height
|
||||
this.cells = make([]Cell, width*height)
|
||||
}
|
||||
|
||||
func (this *cellbuf) resize(width, height int) {
|
||||
if this.width == width && this.height == height {
|
||||
return
|
||||
}
|
||||
|
||||
oldw := this.width
|
||||
oldh := this.height
|
||||
oldcells := this.cells
|
||||
|
||||
this.init(width, height)
|
||||
this.clear()
|
||||
|
||||
minw, minh := oldw, oldh
|
||||
|
||||
if width < minw {
|
||||
minw = width
|
||||
}
|
||||
if height < minh {
|
||||
minh = height
|
||||
}
|
||||
|
||||
for i := 0; i < minh; i++ {
|
||||
srco, dsto := i*oldw, i*width
|
||||
src := oldcells[srco : srco+minw]
|
||||
dst := this.cells[dsto : dsto+minw]
|
||||
copy(dst, src)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *cellbuf) clear() {
|
||||
for i := range this.cells {
|
||||
c := &this.cells[i]
|
||||
c.Ch = ' '
|
||||
c.Fg = foreground
|
||||
c.Bg = background
|
||||
}
|
||||
}
|
||||
|
||||
const cursor_hidden = -1
|
||||
|
||||
func is_cursor_hidden(x, y int) bool {
|
||||
return x == cursor_hidden || y == cursor_hidden
|
||||
}
|
856
vendor/github.com/nsf/termbox-go/termbox_windows.go
generated
vendored
Normal file
856
vendor/github.com/nsf/termbox-go/termbox_windows.go
generated
vendored
Normal file
@ -0,0 +1,856 @@
|
||||
package termbox
|
||||
|
||||
import "syscall"
|
||||
import "unsafe"
|
||||
import "unicode/utf16"
|
||||
import "github.com/mattn/go-runewidth"
|
||||
|
||||
type (
|
||||
wchar uint16
|
||||
short int16
|
||||
dword uint32
|
||||
word uint16
|
||||
char_info struct {
|
||||
char wchar
|
||||
attr word
|
||||
}
|
||||
coord struct {
|
||||
x short
|
||||
y short
|
||||
}
|
||||
small_rect struct {
|
||||
left short
|
||||
top short
|
||||
right short
|
||||
bottom short
|
||||
}
|
||||
console_screen_buffer_info struct {
|
||||
size coord
|
||||
cursor_position coord
|
||||
attributes word
|
||||
window small_rect
|
||||
maximum_window_size coord
|
||||
}
|
||||
console_cursor_info struct {
|
||||
size dword
|
||||
visible int32
|
||||
}
|
||||
input_record struct {
|
||||
event_type word
|
||||
_ [2]byte
|
||||
event [16]byte
|
||||
}
|
||||
key_event_record struct {
|
||||
key_down int32
|
||||
repeat_count word
|
||||
virtual_key_code word
|
||||
virtual_scan_code word
|
||||
unicode_char wchar
|
||||
control_key_state dword
|
||||
}
|
||||
window_buffer_size_record struct {
|
||||
size coord
|
||||
}
|
||||
mouse_event_record struct {
|
||||
mouse_pos coord
|
||||
button_state dword
|
||||
control_key_state dword
|
||||
event_flags dword
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
mouse_lmb = 0x1
|
||||
mouse_rmb = 0x2
|
||||
mouse_mmb = 0x4 | 0x8 | 0x10
|
||||
)
|
||||
|
||||
func (this coord) uintptr() uintptr {
|
||||
return uintptr(*(*int32)(unsafe.Pointer(&this)))
|
||||
}
|
||||
|
||||
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
var is_cjk = runewidth.IsEastAsian()
|
||||
|
||||
var (
|
||||
proc_set_console_active_screen_buffer = kernel32.NewProc("SetConsoleActiveScreenBuffer")
|
||||
proc_set_console_screen_buffer_size = kernel32.NewProc("SetConsoleScreenBufferSize")
|
||||
proc_create_console_screen_buffer = kernel32.NewProc("CreateConsoleScreenBuffer")
|
||||
proc_get_console_screen_buffer_info = kernel32.NewProc("GetConsoleScreenBufferInfo")
|
||||
proc_write_console_output = kernel32.NewProc("WriteConsoleOutputW")
|
||||
proc_write_console_output_character = kernel32.NewProc("WriteConsoleOutputCharacterW")
|
||||
proc_write_console_output_attribute = kernel32.NewProc("WriteConsoleOutputAttribute")
|
||||
proc_set_console_cursor_info = kernel32.NewProc("SetConsoleCursorInfo")
|
||||
proc_set_console_cursor_position = kernel32.NewProc("SetConsoleCursorPosition")
|
||||
proc_get_console_cursor_info = kernel32.NewProc("GetConsoleCursorInfo")
|
||||
proc_read_console_input = kernel32.NewProc("ReadConsoleInputW")
|
||||
proc_get_console_mode = kernel32.NewProc("GetConsoleMode")
|
||||
proc_set_console_mode = kernel32.NewProc("SetConsoleMode")
|
||||
proc_fill_console_output_character = kernel32.NewProc("FillConsoleOutputCharacterW")
|
||||
proc_fill_console_output_attribute = kernel32.NewProc("FillConsoleOutputAttribute")
|
||||
proc_create_event = kernel32.NewProc("CreateEventW")
|
||||
proc_wait_for_multiple_objects = kernel32.NewProc("WaitForMultipleObjects")
|
||||
proc_set_event = kernel32.NewProc("SetEvent")
|
||||
)
|
||||
|
||||
func set_console_active_screen_buffer(h syscall.Handle) (err error) {
|
||||
r0, _, e1 := syscall.Syscall(proc_set_console_active_screen_buffer.Addr(),
|
||||
1, uintptr(h), 0, 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func set_console_screen_buffer_size(h syscall.Handle, size coord) (err error) {
|
||||
r0, _, e1 := syscall.Syscall(proc_set_console_screen_buffer_size.Addr(),
|
||||
2, uintptr(h), size.uintptr(), 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func create_console_screen_buffer() (h syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall6(proc_create_console_screen_buffer.Addr(),
|
||||
5, uintptr(generic_read|generic_write), 0, 0, console_textmode_buffer, 0, 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return syscall.Handle(r0), err
|
||||
}
|
||||
|
||||
func get_console_screen_buffer_info(h syscall.Handle, info *console_screen_buffer_info) (err error) {
|
||||
r0, _, e1 := syscall.Syscall(proc_get_console_screen_buffer_info.Addr(),
|
||||
2, uintptr(h), uintptr(unsafe.Pointer(info)), 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func write_console_output(h syscall.Handle, chars []char_info, dst small_rect) (err error) {
|
||||
tmp_coord = coord{dst.right - dst.left + 1, dst.bottom - dst.top + 1}
|
||||
tmp_rect = dst
|
||||
r0, _, e1 := syscall.Syscall6(proc_write_console_output.Addr(),
|
||||
5, uintptr(h), uintptr(unsafe.Pointer(&chars[0])), tmp_coord.uintptr(),
|
||||
tmp_coord0.uintptr(), uintptr(unsafe.Pointer(&tmp_rect)), 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func write_console_output_character(h syscall.Handle, chars []wchar, pos coord) (err error) {
|
||||
r0, _, e1 := syscall.Syscall6(proc_write_console_output_character.Addr(),
|
||||
5, uintptr(h), uintptr(unsafe.Pointer(&chars[0])), uintptr(len(chars)),
|
||||
pos.uintptr(), uintptr(unsafe.Pointer(&tmp_arg)), 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func write_console_output_attribute(h syscall.Handle, attrs []word, pos coord) (err error) {
|
||||
r0, _, e1 := syscall.Syscall6(proc_write_console_output_attribute.Addr(),
|
||||
5, uintptr(h), uintptr(unsafe.Pointer(&attrs[0])), uintptr(len(attrs)),
|
||||
pos.uintptr(), uintptr(unsafe.Pointer(&tmp_arg)), 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func set_console_cursor_info(h syscall.Handle, info *console_cursor_info) (err error) {
|
||||
r0, _, e1 := syscall.Syscall(proc_set_console_cursor_info.Addr(),
|
||||
2, uintptr(h), uintptr(unsafe.Pointer(info)), 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func get_console_cursor_info(h syscall.Handle, info *console_cursor_info) (err error) {
|
||||
r0, _, e1 := syscall.Syscall(proc_get_console_cursor_info.Addr(),
|
||||
2, uintptr(h), uintptr(unsafe.Pointer(info)), 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func set_console_cursor_position(h syscall.Handle, pos coord) (err error) {
|
||||
r0, _, e1 := syscall.Syscall(proc_set_console_cursor_position.Addr(),
|
||||
2, uintptr(h), pos.uintptr(), 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func read_console_input(h syscall.Handle, record *input_record) (err error) {
|
||||
r0, _, e1 := syscall.Syscall6(proc_read_console_input.Addr(),
|
||||
4, uintptr(h), uintptr(unsafe.Pointer(record)), 1, uintptr(unsafe.Pointer(&tmp_arg)), 0, 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func get_console_mode(h syscall.Handle, mode *dword) (err error) {
|
||||
r0, _, e1 := syscall.Syscall(proc_get_console_mode.Addr(),
|
||||
2, uintptr(h), uintptr(unsafe.Pointer(mode)), 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func set_console_mode(h syscall.Handle, mode dword) (err error) {
|
||||
r0, _, e1 := syscall.Syscall(proc_set_console_mode.Addr(),
|
||||
2, uintptr(h), uintptr(mode), 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func fill_console_output_character(h syscall.Handle, char wchar, n int) (err error) {
|
||||
r0, _, e1 := syscall.Syscall6(proc_fill_console_output_character.Addr(),
|
||||
5, uintptr(h), uintptr(char), uintptr(n), tmp_coord.uintptr(),
|
||||
uintptr(unsafe.Pointer(&tmp_arg)), 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func fill_console_output_attribute(h syscall.Handle, attr word, n int) (err error) {
|
||||
r0, _, e1 := syscall.Syscall6(proc_fill_console_output_attribute.Addr(),
|
||||
5, uintptr(h), uintptr(attr), uintptr(n), tmp_coord.uintptr(),
|
||||
uintptr(unsafe.Pointer(&tmp_arg)), 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func create_event() (out syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall6(proc_create_event.Addr(),
|
||||
4, 0, 0, 0, 0, 0, 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return syscall.Handle(r0), err
|
||||
}
|
||||
|
||||
func wait_for_multiple_objects(objects []syscall.Handle) (err error) {
|
||||
r0, _, e1 := syscall.Syscall6(proc_wait_for_multiple_objects.Addr(),
|
||||
4, uintptr(len(objects)), uintptr(unsafe.Pointer(&objects[0])),
|
||||
0, 0xFFFFFFFF, 0, 0)
|
||||
if uint32(r0) == 0xFFFFFFFF {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func set_event(ev syscall.Handle) (err error) {
|
||||
r0, _, e1 := syscall.Syscall(proc_set_event.Addr(),
|
||||
1, uintptr(ev), 0, 0)
|
||||
if int(r0) == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type diff_msg struct {
|
||||
pos short
|
||||
lines short
|
||||
chars []char_info
|
||||
}
|
||||
|
||||
type input_event struct {
|
||||
event Event
|
||||
err error
|
||||
}
|
||||
|
||||
var (
|
||||
orig_cursor_info console_cursor_info
|
||||
orig_size coord
|
||||
orig_mode dword
|
||||
orig_screen syscall.Handle
|
||||
back_buffer cellbuf
|
||||
front_buffer cellbuf
|
||||
term_size coord
|
||||
input_mode = InputEsc
|
||||
cursor_x = cursor_hidden
|
||||
cursor_y = cursor_hidden
|
||||
foreground = ColorDefault
|
||||
background = ColorDefault
|
||||
in syscall.Handle
|
||||
out syscall.Handle
|
||||
interrupt syscall.Handle
|
||||
charbuf []char_info
|
||||
diffbuf []diff_msg
|
||||
beg_x = -1
|
||||
beg_y = -1
|
||||
beg_i = -1
|
||||
input_comm = make(chan Event)
|
||||
interrupt_comm = make(chan struct{})
|
||||
cancel_comm = make(chan bool, 1)
|
||||
cancel_done_comm = make(chan bool)
|
||||
alt_mode_esc = false
|
||||
|
||||
// these ones just to prevent heap allocs at all costs
|
||||
tmp_info console_screen_buffer_info
|
||||
tmp_arg dword
|
||||
tmp_coord0 = coord{0, 0}
|
||||
tmp_coord = coord{0, 0}
|
||||
tmp_rect = small_rect{0, 0, 0, 0}
|
||||
)
|
||||
|
||||
func get_cursor_position(out syscall.Handle) coord {
|
||||
err := get_console_screen_buffer_info(out, &tmp_info)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return tmp_info.cursor_position
|
||||
}
|
||||
|
||||
func get_term_size(out syscall.Handle) coord {
|
||||
err := get_console_screen_buffer_info(out, &tmp_info)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return tmp_info.size
|
||||
}
|
||||
|
||||
func get_win_size(out syscall.Handle) coord {
|
||||
err := get_console_screen_buffer_info(out, &tmp_info)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return coord{
|
||||
x: tmp_info.window.right - tmp_info.window.left + 1,
|
||||
y: tmp_info.window.bottom - tmp_info.window.top + 1,
|
||||
}
|
||||
}
|
||||
|
||||
func update_size_maybe() {
|
||||
size := get_term_size(out)
|
||||
if size.x != term_size.x || size.y != term_size.y {
|
||||
term_size = size
|
||||
back_buffer.resize(int(size.x), int(size.y))
|
||||
front_buffer.resize(int(size.x), int(size.y))
|
||||
front_buffer.clear()
|
||||
clear()
|
||||
|
||||
area := int(size.x) * int(size.y)
|
||||
if cap(charbuf) < area {
|
||||
charbuf = make([]char_info, 0, area)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var color_table_bg = []word{
|
||||
0, // default (black)
|
||||
0, // black
|
||||
background_red,
|
||||
background_green,
|
||||
background_red | background_green, // yellow
|
||||
background_blue,
|
||||
background_red | background_blue, // magenta
|
||||
background_green | background_blue, // cyan
|
||||
background_red | background_blue | background_green, // white
|
||||
}
|
||||
|
||||
var color_table_fg = []word{
|
||||
foreground_red | foreground_blue | foreground_green, // default (white)
|
||||
0,
|
||||
foreground_red,
|
||||
foreground_green,
|
||||
foreground_red | foreground_green, // yellow
|
||||
foreground_blue,
|
||||
foreground_red | foreground_blue, // magenta
|
||||
foreground_green | foreground_blue, // cyan
|
||||
foreground_red | foreground_blue | foreground_green, // white
|
||||
}
|
||||
|
||||
const (
|
||||
replacement_char = '\uFFFD'
|
||||
max_rune = '\U0010FFFF'
|
||||
surr1 = 0xd800
|
||||
surr2 = 0xdc00
|
||||
surr3 = 0xe000
|
||||
surr_self = 0x10000
|
||||
)
|
||||
|
||||
func append_diff_line(y int) int {
|
||||
n := 0
|
||||
for x := 0; x < front_buffer.width; {
|
||||
cell_offset := y*front_buffer.width + x
|
||||
back := &back_buffer.cells[cell_offset]
|
||||
front := &front_buffer.cells[cell_offset]
|
||||
attr, char := cell_to_char_info(*back)
|
||||
charbuf = append(charbuf, char_info{attr: attr, char: char[0]})
|
||||
*front = *back
|
||||
n++
|
||||
w := runewidth.RuneWidth(back.Ch)
|
||||
if w == 0 || w == 2 && runewidth.IsAmbiguousWidth(back.Ch) {
|
||||
w = 1
|
||||
}
|
||||
x += w
|
||||
// If not CJK, fill trailing space with whitespace
|
||||
if !is_cjk && w == 2 {
|
||||
charbuf = append(charbuf, char_info{attr: attr, char: ' '})
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// compares 'back_buffer' with 'front_buffer' and prepares all changes in the form of
|
||||
// 'diff_msg's in the 'diff_buf'
|
||||
func prepare_diff_messages() {
|
||||
// clear buffers
|
||||
diffbuf = diffbuf[:0]
|
||||
charbuf = charbuf[:0]
|
||||
|
||||
var diff diff_msg
|
||||
gbeg := 0
|
||||
for y := 0; y < front_buffer.height; y++ {
|
||||
same := true
|
||||
line_offset := y * front_buffer.width
|
||||
for x := 0; x < front_buffer.width; x++ {
|
||||
cell_offset := line_offset + x
|
||||
back := &back_buffer.cells[cell_offset]
|
||||
front := &front_buffer.cells[cell_offset]
|
||||
if *back != *front {
|
||||
same = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if same && diff.lines > 0 {
|
||||
diffbuf = append(diffbuf, diff)
|
||||
diff = diff_msg{}
|
||||
}
|
||||
if !same {
|
||||
beg := len(charbuf)
|
||||
end := beg + append_diff_line(y)
|
||||
if diff.lines == 0 {
|
||||
diff.pos = short(y)
|
||||
gbeg = beg
|
||||
}
|
||||
diff.lines++
|
||||
diff.chars = charbuf[gbeg:end]
|
||||
}
|
||||
}
|
||||
if diff.lines > 0 {
|
||||
diffbuf = append(diffbuf, diff)
|
||||
diff = diff_msg{}
|
||||
}
|
||||
}
|
||||
|
||||
func get_ct(table []word, idx int) word {
|
||||
idx = idx & 0x0F
|
||||
if idx >= len(table) {
|
||||
idx = len(table) - 1
|
||||
}
|
||||
return table[idx]
|
||||
}
|
||||
|
||||
func cell_to_char_info(c Cell) (attr word, wc [2]wchar) {
|
||||
attr = get_ct(color_table_fg, int(c.Fg)) | get_ct(color_table_bg, int(c.Bg))
|
||||
if c.Fg&AttrReverse|c.Bg&AttrReverse != 0 {
|
||||
attr = (attr&0xF0)>>4 | (attr&0x0F)<<4
|
||||
}
|
||||
if c.Fg&AttrBold != 0 {
|
||||
attr |= foreground_intensity
|
||||
}
|
||||
if c.Bg&AttrBold != 0 {
|
||||
attr |= background_intensity
|
||||
}
|
||||
|
||||
r0, r1 := utf16.EncodeRune(c.Ch)
|
||||
if r0 == 0xFFFD {
|
||||
wc[0] = wchar(c.Ch)
|
||||
wc[1] = ' '
|
||||
} else {
|
||||
wc[0] = wchar(r0)
|
||||
wc[1] = wchar(r1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func move_cursor(x, y int) {
|
||||
err := set_console_cursor_position(out, coord{short(x), short(y)})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func show_cursor(visible bool) {
|
||||
var v int32
|
||||
if visible {
|
||||
v = 1
|
||||
}
|
||||
|
||||
var info console_cursor_info
|
||||
info.size = 100
|
||||
info.visible = v
|
||||
err := set_console_cursor_info(out, &info)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func clear() {
|
||||
var err error
|
||||
attr, char := cell_to_char_info(Cell{
|
||||
' ',
|
||||
foreground,
|
||||
background,
|
||||
})
|
||||
|
||||
area := int(term_size.x) * int(term_size.y)
|
||||
err = fill_console_output_attribute(out, attr, area)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = fill_console_output_character(out, char[0], area)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if !is_cursor_hidden(cursor_x, cursor_y) {
|
||||
move_cursor(cursor_x, cursor_y)
|
||||
}
|
||||
}
|
||||
|
||||
func key_event_record_to_event(r *key_event_record) (Event, bool) {
|
||||
if r.key_down == 0 {
|
||||
return Event{}, false
|
||||
}
|
||||
|
||||
e := Event{Type: EventKey}
|
||||
if input_mode&InputAlt != 0 {
|
||||
if alt_mode_esc {
|
||||
e.Mod = ModAlt
|
||||
alt_mode_esc = false
|
||||
}
|
||||
if r.control_key_state&(left_alt_pressed|right_alt_pressed) != 0 {
|
||||
e.Mod = ModAlt
|
||||
}
|
||||
}
|
||||
|
||||
ctrlpressed := r.control_key_state&(left_ctrl_pressed|right_ctrl_pressed) != 0
|
||||
|
||||
if r.virtual_key_code >= vk_f1 && r.virtual_key_code <= vk_f12 {
|
||||
switch r.virtual_key_code {
|
||||
case vk_f1:
|
||||
e.Key = KeyF1
|
||||
case vk_f2:
|
||||
e.Key = KeyF2
|
||||
case vk_f3:
|
||||
e.Key = KeyF3
|
||||
case vk_f4:
|
||||
e.Key = KeyF4
|
||||
case vk_f5:
|
||||
e.Key = KeyF5
|
||||
case vk_f6:
|
||||
e.Key = KeyF6
|
||||
case vk_f7:
|
||||
e.Key = KeyF7
|
||||
case vk_f8:
|
||||
e.Key = KeyF8
|
||||
case vk_f9:
|
||||
e.Key = KeyF9
|
||||
case vk_f10:
|
||||
e.Key = KeyF10
|
||||
case vk_f11:
|
||||
e.Key = KeyF11
|
||||
case vk_f12:
|
||||
e.Key = KeyF12
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
return e, true
|
||||
}
|
||||
|
||||
if r.virtual_key_code <= vk_delete {
|
||||
switch r.virtual_key_code {
|
||||
case vk_insert:
|
||||
e.Key = KeyInsert
|
||||
case vk_delete:
|
||||
e.Key = KeyDelete
|
||||
case vk_home:
|
||||
e.Key = KeyHome
|
||||
case vk_end:
|
||||
e.Key = KeyEnd
|
||||
case vk_pgup:
|
||||
e.Key = KeyPgup
|
||||
case vk_pgdn:
|
||||
e.Key = KeyPgdn
|
||||
case vk_arrow_up:
|
||||
e.Key = KeyArrowUp
|
||||
case vk_arrow_down:
|
||||
e.Key = KeyArrowDown
|
||||
case vk_arrow_left:
|
||||
e.Key = KeyArrowLeft
|
||||
case vk_arrow_right:
|
||||
e.Key = KeyArrowRight
|
||||
case vk_backspace:
|
||||
if ctrlpressed {
|
||||
e.Key = KeyBackspace2
|
||||
} else {
|
||||
e.Key = KeyBackspace
|
||||
}
|
||||
case vk_tab:
|
||||
e.Key = KeyTab
|
||||
case vk_enter:
|
||||
e.Key = KeyEnter
|
||||
case vk_esc:
|
||||
switch {
|
||||
case input_mode&InputEsc != 0:
|
||||
e.Key = KeyEsc
|
||||
case input_mode&InputAlt != 0:
|
||||
alt_mode_esc = true
|
||||
return Event{}, false
|
||||
}
|
||||
case vk_space:
|
||||
if ctrlpressed {
|
||||
// manual return here, because KeyCtrlSpace is zero
|
||||
e.Key = KeyCtrlSpace
|
||||
return e, true
|
||||
} else {
|
||||
e.Key = KeySpace
|
||||
}
|
||||
}
|
||||
|
||||
if e.Key != 0 {
|
||||
return e, true
|
||||
}
|
||||
}
|
||||
|
||||
if ctrlpressed {
|
||||
if Key(r.unicode_char) >= KeyCtrlA && Key(r.unicode_char) <= KeyCtrlRsqBracket {
|
||||
e.Key = Key(r.unicode_char)
|
||||
if input_mode&InputAlt != 0 && e.Key == KeyEsc {
|
||||
alt_mode_esc = true
|
||||
return Event{}, false
|
||||
}
|
||||
return e, true
|
||||
}
|
||||
switch r.virtual_key_code {
|
||||
case 192, 50:
|
||||
// manual return here, because KeyCtrl2 is zero
|
||||
e.Key = KeyCtrl2
|
||||
return e, true
|
||||
case 51:
|
||||
if input_mode&InputAlt != 0 {
|
||||
alt_mode_esc = true
|
||||
return Event{}, false
|
||||
}
|
||||
e.Key = KeyCtrl3
|
||||
case 52:
|
||||
e.Key = KeyCtrl4
|
||||
case 53:
|
||||
e.Key = KeyCtrl5
|
||||
case 54:
|
||||
e.Key = KeyCtrl6
|
||||
case 189, 191, 55:
|
||||
e.Key = KeyCtrl7
|
||||
case 8, 56:
|
||||
e.Key = KeyCtrl8
|
||||
}
|
||||
|
||||
if e.Key != 0 {
|
||||
return e, true
|
||||
}
|
||||
}
|
||||
|
||||
if r.unicode_char != 0 {
|
||||
e.Ch = rune(r.unicode_char)
|
||||
return e, true
|
||||
}
|
||||
|
||||
return Event{}, false
|
||||
}
|
||||
|
||||
func input_event_producer() {
|
||||
var r input_record
|
||||
var err error
|
||||
var last_button Key
|
||||
var last_button_pressed Key
|
||||
var last_state = dword(0)
|
||||
var last_x, last_y = -1, -1
|
||||
handles := []syscall.Handle{in, interrupt}
|
||||
for {
|
||||
err = wait_for_multiple_objects(handles)
|
||||
if err != nil {
|
||||
input_comm <- Event{Type: EventError, Err: err}
|
||||
}
|
||||
|
||||
select {
|
||||
case <-cancel_comm:
|
||||
cancel_done_comm <- true
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
err = read_console_input(in, &r)
|
||||
if err != nil {
|
||||
input_comm <- Event{Type: EventError, Err: err}
|
||||
}
|
||||
|
||||
switch r.event_type {
|
||||
case key_event:
|
||||
kr := (*key_event_record)(unsafe.Pointer(&r.event))
|
||||
ev, ok := key_event_record_to_event(kr)
|
||||
if ok {
|
||||
for i := 0; i < int(kr.repeat_count); i++ {
|
||||
input_comm <- ev
|
||||
}
|
||||
}
|
||||
case window_buffer_size_event:
|
||||
sr := *(*window_buffer_size_record)(unsafe.Pointer(&r.event))
|
||||
input_comm <- Event{
|
||||
Type: EventResize,
|
||||
Width: int(sr.size.x),
|
||||
Height: int(sr.size.y),
|
||||
}
|
||||
case mouse_event:
|
||||
mr := *(*mouse_event_record)(unsafe.Pointer(&r.event))
|
||||
ev := Event{Type: EventMouse}
|
||||
switch mr.event_flags {
|
||||
case 0, 2:
|
||||
// single or double click
|
||||
cur_state := mr.button_state
|
||||
switch {
|
||||
case last_state&mouse_lmb == 0 && cur_state&mouse_lmb != 0:
|
||||
last_button = MouseLeft
|
||||
last_button_pressed = last_button
|
||||
case last_state&mouse_rmb == 0 && cur_state&mouse_rmb != 0:
|
||||
last_button = MouseRight
|
||||
last_button_pressed = last_button
|
||||
case last_state&mouse_mmb == 0 && cur_state&mouse_mmb != 0:
|
||||
last_button = MouseMiddle
|
||||
last_button_pressed = last_button
|
||||
case last_state&mouse_lmb != 0 && cur_state&mouse_lmb == 0:
|
||||
last_button = MouseRelease
|
||||
case last_state&mouse_rmb != 0 && cur_state&mouse_rmb == 0:
|
||||
last_button = MouseRelease
|
||||
case last_state&mouse_mmb != 0 && cur_state&mouse_mmb == 0:
|
||||
last_button = MouseRelease
|
||||
default:
|
||||
last_state = cur_state
|
||||
continue
|
||||
}
|
||||
last_state = cur_state
|
||||
ev.Key = last_button
|
||||
last_x, last_y = int(mr.mouse_pos.x), int(mr.mouse_pos.y)
|
||||
ev.MouseX = last_x
|
||||
ev.MouseY = last_y
|
||||
case 1:
|
||||
// mouse motion
|
||||
x, y := int(mr.mouse_pos.x), int(mr.mouse_pos.y)
|
||||
if last_state != 0 && (last_x != x || last_y != y) {
|
||||
ev.Key = last_button_pressed
|
||||
ev.Mod = ModMotion
|
||||
ev.MouseX = x
|
||||
ev.MouseY = y
|
||||
last_x, last_y = x, y
|
||||
} else {
|
||||
ev.Type = EventNone
|
||||
}
|
||||
case 4:
|
||||
// mouse wheel
|
||||
n := int16(mr.button_state >> 16)
|
||||
if n > 0 {
|
||||
ev.Key = MouseWheelUp
|
||||
} else {
|
||||
ev.Key = MouseWheelDown
|
||||
}
|
||||
last_x, last_y = int(mr.mouse_pos.x), int(mr.mouse_pos.y)
|
||||
ev.MouseX = last_x
|
||||
ev.MouseY = last_y
|
||||
default:
|
||||
ev.Type = EventNone
|
||||
}
|
||||
if ev.Type != EventNone {
|
||||
input_comm <- ev
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
221
vendor/github.com/nsf/termbox-go/terminfo.go
generated
vendored
Normal file
221
vendor/github.com/nsf/termbox-go/terminfo.go
generated
vendored
Normal file
@ -0,0 +1,221 @@
|
||||
// +build !windows
|
||||
// This file contains a simple and incomplete implementation of the terminfo
|
||||
// database. Information was taken from the ncurses manpages term(5) and
|
||||
// terminfo(5). Currently, only the string capabilities for special keys and for
|
||||
// functions without parameters are actually used. Colors are still done with
|
||||
// ANSI escape sequences. Other special features that are not (yet?) supported
|
||||
// are reading from ~/.terminfo, the TERMINFO_DIRS variable, Berkeley database
|
||||
// format and extended capabilities.
|
||||
|
||||
package termbox
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
ti_magic = 0432
|
||||
ti_header_length = 12
|
||||
ti_mouse_enter = "\x1b[?1000h\x1b[?1002h\x1b[?1015h\x1b[?1006h"
|
||||
ti_mouse_leave = "\x1b[?1006l\x1b[?1015l\x1b[?1002l\x1b[?1000l"
|
||||
)
|
||||
|
||||
func load_terminfo() ([]byte, error) {
|
||||
var data []byte
|
||||
var err error
|
||||
|
||||
term := os.Getenv("TERM")
|
||||
if term == "" {
|
||||
return nil, fmt.Errorf("termbox: TERM not set")
|
||||
}
|
||||
|
||||
// The following behaviour follows the one described in terminfo(5) as
|
||||
// distributed by ncurses.
|
||||
|
||||
terminfo := os.Getenv("TERMINFO")
|
||||
if terminfo != "" {
|
||||
// if TERMINFO is set, no other directory should be searched
|
||||
return ti_try_path(terminfo)
|
||||
}
|
||||
|
||||
// next, consider ~/.terminfo
|
||||
home := os.Getenv("HOME")
|
||||
if home != "" {
|
||||
data, err = ti_try_path(home + "/.terminfo")
|
||||
if err == nil {
|
||||
return data, nil
|
||||
}
|
||||
}
|
||||
|
||||
// next, TERMINFO_DIRS
|
||||
dirs := os.Getenv("TERMINFO_DIRS")
|
||||
if dirs != "" {
|
||||
for _, dir := range strings.Split(dirs, ":") {
|
||||
if dir == "" {
|
||||
// "" -> "/usr/share/terminfo"
|
||||
dir = "/usr/share/terminfo"
|
||||
}
|
||||
data, err = ti_try_path(dir)
|
||||
if err == nil {
|
||||
return data, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fall back to /usr/share/terminfo
|
||||
return ti_try_path("/usr/share/terminfo")
|
||||
}
|
||||
|
||||
func ti_try_path(path string) (data []byte, err error) {
|
||||
// load_terminfo already made sure it is set
|
||||
term := os.Getenv("TERM")
|
||||
|
||||
// first try, the typical *nix path
|
||||
terminfo := path + "/" + term[0:1] + "/" + term
|
||||
data, err = ioutil.ReadFile(terminfo)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// fallback to darwin specific dirs structure
|
||||
terminfo = path + "/" + hex.EncodeToString([]byte(term[:1])) + "/" + term
|
||||
data, err = ioutil.ReadFile(terminfo)
|
||||
return
|
||||
}
|
||||
|
||||
func setup_term_builtin() error {
|
||||
name := os.Getenv("TERM")
|
||||
if name == "" {
|
||||
return errors.New("termbox: TERM environment variable not set")
|
||||
}
|
||||
|
||||
for _, t := range terms {
|
||||
if t.name == name {
|
||||
keys = t.keys
|
||||
funcs = t.funcs
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
compat_table := []struct {
|
||||
partial string
|
||||
keys []string
|
||||
funcs []string
|
||||
}{
|
||||
{"xterm", xterm_keys, xterm_funcs},
|
||||
{"rxvt", rxvt_unicode_keys, rxvt_unicode_funcs},
|
||||
{"linux", linux_keys, linux_funcs},
|
||||
{"Eterm", eterm_keys, eterm_funcs},
|
||||
{"screen", screen_keys, screen_funcs},
|
||||
// let's assume that 'cygwin' is xterm compatible
|
||||
{"cygwin", xterm_keys, xterm_funcs},
|
||||
{"st", xterm_keys, xterm_funcs},
|
||||
}
|
||||
|
||||
// try compatibility variants
|
||||
for _, it := range compat_table {
|
||||
if strings.Contains(name, it.partial) {
|
||||
keys = it.keys
|
||||
funcs = it.funcs
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("termbox: unsupported terminal")
|
||||
}
|
||||
|
||||
func setup_term() (err error) {
|
||||
var data []byte
|
||||
var header [6]int16
|
||||
var str_offset, table_offset int16
|
||||
|
||||
data, err = load_terminfo()
|
||||
if err != nil {
|
||||
return setup_term_builtin()
|
||||
}
|
||||
|
||||
rd := bytes.NewReader(data)
|
||||
// 0: magic number, 1: size of names section, 2: size of boolean section, 3:
|
||||
// size of numbers section (in integers), 4: size of the strings section (in
|
||||
// integers), 5: size of the string table
|
||||
|
||||
err = binary.Read(rd, binary.LittleEndian, header[:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if (header[1]+header[2])%2 != 0 {
|
||||
// old quirk to align everything on word boundaries
|
||||
header[2] += 1
|
||||
}
|
||||
str_offset = ti_header_length + header[1] + header[2] + 2*header[3]
|
||||
table_offset = str_offset + 2*header[4]
|
||||
|
||||
keys = make([]string, 0xFFFF-key_min)
|
||||
for i, _ := range keys {
|
||||
keys[i], err = ti_read_string(rd, str_offset+2*ti_keys[i], table_offset)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
funcs = make([]string, t_max_funcs)
|
||||
// the last two entries are reserved for mouse. because the table offset is
|
||||
// not there, the two entries have to fill in manually
|
||||
for i, _ := range funcs[:len(funcs)-2] {
|
||||
funcs[i], err = ti_read_string(rd, str_offset+2*ti_funcs[i], table_offset)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
funcs[t_max_funcs-2] = ti_mouse_enter
|
||||
funcs[t_max_funcs-1] = ti_mouse_leave
|
||||
return nil
|
||||
}
|
||||
|
||||
func ti_read_string(rd *bytes.Reader, str_off, table int16) (string, error) {
|
||||
var off int16
|
||||
|
||||
_, err := rd.Seek(int64(str_off), 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = binary.Read(rd, binary.LittleEndian, &off)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
_, err = rd.Seek(int64(table+off), 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var bs []byte
|
||||
for {
|
||||
b, err := rd.ReadByte()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if b == byte(0x00) {
|
||||
break
|
||||
}
|
||||
bs = append(bs, b)
|
||||
}
|
||||
return string(bs), nil
|
||||
}
|
||||
|
||||
// "Maps" the function constants from termbox.go to the number of the respective
|
||||
// string capability in the terminfo file. Taken from (ncurses) term.h.
|
||||
var ti_funcs = []int16{
|
||||
28, 40, 16, 13, 5, 39, 36, 27, 26, 34, 89, 88,
|
||||
}
|
||||
|
||||
// Same as above for the special keys.
|
||||
var ti_keys = []int16{
|
||||
66, 68 /* apparently not a typo; 67 is F10 for whatever reason */, 69, 70,
|
||||
71, 72, 73, 74, 75, 67, 216, 217, 77, 59, 76, 164, 82, 81, 87, 61, 79, 83,
|
||||
}
|
64
vendor/github.com/nsf/termbox-go/terminfo_builtin.go
generated
vendored
Normal file
64
vendor/github.com/nsf/termbox-go/terminfo_builtin.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
// +build !windows
|
||||
|
||||
package termbox
|
||||
|
||||
// Eterm
|
||||
var eterm_keys = []string{
|
||||
"\x1b[11~", "\x1b[12~", "\x1b[13~", "\x1b[14~", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[7~", "\x1b[8~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C",
|
||||
}
|
||||
var eterm_funcs = []string{
|
||||
"\x1b7\x1b[?47h", "\x1b[2J\x1b[?47l\x1b8", "\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b[m\x0f", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "", "", "", "",
|
||||
}
|
||||
|
||||
// screen
|
||||
var screen_keys = []string{
|
||||
"\x1bOP", "\x1bOQ", "\x1bOR", "\x1bOS", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[1~", "\x1b[4~", "\x1b[5~", "\x1b[6~", "\x1bOA", "\x1bOB", "\x1bOD", "\x1bOC",
|
||||
}
|
||||
var screen_funcs = []string{
|
||||
"\x1b[?1049h", "\x1b[?1049l", "\x1b[34h\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[J", "\x1b[m\x0f", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b[?1h\x1b=", "\x1b[?1l\x1b>", ti_mouse_enter, ti_mouse_leave,
|
||||
}
|
||||
|
||||
// xterm
|
||||
var xterm_keys = []string{
|
||||
"\x1bOP", "\x1bOQ", "\x1bOR", "\x1bOS", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1bOH", "\x1bOF", "\x1b[5~", "\x1b[6~", "\x1bOA", "\x1bOB", "\x1bOD", "\x1bOC",
|
||||
}
|
||||
var xterm_funcs = []string{
|
||||
"\x1b[?1049h", "\x1b[?1049l", "\x1b[?12l\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b(B\x1b[m", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b[?1h\x1b=", "\x1b[?1l\x1b>", ti_mouse_enter, ti_mouse_leave,
|
||||
}
|
||||
|
||||
// rxvt-unicode
|
||||
var rxvt_unicode_keys = []string{
|
||||
"\x1b[11~", "\x1b[12~", "\x1b[13~", "\x1b[14~", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[7~", "\x1b[8~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C",
|
||||
}
|
||||
var rxvt_unicode_funcs = []string{
|
||||
"\x1b[?1049h", "\x1b[r\x1b[?1049l", "\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b[m\x1b(B", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b=", "\x1b>", ti_mouse_enter, ti_mouse_leave,
|
||||
}
|
||||
|
||||
// linux
|
||||
var linux_keys = []string{
|
||||
"\x1b[[A", "\x1b[[B", "\x1b[[C", "\x1b[[D", "\x1b[[E", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[1~", "\x1b[4~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C",
|
||||
}
|
||||
var linux_funcs = []string{
|
||||
"", "", "\x1b[?25h\x1b[?0c", "\x1b[?25l\x1b[?1c", "\x1b[H\x1b[J", "\x1b[0;10m", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "", "", "", "",
|
||||
}
|
||||
|
||||
// rxvt-256color
|
||||
var rxvt_256color_keys = []string{
|
||||
"\x1b[11~", "\x1b[12~", "\x1b[13~", "\x1b[14~", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[7~", "\x1b[8~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C",
|
||||
}
|
||||
var rxvt_256color_funcs = []string{
|
||||
"\x1b7\x1b[?47h", "\x1b[2J\x1b[?47l\x1b8", "\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b[m\x0f", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b=", "\x1b>", ti_mouse_enter, ti_mouse_leave,
|
||||
}
|
||||
|
||||
var terms = []struct {
|
||||
name string
|
||||
keys []string
|
||||
funcs []string
|
||||
}{
|
||||
{"Eterm", eterm_keys, eterm_funcs},
|
||||
{"screen", screen_keys, screen_funcs},
|
||||
{"xterm", xterm_keys, xterm_funcs},
|
||||
{"rxvt-unicode", rxvt_unicode_keys, rxvt_unicode_funcs},
|
||||
{"linux", linux_keys, linux_funcs},
|
||||
{"rxvt-256color", rxvt_256color_keys, rxvt_256color_funcs},
|
||||
}
|
Loading…
Reference in New Issue
Block a user