vendored deps

master
Stephen McQuay 7 years ago
parent fe830a3d5a
commit 9f47b066db
No known key found for this signature in database
GPG Key ID: 1ABF428F71BAFC3D
  1. 26
      vendor/github.com/mattn/go-runewidth/README.mkd
  2. 464
      vendor/github.com/mattn/go-runewidth/runewidth.go
  3. 8
      vendor/github.com/mattn/go-runewidth/runewidth_js.go
  4. 69
      vendor/github.com/mattn/go-runewidth/runewidth_posix.go
  5. 229
      vendor/github.com/mattn/go-runewidth/runewidth_test.go
  6. 24
      vendor/github.com/mattn/go-runewidth/runewidth_windows.go
  7. 4
      vendor/github.com/nsf/termbox-go/AUTHORS
  8. 19
      vendor/github.com/nsf/termbox-go/LICENSE
  9. 25
      vendor/github.com/nsf/termbox-go/README.md
  10. 459
      vendor/github.com/nsf/termbox-go/api.go
  11. 187
      vendor/github.com/nsf/termbox-go/api_common.go
  12. 239
      vendor/github.com/nsf/termbox-go/api_windows.go
  13. 110
      vendor/github.com/nsf/termbox-go/collect_terminfo.py
  14. 39
      vendor/github.com/nsf/termbox-go/syscalls.go
  15. 41
      vendor/github.com/nsf/termbox-go/syscalls_darwin.go
  16. 40
      vendor/github.com/nsf/termbox-go/syscalls_darwin_amd64.go
  17. 39
      vendor/github.com/nsf/termbox-go/syscalls_freebsd.go
  18. 33
      vendor/github.com/nsf/termbox-go/syscalls_linux.go
  19. 39
      vendor/github.com/nsf/termbox-go/syscalls_netbsd.go
  20. 39
      vendor/github.com/nsf/termbox-go/syscalls_openbsd.go
  21. 61
      vendor/github.com/nsf/termbox-go/syscalls_windows.go
  22. 514
      vendor/github.com/nsf/termbox-go/termbox.go
  23. 59
      vendor/github.com/nsf/termbox-go/termbox_common.go
  24. 856
      vendor/github.com/nsf/termbox-go/termbox_windows.go
  25. 221
      vendor/github.com/nsf/termbox-go/terminfo.go
  26. 64
      vendor/github.com/nsf/termbox-go/terminfo_builtin.go
  27. 174
      vendor/github.com/spf13/cobra/LICENSE.txt
  28. 892
      vendor/github.com/spf13/cobra/README.md
  29. 602
      vendor/github.com/spf13/cobra/bash_completions.go
  30. 206
      vendor/github.com/spf13/cobra/bash_completions.md
  31. 140
      vendor/github.com/spf13/cobra/bash_completions_test.go
  32. 171
      vendor/github.com/spf13/cobra/cobra.go
  33. 1188
      vendor/github.com/spf13/cobra/cobra_test.go
  34. 1217
      vendor/github.com/spf13/cobra/command.go
  35. 5
      vendor/github.com/spf13/cobra/command_notwin.go
  36. 114
      vendor/github.com/spf13/cobra/command_test.go
  37. 26
      vendor/github.com/spf13/cobra/command_win.go
  38. 28
      vendor/github.com/spf13/pflag/LICENSE
  39. 256
      vendor/github.com/spf13/pflag/README.md
  40. 97
      vendor/github.com/spf13/pflag/bool.go
  41. 180
      vendor/github.com/spf13/pflag/bool_test.go
  42. 97
      vendor/github.com/spf13/pflag/count.go
  43. 55
      vendor/github.com/spf13/pflag/count_test.go
  44. 86
      vendor/github.com/spf13/pflag/duration.go
  45. 77
      vendor/github.com/spf13/pflag/example_test.go
  46. 29
      vendor/github.com/spf13/pflag/export_test.go
  47. 934
      vendor/github.com/spf13/pflag/flag.go
  48. 913
      vendor/github.com/spf13/pflag/flag_test.go
  49. 91
      vendor/github.com/spf13/pflag/float32.go
  50. 87
      vendor/github.com/spf13/pflag/float64.go
  51. 104
      vendor/github.com/spf13/pflag/golangflag.go
  52. 39
      vendor/github.com/spf13/pflag/golangflag_test.go
  53. 87
      vendor/github.com/spf13/pflag/int.go
  54. 91
      vendor/github.com/spf13/pflag/int32.go
  55. 87
      vendor/github.com/spf13/pflag/int64.go
  56. 91
      vendor/github.com/spf13/pflag/int8.go
  57. 128
      vendor/github.com/spf13/pflag/int_slice.go
  58. 162
      vendor/github.com/spf13/pflag/int_slice_test.go
  59. 96
      vendor/github.com/spf13/pflag/ip.go
  60. 63
      vendor/github.com/spf13/pflag/ip_test.go
  61. 122
      vendor/github.com/spf13/pflag/ipmask.go
  62. 100
      vendor/github.com/spf13/pflag/ipnet.go
  63. 70
      vendor/github.com/spf13/pflag/ipnet_test.go
  64. 82
      vendor/github.com/spf13/pflag/string.go
  65. 111
      vendor/github.com/spf13/pflag/string_slice.go
  66. 161
      vendor/github.com/spf13/pflag/string_slice_test.go
  67. 91
      vendor/github.com/spf13/pflag/uint.go
  68. 89
      vendor/github.com/spf13/pflag/uint16.go
  69. 89
      vendor/github.com/spf13/pflag/uint32.go
  70. 91
      vendor/github.com/spf13/pflag/uint64.go
  71. 91
      vendor/github.com/spf13/pflag/uint8.go

@ -0,0 +1,26 @@
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)
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

@ -0,0 +1,464 @@
package runewidth
var EastAsianWidth = IsEastAsian()
var DefaultCondition = &Condition{EastAsianWidth}
type interval struct {
first rune
last rune
}
var combining = []interval{
{0x0300, 0x036F}, {0x0483, 0x0486}, {0x0488, 0x0489},
{0x0591, 0x05BD}, {0x05BF, 0x05BF}, {0x05C1, 0x05C2},
{0x05C4, 0x05C5}, {0x05C7, 0x05C7}, {0x0600, 0x0603},
{0x0610, 0x0615}, {0x064B, 0x065E}, {0x0670, 0x0670},
{0x06D6, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED},
{0x070F, 0x070F}, {0x0711, 0x0711}, {0x0730, 0x074A},
{0x07A6, 0x07B0}, {0x07EB, 0x07F3}, {0x0901, 0x0902},
{0x093C, 0x093C}, {0x0941, 0x0948}, {0x094D, 0x094D},
{0x0951, 0x0954}, {0x0962, 0x0963}, {0x0981, 0x0981},
{0x09BC, 0x09BC}, {0x09C1, 0x09C4}, {0x09CD, 0x09CD},
{0x09E2, 0x09E3}, {0x0A01, 0x0A02}, {0x0A3C, 0x0A3C},
{0x0A41, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D},
{0x0A70, 0x0A71}, {0x0A81, 0x0A82}, {0x0ABC, 0x0ABC},
{0x0AC1, 0x0AC5}, {0x0AC7, 0x0AC8}, {0x0ACD, 0x0ACD},
{0x0AE2, 0x0AE3}, {0x0B01, 0x0B01}, {0x0B3C, 0x0B3C},
{0x0B3F, 0x0B3F}, {0x0B41, 0x0B43}, {0x0B4D, 0x0B4D},
{0x0B56, 0x0B56}, {0x0B82, 0x0B82}, {0x0BC0, 0x0BC0},
{0x0BCD, 0x0BCD}, {0x0C3E, 0x0C40}, {0x0C46, 0x0C48},
{0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, {0x0CBC, 0x0CBC},
{0x0CBF, 0x0CBF}, {0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD},
{0x0CE2, 0x0CE3}, {0x0D41, 0x0D43}, {0x0D4D, 0x0D4D},
{0x0DCA, 0x0DCA}, {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6},
{0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E},
{0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC},
{0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35},
{0x0F37, 0x0F37}, {0x0F39, 0x0F39}, {0x0F71, 0x0F7E},
{0x0F80, 0x0F84}, {0x0F86, 0x0F87}, {0x0F90, 0x0F97},
{0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102D, 0x1030},
{0x1032, 0x1032}, {0x1036, 0x1037}, {0x1039, 0x1039},
{0x1058, 0x1059}, {0x1160, 0x11FF}, {0x135F, 0x135F},
{0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753},
{0x1772, 0x1773}, {0x17B4, 0x17B5}, {0x17B7, 0x17BD},
{0x17C6, 0x17C6}, {0x17C9, 0x17D3}, {0x17DD, 0x17DD},
{0x180B, 0x180D}, {0x18A9, 0x18A9}, {0x1920, 0x1922},
{0x1927, 0x1928}, {0x1932, 0x1932}, {0x1939, 0x193B},
{0x1A17, 0x1A18}, {0x1B00, 0x1B03}, {0x1B34, 0x1B34},
{0x1B36, 0x1B3A}, {0x1B3C, 0x1B3C}, {0x1B42, 0x1B42},
{0x1B6B, 0x1B73}, {0x1DC0, 0x1DCA}, {0x1DFE, 0x1DFF},
{0x200B, 0x200F}, {0x202A, 0x202E}, {0x2060, 0x2063},
{0x206A, 0x206F}, {0x20D0, 0x20EF}, {0x302A, 0x302F},
{0x3099, 0x309A}, {0xA806, 0xA806}, {0xA80B, 0xA80B},
{0xA825, 0xA826}, {0xFB1E, 0xFB1E}, {0xFE00, 0xFE0F},
{0xFE20, 0xFE23}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB},
{0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F},
{0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x1D167, 0x1D169},
{0x1D173, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD},
{0x1D242, 0x1D244}, {0xE0001, 0xE0001}, {0xE0020, 0xE007F},
{0xE0100, 0xE01EF},
}
type ctype int
const (
narrow ctype = iota
ambiguous
wide
halfwidth
fullwidth
neutral
)
type intervalType struct {
first rune
last rune
ctype ctype
}
var ctypes = []intervalType{
{0x0020, 0x007E, narrow},
{0x00A1, 0x00A1, ambiguous},
{0x00A2, 0x00A3, narrow},
{0x00A4, 0x00A4, ambiguous},
{0x00A5, 0x00A6, narrow},
{0x00A7, 0x00A8, ambiguous},
{0x00AA, 0x00AA, ambiguous},
{0x00AC, 0x00AC, narrow},
{0x00AD, 0x00AE, ambiguous},
{0x00AF, 0x00AF, narrow},
{0x00B0, 0x00B4, ambiguous},
{0x00B6, 0x00BA, ambiguous},
{0x00BC, 0x00BF, ambiguous},
{0x00C6, 0x00C6, ambiguous},
{0x00D0, 0x00D0, ambiguous},
{0x00D7, 0x00D8, ambiguous},
{0x00DE, 0x00E1, ambiguous},
{0x00E6, 0x00E6, ambiguous},
{0x00E8, 0x00EA, ambiguous},
{0x00EC, 0x00ED, ambiguous},
{0x00F0, 0x00F0, ambiguous},
{0x00F2, 0x00F3, ambiguous},
{0x00F7, 0x00FA, ambiguous},
{0x00FC, 0x00FC, ambiguous},
{0x00FE, 0x00FE, ambiguous},
{0x0101, 0x0101, ambiguous},
{0x0111, 0x0111, ambiguous},
{0x0113, 0x0113, ambiguous},
{0x011B, 0x011B, ambiguous},
{0x0126, 0x0127, ambiguous},
{0x012B, 0x012B, ambiguous},
{0x0131, 0x0133, ambiguous},
{0x0138, 0x0138, ambiguous},
{0x013F, 0x0142, ambiguous},
{0x0144, 0x0144, ambiguous},
{0x0148, 0x014B, ambiguous},
{0x014D, 0x014D, ambiguous},
{0x0152, 0x0153, ambiguous},
{0x0166, 0x0167, ambiguous},
{0x016B, 0x016B, ambiguous},
{0x01CE, 0x01CE, ambiguous},
{0x01D0, 0x01D0, ambiguous},
{0x01D2, 0x01D2, ambiguous},
{0x01D4, 0x01D4, ambiguous},
{0x01D6, 0x01D6, ambiguous},
{0x01D8, 0x01D8, ambiguous},
{0x01DA, 0x01DA, ambiguous},
{0x01DC, 0x01DC, ambiguous},
{0x0251, 0x0251, ambiguous},
{0x0261, 0x0261, ambiguous},
{0x02C4, 0x02C4, ambiguous},
{0x02C7, 0x02C7, ambiguous},
{0x02C9, 0x02CB, ambiguous},
{0x02CD, 0x02CD, ambiguous},
{0x02D0, 0x02D0, ambiguous},
{0x02D8, 0x02DB, ambiguous},
{0x02DD, 0x02DD, ambiguous},
{0x02DF, 0x02DF, ambiguous},
{0x0300, 0x036F, ambiguous},
{0x0391, 0x03A2, ambiguous},
{0x03A3, 0x03A9, ambiguous},
{0x03B1, 0x03C1, ambiguous},
{0x03C3, 0x03C9, ambiguous},
{0x0401, 0x0401, ambiguous},
{0x0410, 0x044F, ambiguous},
{0x0451, 0x0451, ambiguous},
{0x1100, 0x115F, wide},
{0x2010, 0x2010, ambiguous},
{0x2013, 0x2016, ambiguous},
{0x2018, 0x2019, ambiguous},
{0x201C, 0x201D, ambiguous},
{0x2020, 0x2022, ambiguous},
{0x2024, 0x2027, ambiguous},
{0x2030, 0x2030, ambiguous},
{0x2032, 0x2033, ambiguous},
{0x2035, 0x2035, ambiguous},
{0x203B, 0x203B, ambiguous},
{0x203E, 0x203E, ambiguous},
{0x2074, 0x2074, ambiguous},
{0x207F, 0x207F, ambiguous},
{0x2081, 0x2084, ambiguous},
{0x20A9, 0x20A9, halfwidth},
{0x20AC, 0x20AC, ambiguous},
{0x2103, 0x2103, ambiguous},
{0x2105, 0x2105, ambiguous},
{0x2109, 0x2109, ambiguous},
{0x2113, 0x2113, ambiguous},
{0x2116, 0x2116, ambiguous},
{0x2121, 0x2122, ambiguous},
{0x2126, 0x2126, ambiguous},
{0x212B, 0x212B, ambiguous},
{0x2153, 0x2154, ambiguous},
{0x215B, 0x215E, ambiguous},
{0x2160, 0x216B, ambiguous},
{0x2170, 0x2179, ambiguous},
{0x2189, 0x218A, ambiguous},
{0x2190, 0x2199, ambiguous},
{0x21B8, 0x21B9, ambiguous},
{0x21D2, 0x21D2, ambiguous},
{0x21D4, 0x21D4, ambiguous},
{0x21E7, 0x21E7, ambiguous},
{0x2200, 0x2200, ambiguous},
{0x2202, 0x2203, ambiguous},
{0x2207, 0x2208, ambiguous},
{0x220B, 0x220B, ambiguous},
{0x220F, 0x220F, ambiguous},
{0x2211, 0x2211, ambiguous},
{0x2215, 0x2215, ambiguous},
{0x221A, 0x221A, ambiguous},
{0x221D, 0x2220, ambiguous},
{0x2223, 0x2223, ambiguous},
{0x2225, 0x2225, ambiguous},
{0x2227, 0x222C, ambiguous},
{0x222E, 0x222E, ambiguous},
{0x2234, 0x2237, ambiguous},
{0x223C, 0x223D, ambiguous},
{0x2248, 0x2248, ambiguous},
{0x224C, 0x224C, ambiguous},
{0x2252, 0x2252, ambiguous},
{0x2260, 0x2261, ambiguous},
{0x2264, 0x2267, ambiguous},
{0x226A, 0x226B, ambiguous},
{0x226E, 0x226F, ambiguous},
{0x2282, 0x2283, ambiguous},
{0x2286, 0x2287, ambiguous},
{0x2295, 0x2295, ambiguous},
{0x2299, 0x2299, ambiguous},
{0x22A5, 0x22A5, ambiguous},
{0x22BF, 0x22BF, ambiguous},
{0x2312, 0x2312, ambiguous},
{0x2329, 0x232A, wide},
{0x2460, 0x24E9, ambiguous},
{0x24EB, 0x254B, ambiguous},
{0x2550, 0x2573, ambiguous},
{0x2580, 0x258F, ambiguous},
{0x2592, 0x2595, ambiguous},
{0x25A0, 0x25A1, ambiguous},
{0x25A3, 0x25A9, ambiguous},
{0x25B2, 0x25B3, ambiguous},
{0x25B6, 0x25B7, ambiguous},
{0x25BC, 0x25BD, ambiguous},
{0x25C0, 0x25C1, ambiguous},
{0x25C6, 0x25C8, ambiguous},
{0x25CB, 0x25CB, ambiguous},
{0x25CE, 0x25D1, ambiguous},
{0x25E2, 0x25E5, ambiguous},
{0x25EF, 0x25EF, ambiguous},
{0x2605, 0x2606, ambiguous},
{0x2609, 0x2609, ambiguous},
{0x260E, 0x260F, ambiguous},
{0x2614, 0x2615, ambiguous},
{0x261C, 0x261C, ambiguous},
{0x261E, 0x261E, ambiguous},
{0x2640, 0x2640, ambiguous},
{0x2642, 0x2642, ambiguous},
{0x2660, 0x2661, ambiguous},
{0x2663, 0x2665, ambiguous},
{0x2667, 0x266A, ambiguous},
{0x266C, 0x266D, ambiguous},
{0x266F, 0x266F, ambiguous},
{0x269E, 0x269F, ambiguous},
{0x26BE, 0x26BF, ambiguous},
{0x26C4, 0x26CD, ambiguous},
{0x26CF, 0x26E1, ambiguous},
{0x26E3, 0x26E3, ambiguous},
{0x26E8, 0x26FF, ambiguous},
{0x273D, 0x273D, ambiguous},
{0x2757, 0x2757, ambiguous},
{0x2776, 0x277F, ambiguous},
{0x27E6, 0x27ED, narrow},
{0x2985, 0x2986, narrow},
{0x2B55, 0x2B59, ambiguous},
{0x2E80, 0x2E9A, wide},
{0x2E9B, 0x2EF4, wide},
{0x2F00, 0x2FD6, wide},
{0x2FF0, 0x2FFC, wide},
{0x3000, 0x3000, fullwidth},
{0x3001, 0x303E, wide},
{0x3041, 0x3097, wide},
{0x3099, 0x3100, wide},
{0x3105, 0x312E, wide},
{0x3131, 0x318F, wide},
{0x3190, 0x31BB, wide},
{0x31C0, 0x31E4, wide},
{0x31F0, 0x321F, wide},
{0x3220, 0x3247, wide},
{0x3248, 0x324F, ambiguous},
{0x3250, 0x32FF, wide},
{0x3300, 0x4DBF, wide},
{0x4E00, 0xA48D, wide},
{0xA490, 0xA4C7, wide},
{0xA960, 0xA97D, wide},
{0xAC00, 0xD7A4, wide},
{0xE000, 0xF8FF, ambiguous},
{0xF900, 0xFAFF, wide},
{0xFE00, 0xFE0F, ambiguous},
{0xFE10, 0xFE1A, wide},
{0xFE30, 0xFE53, wide},
{0xFE54, 0xFE67, wide},
{0xFE68, 0xFE6C, wide},
{0xFF01, 0xFF60, fullwidth},
{0xFF61, 0xFFBF, halfwidth},
{0xFFC2, 0xFFC8, halfwidth},
{0xFFCA, 0xFFD0, halfwidth},
{0xFFD2, 0xFFD8, halfwidth},
{0xFFDA, 0xFFDD, halfwidth},
{0xFFE0, 0xFFE7, fullwidth},
{0xFFE8, 0xFFEF, halfwidth},
{0xFFFD, 0xFFFE, ambiguous},
{0x1B000, 0x1B002, wide},
{0x1F100, 0x1F10A, ambiguous},
{0x1F110, 0x1F12D, ambiguous},
{0x1F130, 0x1F169, ambiguous},
{0x1F170, 0x1F19B, ambiguous},
{0x1F200, 0x1F203, wide},
{0x1F210, 0x1F23B, wide},
{0x1F240, 0x1F249, wide},
{0x1F250, 0x1F252, wide},
{0x20000, 0x2FFFE, wide},
{0x30000, 0x3FFFE, wide},
{0xE0100, 0xE01F0, ambiguous},
{0xF0000, 0xFFFFD, ambiguous},
{0x100000, 0x10FFFE, ambiguous},
}
type Condition struct {
EastAsianWidth bool
}
func NewCondition() *Condition {
return &Condition{EastAsianWidth}
}
// RuneWidth returns the number of cells in r.
// See http://www.unicode.org/reports/tr11/
func (c *Condition) RuneWidth(r rune) int {
if r == 0 {
return 0
}
if r < 32 || (r >= 0x7f && r < 0xa0) {
return 1
}
for _, iv := range combining {
if iv.first <= r && r <= iv.last {
return 0
}
}
if c.EastAsianWidth && IsAmbiguousWidth(r) {
return 2
}
if r >= 0x1100 &&
(r <= 0x115f || r == 0x2329 || r == 0x232a ||
(r >= 0x2e80 && r <= 0xa4cf && r != 0x303f) ||
(r >= 0xac00 && r <= 0xd7a3) ||
(r >= 0xf900 && r <= 0xfaff) ||
(r >= 0xfe30 && r <= 0xfe6f) ||
(r >= 0xff00 && r <= 0xff60) ||
(r >= 0xffe0 && r <= 0xffe6) ||
(r >= 0x20000 && r <= 0x2fffd) ||
(r >= 0x30000 && r <= 0x3fffd)) {
return 2
}
return 1
}
func (c *Condition) StringWidth(s string) (width int) {
for _, r := range []rune(s) {
width += c.RuneWidth(r)
}
return width
}
func (c *Condition) Truncate(s string, w int, tail string) string {
if c.StringWidth(s) <= w {
return s
}
r := []rune(s)
tw := c.StringWidth(tail)
w -= tw
width := 0
i := 0
for ; i < len(r); i++ {
cw := c.RuneWidth(r[i])
if width+cw > w {
break
}
width += cw
}
return string(r[0:i]) + tail
}
func (c *Condition) Wrap(s string, w int) string {
width := 0
out := ""
for _, r := range []rune(s) {
cw := RuneWidth(r)
if r == '\n' {
out += string(r)
width = 0
continue
} else if width+cw > w {
out += "\n"
width = 0
out += string(r)
width += cw
continue
}
out += string(r)
width += cw
}
return out
}
func (c *Condition) FillLeft(s string, w int) string {
width := c.StringWidth(s)
count := w - width
if count > 0 {
b := make([]byte, count)
for i := range b {
b[i] = ' '
}
return string(b) + s
}
return s
}
func (c *Condition) FillRight(s string, w int) string {
width := c.StringWidth(s)
count := w - width
if count > 0 {
b := make([]byte, count)
for i := range b {
b[i] = ' '
}
return s + string(b)
}
return s
}
// RuneWidth returns the number of cells in r.
// See http://www.unicode.org/reports/tr11/
func RuneWidth(r rune) int {
return DefaultCondition.RuneWidth(r)
}
func ct(r rune) ctype {
for _, iv := range ctypes {
if iv.first <= r && r <= iv.last {
return iv.ctype
}
}
return neutral
}
// IsAmbiguousWidth returns whether is ambiguous width or not.
func IsAmbiguousWidth(r rune) bool {
return ct(r) == ambiguous
}
// IsAmbiguousWidth returns whether is ambiguous width or not.
func IsNeutralWidth(r rune) bool {
return ct(r) == neutral
}
func StringWidth(s string) (width int) {
return DefaultCondition.StringWidth(s)
}
func Truncate(s string, w int, tail string) string {
return DefaultCondition.Truncate(s, w, tail)
}
func Wrap(s string, w int) string {
return DefaultCondition.Wrap(s, w)
}
func FillLeft(s string, w int) string {
return DefaultCondition.FillLeft(s, w)
}
func FillRight(s string, w int) string {
return DefaultCondition.FillRight(s, w)
}

@ -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
}

@ -0,0 +1,69 @@
// +build !windows,!js
package runewidth
import (
"os"
"regexp"
"strings"
)
var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`)
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
}
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
}
}
mbc_max := 1
switch charset {
case "utf-8", "utf8":
mbc_max = 6
case "jis":
mbc_max = 8
case "eucjp":
mbc_max = 3
case "euckr", "euccn":
mbc_max = 2
case "sjis", "cp932", "cp51932", "cp936", "cp949", "cp950":
mbc_max = 2
case "big5":
mbc_max = 2
case "gbk", "gb2312":
mbc_max = 2
}
if mbc_max > 1 && (charset[0] != 'u' ||
strings.HasPrefix(locale, "ja") ||
strings.HasPrefix(locale, "ko") ||
strings.HasPrefix(locale, "zh")) {
return true
}
return false
}

@ -0,0 +1,229 @@
package runewidth
import (
"testing"
)
var runewidthtests = []struct {
in rune
out int
}{
{'ไธ–', 2},
{'็•Œ', 2},
{'๏ฝพ', 1},
{'๏ฝถ', 1},
{'๏ฝฒ', 1},
{'โ˜†', 2}, // double width in ambiguous
{'\x00', 0},
{'\x01', 1},
{'\u0300', 0},
}
func TestRuneWidth(t *testing.T) {
c := NewCondition()
c.EastAsianWidth = true
for _, tt := range runewidthtests {
if out := c.RuneWidth(tt.in); out != tt.out {
t.Errorf("Width(%q) = %q, want %q", tt.in, out, tt.out)
}
}
}
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) = %q, want %q", tt.in, out, tt.out)
}
}
}
var stringwidthtests = []struct {
in string
out int
}{
{"โ– ใˆฑใฎไธ–็•Œโ‘ ", 12},
{"ใ‚นใ‚ฟใƒผโ˜†", 8},
}
func TestStringWidth(t *testing.T) {
c := NewCondition()
c.EastAsianWidth = true
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)
}
}
}
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) = %q, want %q", 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)
}
}

@ -0,0 +1,24 @@
package runewidth
import (
"syscall"
)
var (
kernel32 = syscall.NewLazyDLL("kernel32")
procGetConsoleOutputCP = kernel32.NewProc("GetConsoleOutputCP")
)
func IsEastAsian() bool {
r1, _, _ := procGetConsoleOutputCP.Call()
if r1 == 0 {
return false
}
switch int(r1) {
case 932, 51932, 936, 949, 950:
return true
}
return false
}

@ -0,0 +1,4 @@
# Please keep this file sorted.
Georg Reinke <guelfey@googlemail.com>
nsf <no.smile.face@gmail.com>

@ -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.

@ -0,0 +1,25 @@
## 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.
### API reference
[godoc.org/github.com/nsf/termbox-go](http://godoc.org/github.com/nsf/termbox-go)

@ -0,0 +1,459 @@
// +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.Oflag &^= syscall_OPOST
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
}
}
panic("unreachable")
}
// 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()
}

@ -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