fixes #26 Improved docs desired

This commit is contained in:
Garrett D'Amore 2015-10-05 15:46:51 -07:00
parent c2130fd973
commit b19d7067f2
11 changed files with 168 additions and 40 deletions

View File

@ -14,7 +14,8 @@
package tcell
// AttrMask represents a mask of text attributes.
// AttrMask represents a mask of text attributes, apart from color.
// Note that support for attributes may vary widely across terminals.
type AttrMask int
// NB: the colors listed here are in the order that ANSI terminals expect.
@ -25,5 +26,7 @@ const (
AttrReverse
AttrUnderline
AttrDim
// AttrNone is just normal text.
AttrNone AttrMask = 0
)

View File

@ -81,6 +81,9 @@ func (c *Cell) SetCell(ch []rune, style Style) {
c.PutStyle(style)
}
// PutChars is a handy way to write runes to the Cell, without changing its
// style. The first rune should be a printable non-zero width value, and
// subsequent values may be combining marks.
func (c *Cell) PutChars(ch []rune) {
var mainc rune
@ -120,10 +123,14 @@ func (c *Cell) PutChars(ch []rune) {
c.Width = width
}
// PutChar writes a single rune into the cells location. The rune should be a
// a normal (not combining) printable character.
func (c *Cell) PutChar(ch rune) {
c.PutChars([]rune{ch})
}
// PutStyle changes the style of the given Cell, without altering the character
// content.
func (c *Cell) PutStyle(style Style) {
if c.Style != style {
c.Style = style

View File

@ -20,6 +20,8 @@ package tcell
type Color int16
const (
// ColorDefault is used to leave the Color unchanged from whatever
// system or teminal default may exist.
ColorDefault Color = iota
ColorBlack
ColorRed

40
doc.go Normal file
View File

@ -0,0 +1,40 @@
// Copyright 2015 The TCell Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use file except in compliance with the License.
// You may obtain a copy of the license at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package tcell provides a lower-level, portable API for building
// programs that interact with terminals or consoles. It works with
// both common (and many uncommon!) terminals or terminal emulators,
// and Windows console implementations.
//
// It provides support for up to 256 colors, text attributes, and box drawing
// elements. A database of terminals built from a real terminfo database
// is provided, along with code to generate new database entries.
//
// Tcell offers very rich support for mice, dependent upon the terminal
// of course. (Windows, XTerm, and iTerm 2 are known to work very well.)
//
// If the environment is not Unicode by default, such as an ISO8859 based
// locale or GB18030, Tcell can convert input and outupt, so that your
// terminal can operate in whatever locale is most convenient, while the
// application program can just assume "everything is UTF-8". Reasonable
// defaults are used for updating characters to something suitable for
// display. Unicode box drawing characters will be converted to use the
// alternate character set of your terminal, if native conversions are
// not available. If no ACS is available, then some ASCII fallbacks will
// be used.
//
// A rich set of keycodes is supported, with support for up to 65 function
// keys, and various other special keys.
//
package tcell

View File

@ -23,38 +23,46 @@ import (
var encodings map[string]encoding.Encoding
var encodingLk sync.Mutex
// RegisterEncoding may be called by the application to register an encoding. The
// presence of additional encodings will facilitate application usage with terminal
// environments where the I/O subsystem does not support Unicode. Please see the
// Go documentation for encodings -- most of the common ones exist already as stock
// variables. For example, ISO8859-15 can be registered using the following code:
// RegisterEncoding may be called by the application to register an encoding.
// The presence of additional encodings will facilitate application usage with
// terminal environments where the I/O subsystem does not support Unicode.
// Please see the Go documentation for golang.org/x/text/encoding -- most of
// the common ones exist already as stock variables. For example, ISO8859-15
// can be registered using the following code:
//
// import "golang.org/x/text/encoding/charmap"
//
// ...
// RegisterEncoding("ISO8859-15", charmap.ISO8859_15)
//
// Aliases can be registered as well, for example "8859-15" could be an alias for
// "ISO8859-15".
// Aliases can be registered as well, for example "8859-15" could be an alias
// for "ISO8859-15".
//
// For POSIX systems, the tcell pacakge will check the environment variables LC_ALL, LC_CTYPE,
// and LANG (in that order) to determine the character set. These are expected to have the
// following pattern: $language[.$codeset[@$variant] We extract only the $codeset part,
// which will usually be something like UTF-8 or ISO8859-15 or KOI8-R. Note that if the
// locale is either "POSIX" or "C", then we assume US-ASCII (the POSIX 'portable character set'
// For POSIX systems, the tcell pacakge will check the environment variables
// LC_ALL, LC_CTYPE, and LANG (in that order) to determine the character set.
// These are expected to have the following pattern:
//
// $language[.$codeset[@$variant]
// We extract only the $codeset part, which will usually be something like
// UTF-8 or ISO8859-15 or KOI8-R. Note that if the locale is either "POSIX"
// or "C", then we assume US-ASCII (the POSIX 'portable character set'
// and assume all other characters are somehow invalid.)
//
// On Windows systems, the Console is assumed to be UTF-16LE. As we communicate with the
// console subsystem using UTF-16LE, no conversions are necessary. So none of this is required
// for Windows systems.
// On Windows systems, the Console is assumed to be UTF-16LE. As we
// communicate with the console subsystem using UTF-16LE, no conversions are
// necessary. So none of this is required for Windows systems.
//
// Modern POSIX systems and terminal emulators may use UTF-8, and for those systems, this
// API is also unnecessary. For example, Darwin (MacOS X) and modern Linux running modern
// xterm generally will out of the box without any of this.
// Modern POSIX systems and terminal emulators may use UTF-8, and for those
// systems, this API is also unnecessary. For example, Darwin (MacOS X) and
// modern Linux running modern xterm generally will out of the box without
// any of this. Use of UTF-8 is recommended when possible, as it saves
// quite a lot processing overhead.
//
// Note that some encodings are quite large (for example GB18030 which is a superset of
// Unicode) and so the application size can be expected ot increase quite a bit as each
// encoding is added.
// Note that some encodings are quite large (for example GB18030 which is a
// superset of Unicode) and so the application size can be expected ot
// increase quite a bit as each encoding is added. The East Asian encodings
// have been seen to add 100-200K per encoding to the application size.
//
func RegisterEncoding(name string, enc encoding.Encoding) {
encodingLk.Lock()
@ -65,6 +73,10 @@ func RegisterEncoding(name string, enc encoding.Encoding) {
encodingLk.Unlock()
}
// GetEncoding is used by Screen implementors who want to locate an encoding
// for the given character set name. Note that this will return nil for
// either the Unicode (UTF-8) or ASCII encodings, since we don't use
// encodings for them but instead have our own native methods.
func GetEncoding(name string) encoding.Encoding {
encodingLk.Lock()
defer encodingLk.Unlock()

18
key.go
View File

@ -40,7 +40,8 @@ import (
//
// Generally, terminal applications have far less visibility into keyboard
// activity than graphical applications. Hence, they should avoid depending
// overly much on availability of such details.
// overly much on availability of modifiers, or the availability of any
// specific keys.
type EventKey struct {
t time.Time
mod ModMask
@ -48,22 +49,37 @@ type EventKey struct {
ch rune
}
// When returns the time when this Event was created, which should closely
// match the time when the key was pressed.
func (*EventKey) When() time.Time {
return time.Now()
}
// Rune returns the rune corresponding to the key press, if it makes sense.
// The result is only defined if the value of Key() is KeyRune.
func (ev *EventKey) Rune() rune {
return ev.ch
}
// Key returns a virtual key code. We use this to identify specific key
// codes, such as KeyEnter, etc. Most control and function keys are reported
// with unique Key values. Normal alphanumeric and punctuation keys will
// generally return KeyRune here; the specific key can be further decoded
// using the Rune() function.
func (ev *EventKey) Key() Key {
return ev.key
}
// ModMask returns the modifiers that were present with the key press. Note
// that not all platforms and terminals support this equally well, and some
// cases we will not not know for sure. Hence, applications should avoid
// using this in most circumstances.
func (ev *EventKey) Mod() ModMask {
return ev.mod
}
// Name returns a printable value or the key stroke. This can be used
// when printing the event, for example.
func (ev *EventKey) Name() string {
s := ""
m := []string{}

View File

@ -25,10 +25,12 @@ import (
// without any intervening button release.
//
// Mouse wheel events, when reported, may appear on their own as individual
// impulses.
// impulses; that is, there will normally not be a release event delivered
// for mouse wheel movements.
//
// Most terminals cannot report the state of more than one button at a time --
// and few can report motion events.
// and many cannot report motion events. (Windows consoles, modern XTerm, and
// modern emulators like iTerm2, are known to support this well, though.)
//
// Applications can inspect the time between events to figure out double clicks
// and such.
@ -44,18 +46,25 @@ func (ev *EventMouse) When() time.Time {
return ev.t
}
// ButtonMask returns the list of buttons that were pressed.
func (ev *EventMouse) Buttons() ButtonMask {
return ev.btn
}
// Modifiers returns a list of keyboard modifiers that were pressed
// with the mouse button(s).
func (ev *EventMouse) Modifiers() ModMask {
return ev.mod
}
// Position returns the mouse position in character cells. The origin
// 0, 0 is at the upper left corner.
func (ev *EventMouse) Position() (int, int) {
return ev.x, ev.y
}
// NewEventMouse is used to create a new mouse event. Applications
// shouldn't need to use this; its mostly for screen implementors.
func NewEventMouse(x, y int, btn ButtonMask, mod ModMask) *EventMouse {
return &EventMouse{t: time.Now(), x: x, y: y, btn: btn, mod: mod}
}
@ -64,15 +73,20 @@ func NewEventMouse(x, y int, btn ButtonMask, mod ModMask) *EventMouse {
type ButtonMask int16
const (
// Button1 is usually the left mouse button.
Button1 ButtonMask = 1 << iota
// Button2 is usually the middle mouse button, for three button mice.
Button2
// Button3 is usually the right mouse button on 2 or 3 button mice.
Button3
Button4
Button5
Button6
Button7
Button8
// WheelUp indicates the wheel being moved up, away from the user.
WheelUp
// WheelDown indicates the wheel being moved down, towards the user.
WheelDown
WheelLeft
WheelRight

View File

@ -14,10 +14,9 @@
package tcell
// Screen represents the physical (or emulated) screen, without any buffering.
// Screen represents the physical (or emulated) screen.
// This can be a terminal window or a physical console. Platforms implement
// this differerently. Applications are unlikely to interface directly with
// this.
// this differerently.
type Screen interface {
// Init initializes the screen for use.
Init() error
@ -25,7 +24,9 @@ type Screen interface {
// Fini finalizes the screen also releasing resources.
Fini()
// Clear erases the screen.
// Clear erases the screen. The contents of any screen buffers
// will also be cleared. This has the logical effect of
// filling the screen with spaces, using the global default style.
Clear()
// SetCell sets the cell at the given location.
@ -61,7 +62,7 @@ type Screen interface {
GetCell(x, y int) *Cell
// SetStyle sets the default style to use when clearing the screen
// or when StyleDefault is specified. If it is also STyleDefault,
// or when StyleDefault is specified. If it is also StyleDefault,
// then whatever system/terminal default is relevant will be used.
SetStyle(style Style)
@ -93,13 +94,13 @@ type Screen interface {
DisableMouse()
// Colors returns the number of colors. All colors are assumed to
// use the ANSI color map.
// use the ANSI color map. If a terminal is monochrome, it will
// return 0.
Colors() int
// Show takes any output that was deferred due to buffering, and
// flushes it to the physical display. It does so in the least
// expensive and disruptive manner possible, only making writes that
// are believed to actually be necessary.
// flushes it to the physical display. It does so in the most
// efficient and least visually disruptive manner possible.
Show()
// Sync works like Show(), but it updates every visible cell on the
@ -119,6 +120,8 @@ type Screen interface {
CharacterSet() string
}
// NewScreen returns a default Screen suitable for the user's terminal
// environment.
func NewScreen() (Screen, error) {
// First we attempt to obtain a terminfo screen. This should work
// in most places if $TERM is set.

View File

@ -14,10 +14,15 @@
package tcell
// Color represents a color. We encode it in a 64-bit int for efficiency.
// Style represents a complete text style, including both foreground
// and background color. We encode it in a 64-bit int for efficiency.
// The coding is (MSB): <16b rsvd><16b attr><16b fgcolor><16b bgcolor>.
// This gives 16bit color options, if it ever becomes truly necessary.
// I can't see a need to get beyond 256 colors.
// However, applications must not rely on this encoding.
//
// Note that not all terminals can display all colors or attributes, and
// many might have specific incompatibilities between specific attributes
// and color combinations.
type Style int64
func NewStyle() Style {
@ -26,15 +31,21 @@ func NewStyle() Style {
const StyleDefault Style = 0
// Foreground returns a new style based on s, with the foreground color set
// as requested. ColorDefault can be used to select the global default.
func (s Style) Foreground(c Color) Style {
return (s &^ Style(0xffff0000)) | (Style(c) << 16)
}
// Background returns a new style based on s, with the background color set
// as requested. ColorDefault can be used to select the global default.
func (s Style) Background(c Color) Style {
return (s &^ (0xffff)) | Style(c)
}
func (s Style) Decompose() (Color, Color, AttrMask) {
// Decompose breaks a style up, returning the foreground, background,
// and other attributes.
func (s Style) Decompose() (fg Color, bg Color, attr AttrMask) {
return Color((s >> 16) & 0xffff),
Color(s & 0xfffff),
AttrMask((s >> 32) & 0xffff)
@ -53,22 +64,33 @@ func (s Style) Normal() Style {
return s &^ (Style(0xfffff) << 32)
}
// Bold returns a new style based on s, with the bold attribute set
// as requested.
func (s Style) Bold(on bool) Style {
return s.setAttrs(Style(AttrBold), on)
}
// Blink returns a new style based on s, with the blink attribute set
// as requested.
func (s Style) Blink(on bool) Style {
return s.setAttrs(Style(AttrBlink), on)
}
// Dim returns a new style based on s, with the dim attribute set
// as requested.
func (s Style) Dim(on bool) Style {
return s.setAttrs(Style(AttrDim), on)
}
// Reverse returns a new style based on s, with the reverse attribute set
// as requested. (Reverse usually changes the foreground and background
// colors.)
func (s Style) Reverse(on bool) Style {
return s.setAttrs(Style(AttrReverse), on)
}
// Reverse returns a new style based on s, with the underline attribute set
// as requested.
func (s Style) Underline(on bool) Style {
return s.setAttrs(Style(AttrUnderline), on)
}

View File

@ -26,6 +26,14 @@ import (
"golang.org/x/text/transform"
)
// NewTerminfoScreen returns a Screen that uses the stock TTY interface
// and POSIX termios, combined with a terminfo description taken from
// the $TERM environment variable. It returns an error if the terminal
// is not supported for any reason.
//
// For terminals that do not support dynamic resize events, the $LINES
// $COLUMNS environment variables can be set to the actual window size,
// otherwise defaults taken from the terminal database are used.
func NewTerminfoScreen() (Screen, error) {
ti, e := LookupTerminfo(os.Getenv("TERM"))
if e != nil {
@ -285,7 +293,6 @@ func (t *tScreen) GetCell(x, y int) *Cell {
return &cell
}
func (t *tScreen) encodeRune(r rune, buf []byte) []byte {
// all the character sets we care about are ASCII supersets
@ -323,7 +330,7 @@ func (t *tScreen) encodeRune(r rune, buf []byte) []byte {
buf = append(buf, '?')
}
}
} else {
} else {
buf = append(buf, nb...)
}
} else if len(buf) == 0 {
@ -925,7 +932,7 @@ func (t *tScreen) parseRune(buf *bytes.Buffer) (bool, bool) {
ev := NewEventKey(KeyRune, r, ModNone)
t.PostEvent(ev)
}
for eat := 0; eat < nin; eat++ {
for eat := 0; eat < nin; eat++ {
buf.ReadByte()
}
return true, true

View File

@ -20,6 +20,8 @@ import (
"errors"
)
// This stub file is for systems that have no termios.
type termiosPrivate struct{}
func (t *tScreen) termioInit() error {