term

package module
v0.0.0-...-d3199ed Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 18, 2020 License: Apache-2.0 Imports: 4 Imported by: 0

README

A terminal voice, 05:06 am on 8th of October 2020

Pixels. I don't like pixels. Some people call them cells. Like prison cells... They are all just abstraction, while me, a terminal, I'm real.

My author here, attempted to write me better. He likes channels. He is more suitable to work on Danube-Black Sea channel. Or just get a life, instead of using Go channels to experiment on me.

He reaped the work of a lifetime from other people for that. Just a bunch of constants and concepts and patterns, if you ask me.

He thinks that something goes faster if you have less allocation. We will see in the end. He also thinks in separation of concerns, whatever that means. It's probably abstraction too. Just like pixels, and I don't like pixels.

What is this?

Well, everything started while playing with tcell. I've asked myself why there is no separation of concerns inside of it. I mean, the problem it's simple: we have a file reader - for reading input from keyboard and mouse - and a file writer to display stuff. Everything else are just rules and functionality which terminals provide, a bunch of predefined []byte which are used to send commands.

While thinking about separation of concerns, I've asked myself about context.Context : is it or it is not for cancellation? It seems that in this context, the context.Context is suitable for cancellation usage. The Application will provide a cancellable context.Context and upon shutdown (think CTRL+Q or double ESC), it will cancel it.

Package info

This holds various terminal specific commands, which are registered and looked up by the core. For using as little allocation as possible, I've created []byte slices for each and every used command, so instead of passing string around, we're just using those slices to write to output. Also, there are caches for goto and colors, so []byte required to be written in output is cached. Despite the fact that is has public methods and properties, it's not intended for direct usage, being core's responsibility to orchestrate the writes to output.

Package core

Creates key, event and resize dispatchers. All events are passed via channels, to avoid allocations.

The core constructor supports functional options : NewCore(termEnv string, options ...Option).

Possible options are :

  • WithFinalizer - for the case when Application want to execute a function prior shutdown.
  • WithWinSizeBufferedChannelSize - Application can set the size of the buffered channel. Defaults to runtime.NumCPU().
  • WithRunesFallback - Application can set the runes fallback upon constructing.
  • WithTrueColor - a functional option so Application can send "disable" to disable true color
Responsibilities
  • offers information about terminal (size, colors, has mouse, charset, keys)
  • registers/unregister listeners for term.Pixel changes
  • registers/unregister Mouse and Key handlers
  • registers/unregister Resize event handlers
  • offers ability to show or hide the cursor
  • the core exists for the whole Application lifecycle

Constructor returns an interface. The Engine interface:

  • DyingChan() chan struct{} - it's a channel that needs to be listened inside Application, to allow gracefully shutdowns.
  • Start(ctx context.Context) error - the Application call this method with a cancellable context, so core will shutdown upon cancellation.
  • ResizeDispatcher() ResizeDispatcher - exposes the resize dispatcher, so Components can Register themselves to listening events.
  • KeyDispatcher() KeyDispatcher - exposes the key dispatcher, so Components can Register themselves to listening events.
  • MouseDispatcher() MouseDispatcher - exposes the mouse dispatcher, so Components can Register themselves to listening events.
  • CanDisplay(r rune, checkFallbacks bool) bool - checks if the rune can be displayed in terminal.
  • CharacterSet() string - returns the current char set.
  • SetRuneFallback(orig rune, fallback string) - sets the fallback for a rune.
  • UnsetRuneFallback(orig rune) - forgets the fallback set above.
  • NumColors() int - returns the number of colors that terminal supports.
  • Size() *Size - returns the current size of the window.
  • HasTrueColor() bool - returns the terminal support for true colors.
  • Palette() []color.Color - returns the terminal palette
  • Colors() map[color.Color]color.Color - returns the terminal color map.
  • ActivePixels(pixels []PixelGetter) - used by Application to orchestrate pixels. Pages will be able to have their own set of pixels.
  • Redraw(pixels []PixelGetter) - temporary exposed for Application to force draw.
  • ShowCursor(where *term.Position) - displays input cursor at coordinates.
  • HideCursor() - hides input cursor.
  • Cursor() *term.Position - returns current input cursor position.
  • Clear() - clears the screen.
  • Style() Style - returns the terminal styles and palette. Style is an interface.
  • HasMouse() bool - returns true if there is mouse support available.

ResizeEvent is an interface has only one method Size() Size and Size has - of course - Width and Height properties.

Application must call Start(ctx context.Context) error with a cancellable context, in order to use ActivePixels(pixels []PixelGetter) registration.

Package geom

A Pixel is an interface which is known by both Application and Engine. The setters will write to a channel, so core can receive the draw request, when a property of the pixel has changed.

A Pixel constructor accepts the following functional options:

  • WithBackground - presets the background color.
  • WithForeground - presets the foreground (text) color.
  • WithPoint - is required, and sets the position of the pixel (column and row).
  • WithRune - presets the rune.
  • WithUnicode - presets the unicode (optional, for that reason it is a pointer).
  • WithAttrs - presets the style.Mask of the Pixel.

The Pixel interface (includes PixelGetter and PixelSetter interfaces):

  • DrawCh() chan Pixel - the channel used by core to listen redraw request.
  • PositionHash() int - the position hash of the Pixel.
  • Style() (color.Color, color.Color, style.Mask) - colors and attributes of the Pixel, expanded as foreground, background and attributes
  • Rune() rune - rune.
  • Width() int - rune and Unicode width.
  • HasUnicode() bool - exposes if Unicode is a nil pointer or not.
  • Unicode() Unicode - Unicode if declared.
  • Set(r rune, fg, bg color.Color) - setter for rune and colors. If any of them changed, redraw request gets triggered.
  • SetFgBg(fg, bg color.Color) - setter for colors. If any of them changed, redraw request gets triggered.
  • SetForeground(c color.Color) - setter just for foreground.
  • SetBackground(c color.Color) - setter just for background.
  • SetAttrs(m style.Mask) - setter for style.Mask.
  • SetUnicode(u Unicode) - setter for Unicode.
  • SetRune(r rune) - setter for rune.
  • SetAll(bg, fg color.Color, m style.Mask, r rune, u Unicode) - setter for everything. If any of them changed, redraw request gets triggered.

Package key

  • Register(r KeyListener) - used by Components to register to events listening. Events come via a channel (listener must implement KeyListener interface).
  • LifeCycle(ctx context.Context) - used by core upon Start(ctx context.Context) error call.
  • HasKey(k Key) bool - checks if terminal supports the key provided as parameter.
  • DyingChan() chan struct{} - core listens to this channel to check if dispatcher has finished shutdown, upon context cancellation.
  • InChan() chan []byte - core uses this channel to send input from terminal.

Package mouse

  • Register(r MouseListener)- used by Components to register to events listening. Events come via a channel (listener must implement MouseListener interface).
  • LifeCycle(ctx context.Context, out *os.File)- used by core upon Start(ctx context.Context) error call.
  • Enable() - enables mouse support
  • Disable() - disables mouse support
  • ResizeListen() chan ResizeEvent - core uses this channel to send resize events.
  • DyingChan() chan struct{} - core listens to this channel to check if dispatcher has finished shutdown, upon context cancellation.
  • InChan() chan []byte - core uses this channel to send input from terminal.

Package style

  • Palette() []color.Color - returns the known palette
  • Colors() map[color.Color]color.Color - returns all colors map

Documentation

Index

Constants

View Source
const (
	MinusOneMinusOne = 4294967295
)

Variables

This section is empty.

Functions

func Abs

func Abs(a int) int

Abs returns the absolute value

func Hash

func Hash(column, row int) int

Hash - combines a row and a column into a single integer. Note that it doesn't work with very large numbers.

func Height

func Height(p1, p2 *Position) int

Height

func Max

func Max(x, y int) int

Max returns the larger of the passed values.

func Min

func Min(x, y int) int

Min returns the smaller of the passed values.

func UnHash

func UnHash(hash int) (int, int)

UnHash - given a hash built with above function, return the original column and row. Note that negative values are not returned correctly. Use UnHashNeg below.

func UnHashNeg

func UnHashNeg(hash int) (int, int)

UnHashNeg - given a hash built with above function, return the original column and row. Note that negative values are "special"

func Width

func Width(p1, p2 *Position) int

Width

Types

type ButtonMask

type ButtonMask int16

ButtonMask is a mask of mouse buttons and wheel events. Mouse button presses are normally delivered as both press and release events. Mouse wheel events are normally just single impulse events. Windows supports up to eight separate buttons plus all four wheel directions, but XTerm can only support mouse buttons 1-3 and wheel up/down. Its not unheard of for terminals to support only one or two buttons (think Macs). Old terminals, and true emulations (such as vt100) won't support mice at all, of course.

type Death

type Death interface {
	DyingChan() chan struct{}
}

Death is provided by both dispatchers and receivers

type Engine

type Engine interface {
	Death                                        // returns the chan that creator needs to be listen for graceful shutdown
	Start(ctx context.Context) error             // returns error if we cannot start
	ResizeDispatcher() ResizeDispatcher          // returns the event dispatcher, so listeners can call Register(r Receiver) method
	KeyDispatcher() KeyDispatcher                // returns the event dispatcher, so listeners can call Register(r Receiver) method
	MouseDispatcher() MouseDispatcher            // returns the event dispatcher, so listeners can call Register(r Receiver) method
	CanDisplay(r rune, checkFallbacks bool) bool // checks if a rune can be displayed
	CharacterSet() string                        // getter for current charset
	SetRuneFallback(orig rune, fallback string)  // sets a fallback for a rune
	UnsetRuneFallback(orig rune)                 // forgets fallback for a rune
	NumColors() int                              // returns the number of colors of the current display
	Size() *Size                                 // returns the size of the current display
	HasTrueColor() bool                          // returns true if can display true color
	Style() Style                                // returns the terminal styles and palette
	ActivePixels(pixels []PixelGetter)           // registers the active pixels, forgetting the old ones. This behaviour should be found in Pages
	Redraw(pixels []PixelGetter)                 // does a buffered redraw of the screen (TODO : should not be used)
	ShowCursor(where *Position)                  // shows the cursor at the indicated position
	HideCursor()                                 // hides the cursor
	Cursor() *Position                           // returns the cursor current position
	Clear()                                      // cleans the screen
	HasMouse() bool                              // returns true if mouse support is available
}

Engine is the interface of the core

type InputListener

type InputListener interface {
	InChan() chan []byte
}

InputListener is implemented by MouseDispatcher and KeyDispatcher

type Key

type Key int16

Key is a generic value for representing keys, and especially special keys (function keys, cursor movement keys, etc.) For normal keys, like ASCII letters, we use Rune, and then expect the application to inspect the Rune() member of the KeyEvent.

type KeyDispatcher

type KeyDispatcher interface {
	Death
	InputListener
	Lifecycler
	Register(r KeyListener)
	HasKey(k Key) bool
}

we hide our implementation behind this interface

type KeyEvent

type KeyEvent interface {
	Rune() rune
	Key() Key
	Modifiers() ModMask
	Name() string
	ModName() string
}

type KeyListener

type KeyListener interface {
	Death
	KeyListen() chan KeyEvent
}

KeyListener must be implementers of KeyEvent

type Lifecycler

type Lifecycler interface {
	LifeCycle(ctx context.Context)
}

Lifecycler implements a context cancel listener

type ModMask

type ModMask int16

ModMask is a mask of modifier keys. Note that it will not always be possible to report modifier keys.

type MouseDispatcher

type MouseDispatcher interface {
	ResizeListener
	InputListener
	Lifecycler
	Register(r MouseListener)
	Enable()
	Disable()
}

MouseDispatcher is implemented in mouse package

type MouseEvent

type MouseEvent interface {
	Buttons() ButtonMask
	Modifiers() ModMask
	Position() (int, int)
	ButtonNames() string
	ModName() string
}

MouseEvent is an interface that is implemented by mouse package

type MouseListener

type MouseListener interface {
	Death
	MouseListen() chan MouseEvent
}

MouseListener is implemented by listeners of mouse events

type Pixel

type Pixel interface {
	PixelGetter
	PixelSetter
}

type PixelGetter

type PixelGetter interface {
	DrawCh() chan PixelGetter                      // channel which tells core that pixel needs drawing
	PositionHash() int                             // position (x,y) where is pixel is placed
	Style() (color.Color, color.Color, style.Mask) // style (background and foreground colors, attributes)
	Rune() rune                                    // the rune pixel contains
	Width() int                                    // the width of the rune, usually is 1, but unicode adds more to it
	HasUnicode() bool                              // helper for not reading unicode everytime
	Unicode() *Unicode                             // if unicode, it adds to the rune
}

PixelGetter is the complete interface (both setter and getter)

type PixelSetter

type PixelSetter interface {
	Set(r rune, fg, bg color.Color)                             // sets both colors and rune so we don't do three calls
	SetFgBg(fg, bg color.Color)                                 // sets both colors, so we don't do two calls (usually only if the colors have changed)
	SetForeground(c color.Color)                                // as name says
	SetBackground(c color.Color)                                // as name says
	SetAttrs(m style.Mask)                                      // as name says
	SetUnicode(u Unicode)                                       // as name says
	SetRune(r rune)                                             // sets the content of the pixel and triggers redrawing
	SetAll(bg, fg color.Color, m style.Mask, r rune, u Unicode) // in case we need to call all changes, without placing too many calls
}

PixelSetter is the complete interface (both setter and getter)

type Position

type Position struct {
	Row    int
	Column int
	// contains filtered or unexported fields
}

func Center

func Center(p1, p2 *Position) *Position

Center : both parameters should be odd numbers

func NewPosition

func NewPosition(column, row int) *Position

NewPosition

func (*Position) Hash

func (p *Position) Hash() int

Position hash

func (*Position) PlusCols

func (p *Position) PlusCols(plusColumns int) *Position

PlusCols

func (*Position) PlusRows

func (p *Position) PlusRows(plusRows int) *Position

PlusRows

func (Position) String

func (p Position) String() string

Stringer implementation

func (*Position) UpdateHash

func (p *Position) UpdateHash()

UpdateHash - refreshes the hash on row/column change

type ResizeDispatcher

type ResizeDispatcher interface {
	Death
	Register(r ResizeListener)
}

ResizeDispatcher is implemented by core engine

type ResizeEvent

type ResizeEvent interface {
	Size() *Size
}

ResizeEvent is an interface that implemented by core

type ResizeListener

type ResizeListener interface {
	Death
	ResizeListen() chan ResizeEvent
}

ResizeListener is for listeners that must implement this interface

type Size

type Size struct {
	Columns int // The number of units along the horizontal axis.
	Rows    int // The number of units along the vertical axis.
}

Size describes something with width and height.

func NewSize

func NewSize(columns int, rows int) *Size

NewSize returns a newly allocated Size of the specified dimensions.

func (*Size) Add

func (s *Size) Add(s2 *Size) Size

Add returns a new Size that is the result of increasing the current size by s2 Width and Height.

func (*Size) IsZero

func (s *Size) IsZero() bool

IsZero returns whether the Size has zero width and zero height.

func (*Size) Max

func (s *Size) Max(s2 Size) *Size

Max returns a new Size that is the maximum of the current Size and s2.

func (*Size) Min

func (s *Size) Min(s2 Size) *Size

Min returns a new Size that is the minimum of the current Size and s2.

func (*Size) Subtract

func (s *Size) Subtract(s2 Size) Size

Subtract returns a new Size that is the result of decreasing the current size by s2 Width and Height.

type Style

type Style interface {
	Colors() map[color.Color]color.Color //
	Palette() []color.Color              //
	FindColor(c color.Color) color.Color //
}

type Unicode

type Unicode []rune

Directories

Path Synopsis
The colorful package provides all kinds of functions for working with colors.
The colorful package provides all kinds of functions for working with colors.
Package easing is a go implementation of Robert Penner's Easing Equations - http://robertpenner.com/easing/
Package easing is a go implementation of Robert Penner's Easing Equations - http://robertpenner.com/easing/
playground

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL