mirror of
https://github.com/taigrr/wtf
synced 2026-04-01 20:38:43 -07:00
Update dependencies to latest versions
This commit is contained in:
2
vendor/github.com/rivo/tview/README.md
generated
vendored
2
vendor/github.com/rivo/tview/README.md
generated
vendored
@@ -65,6 +65,8 @@ Add your issue here on GitHub. Feel free to get in touch if you have any questio
|
||||
|
||||
(There are no corresponding tags in the project. I only keep such a history in this README.)
|
||||
|
||||
- v0.19 (2018-10-28)
|
||||
- Added `QueueUpdate()` and `QueueEvent()` to `Application` to help with modifications to primitives from goroutines.
|
||||
- v0.18 (2018-10-18)
|
||||
- `InputField` elements can now be navigated freely.
|
||||
- v0.17 (2018-06-20)
|
||||
|
||||
337
vendor/github.com/rivo/tview/application.go
generated
vendored
337
vendor/github.com/rivo/tview/application.go
generated
vendored
@@ -1,27 +1,34 @@
|
||||
package tview
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
// The size of the event/update/redraw channels.
|
||||
const queueSize = 100
|
||||
|
||||
// Application represents the top node of an application.
|
||||
//
|
||||
// It is not strictly required to use this class as none of the other classes
|
||||
// depend on it. However, it provides useful tools to set up an application and
|
||||
// plays nicely with all widgets.
|
||||
//
|
||||
// The following command displays a primitive p on the screen until Ctrl-C is
|
||||
// pressed:
|
||||
//
|
||||
// if err := tview.NewApplication().SetRoot(p, true).Run(); err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
type Application struct {
|
||||
sync.RWMutex
|
||||
|
||||
// The application's screen.
|
||||
// The application's screen. Apart from Run(), this variable should never be
|
||||
// set directly. Always use the screenReplacement channel after calling
|
||||
// Fini(), to set a new screen (or nil to stop the application).
|
||||
screen tcell.Screen
|
||||
|
||||
// Indicates whether the application's screen is currently active.
|
||||
running bool
|
||||
|
||||
// The primitive which currently has the keyboard focus.
|
||||
focus Primitive
|
||||
|
||||
@@ -44,13 +51,26 @@ type Application struct {
|
||||
// was drawn.
|
||||
afterDraw func(screen tcell.Screen)
|
||||
|
||||
// Halts the event loop during suspended mode.
|
||||
suspendMutex sync.Mutex
|
||||
// Used to send screen events from separate goroutine to main event loop
|
||||
events chan tcell.Event
|
||||
|
||||
// Functions queued from goroutines, used to serialize updates to primitives.
|
||||
updates chan func()
|
||||
|
||||
// An object that the screen variable will be set to after Fini() was called.
|
||||
// Use this channel to set a new screen object for the application
|
||||
// (screen.Init() and draw() will be called implicitly). A value of nil will
|
||||
// stop the application.
|
||||
screenReplacement chan tcell.Screen
|
||||
}
|
||||
|
||||
// NewApplication creates and returns a new application.
|
||||
func NewApplication() *Application {
|
||||
return &Application{}
|
||||
return &Application{
|
||||
events: make(chan tcell.Event, queueSize),
|
||||
updates: make(chan func(), queueSize),
|
||||
screenReplacement: make(chan tcell.Screen, 1),
|
||||
}
|
||||
}
|
||||
|
||||
// SetInputCapture sets a function which captures all key events before they are
|
||||
@@ -75,29 +95,29 @@ func (a *Application) GetInputCapture() func(event *tcell.EventKey) *tcell.Event
|
||||
|
||||
// SetScreen allows you to provide your own tcell.Screen object. For most
|
||||
// applications, this is not needed and you should be familiar with
|
||||
// tcell.Screen when using this function. Run() will call Init() and Fini() on
|
||||
// the provided screen object.
|
||||
// tcell.Screen when using this function.
|
||||
//
|
||||
// This function is typically called before calling Run(). Calling it while an
|
||||
// application is running will switch the application to the new screen. Fini()
|
||||
// will be called on the old screen and Init() on the new screen (errors
|
||||
// returned by Init() will lead to a panic).
|
||||
//
|
||||
// Note that calling Suspend() will invoke Fini() on your screen object and it
|
||||
// will not be restored when suspended mode ends. Instead, a new default screen
|
||||
// object will be created.
|
||||
// This function is typically called before the first call to Run(). Init() need
|
||||
// not be called on the screen.
|
||||
func (a *Application) SetScreen(screen tcell.Screen) *Application {
|
||||
if screen == nil {
|
||||
return a // Invalid input. Do nothing.
|
||||
}
|
||||
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
if a.running {
|
||||
a.screen.Fini()
|
||||
}
|
||||
a.screen = screen
|
||||
if a.running {
|
||||
if err := a.screen.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if a.screen == nil {
|
||||
// Run() has not been called yet.
|
||||
a.screen = screen
|
||||
a.Unlock()
|
||||
return a
|
||||
}
|
||||
|
||||
// Run() is already in progress. Exchange screen.
|
||||
oldScreen := a.screen
|
||||
a.Unlock()
|
||||
oldScreen.Fini()
|
||||
a.screenReplacement <- screen
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
@@ -114,12 +134,11 @@ func (a *Application) Run() error {
|
||||
a.Unlock()
|
||||
return err
|
||||
}
|
||||
if err = a.screen.Init(); err != nil {
|
||||
a.Unlock()
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err = a.screen.Init(); err != nil {
|
||||
a.Unlock()
|
||||
return err
|
||||
}
|
||||
a.running = true
|
||||
|
||||
// We catch panics to clean up because they mess up the terminal.
|
||||
defer func() {
|
||||
@@ -127,72 +146,118 @@ func (a *Application) Run() error {
|
||||
if a.screen != nil {
|
||||
a.screen.Fini()
|
||||
}
|
||||
a.running = false
|
||||
panic(p)
|
||||
}
|
||||
}()
|
||||
|
||||
// Draw the screen for the first time.
|
||||
a.Unlock()
|
||||
a.Draw()
|
||||
a.draw()
|
||||
|
||||
// Start event loop.
|
||||
for {
|
||||
// Do not poll events during suspend mode
|
||||
a.suspendMutex.Lock()
|
||||
a.RLock()
|
||||
screen := a.screen
|
||||
a.RUnlock()
|
||||
if screen == nil {
|
||||
a.suspendMutex.Unlock()
|
||||
break
|
||||
}
|
||||
|
||||
// Wait for next event.
|
||||
event := a.screen.PollEvent()
|
||||
a.suspendMutex.Unlock()
|
||||
if event == nil {
|
||||
// The screen was finalized. Exit the loop.
|
||||
break
|
||||
}
|
||||
|
||||
switch event := event.(type) {
|
||||
case *tcell.EventKey:
|
||||
a.RLock()
|
||||
p := a.focus
|
||||
a.RUnlock()
|
||||
|
||||
// Intercept keys.
|
||||
if a.inputCapture != nil {
|
||||
event = a.inputCapture(event)
|
||||
if event == nil {
|
||||
break // Don't forward event.
|
||||
}
|
||||
}
|
||||
|
||||
// Ctrl-C closes the application.
|
||||
if event.Key() == tcell.KeyCtrlC {
|
||||
a.Stop()
|
||||
}
|
||||
|
||||
// Pass other key events to the currently focused primitive.
|
||||
if p != nil {
|
||||
if handler := p.InputHandler(); handler != nil {
|
||||
handler(event, func(p Primitive) {
|
||||
a.SetFocus(p)
|
||||
})
|
||||
a.Draw()
|
||||
}
|
||||
}
|
||||
case *tcell.EventResize:
|
||||
// Separate loop to wait for screen events.
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for {
|
||||
a.RLock()
|
||||
screen := a.screen
|
||||
a.RUnlock()
|
||||
screen.Clear()
|
||||
a.Draw()
|
||||
if screen == nil {
|
||||
// We have no screen. Let's stop.
|
||||
a.QueueEvent(nil)
|
||||
break
|
||||
}
|
||||
|
||||
// Wait for next event and queue it.
|
||||
event := screen.PollEvent()
|
||||
if event != nil {
|
||||
// Regular event. Queue.
|
||||
a.QueueEvent(event)
|
||||
continue
|
||||
}
|
||||
|
||||
// A screen was finalized (event is nil). Wait for a new scren.
|
||||
screen = <-a.screenReplacement
|
||||
if screen == nil {
|
||||
// No new screen. We're done.
|
||||
a.QueueEvent(nil)
|
||||
return
|
||||
}
|
||||
|
||||
// We have a new screen. Keep going.
|
||||
a.Lock()
|
||||
a.screen = screen
|
||||
a.Unlock()
|
||||
|
||||
// Initialize and draw this screen.
|
||||
if err := screen.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
a.draw()
|
||||
}
|
||||
}()
|
||||
|
||||
// Start event loop.
|
||||
EventLoop:
|
||||
for {
|
||||
select {
|
||||
case event := <-a.events:
|
||||
if event == nil {
|
||||
break EventLoop
|
||||
}
|
||||
|
||||
switch event := event.(type) {
|
||||
case *tcell.EventKey:
|
||||
a.RLock()
|
||||
p := a.focus
|
||||
inputCapture := a.inputCapture
|
||||
a.RUnlock()
|
||||
|
||||
// Intercept keys.
|
||||
if inputCapture != nil {
|
||||
event = inputCapture(event)
|
||||
if event == nil {
|
||||
a.draw()
|
||||
continue // Don't forward event.
|
||||
}
|
||||
}
|
||||
|
||||
// Ctrl-C closes the application.
|
||||
if event.Key() == tcell.KeyCtrlC {
|
||||
a.Stop()
|
||||
}
|
||||
|
||||
// Pass other key events to the currently focused primitive.
|
||||
if p != nil {
|
||||
if handler := p.InputHandler(); handler != nil {
|
||||
handler(event, func(p Primitive) {
|
||||
a.SetFocus(p)
|
||||
})
|
||||
a.draw()
|
||||
}
|
||||
}
|
||||
case *tcell.EventResize:
|
||||
a.RLock()
|
||||
screen := a.screen
|
||||
a.RUnlock()
|
||||
if screen == nil {
|
||||
continue
|
||||
}
|
||||
screen.Clear()
|
||||
a.draw()
|
||||
}
|
||||
|
||||
// If we have updates, now is the time to execute them.
|
||||
case updater := <-a.updates:
|
||||
updater()
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the event loop to finish.
|
||||
wg.Wait()
|
||||
a.screen = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -200,12 +265,13 @@ func (a *Application) Run() error {
|
||||
func (a *Application) Stop() {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
if a.screen == nil {
|
||||
screen := a.screen
|
||||
if screen == nil {
|
||||
return
|
||||
}
|
||||
a.screen.Fini()
|
||||
a.screen = nil
|
||||
a.running = false
|
||||
screen.Fini()
|
||||
a.screenReplacement <- nil
|
||||
}
|
||||
|
||||
// Suspend temporarily suspends the application by exiting terminal UI mode and
|
||||
@@ -217,53 +283,54 @@ func (a *Application) Stop() {
|
||||
// terminal UI mode was not exited, and "f" was not called.
|
||||
func (a *Application) Suspend(f func()) bool {
|
||||
a.RLock()
|
||||
|
||||
if a.screen == nil {
|
||||
// Screen has not yet been initialized.
|
||||
a.RUnlock()
|
||||
return false
|
||||
screen := a.screen
|
||||
a.RUnlock()
|
||||
if screen == nil {
|
||||
return false // Screen has not yet been initialized.
|
||||
}
|
||||
|
||||
// Enter suspended mode.
|
||||
a.suspendMutex.Lock()
|
||||
defer a.suspendMutex.Unlock()
|
||||
a.RUnlock()
|
||||
a.Stop()
|
||||
|
||||
// Deal with panics during suspended mode. Exit the program.
|
||||
defer func() {
|
||||
if p := recover(); p != nil {
|
||||
fmt.Println(p)
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
screen.Fini()
|
||||
|
||||
// Wait for "f" to return.
|
||||
f()
|
||||
|
||||
// Make a new screen and redraw.
|
||||
a.Lock()
|
||||
// Make a new screen.
|
||||
var err error
|
||||
a.screen, err = tcell.NewScreen()
|
||||
screen, err = tcell.NewScreen()
|
||||
if err != nil {
|
||||
a.Unlock()
|
||||
panic(err)
|
||||
}
|
||||
if err = a.screen.Init(); err != nil {
|
||||
a.Unlock()
|
||||
panic(err)
|
||||
}
|
||||
a.running = true
|
||||
a.Unlock()
|
||||
a.Draw()
|
||||
a.screenReplacement <- screen
|
||||
// One key event will get lost, see https://github.com/gdamore/tcell/issues/194
|
||||
|
||||
// Continue application loop.
|
||||
return true
|
||||
}
|
||||
|
||||
// Draw refreshes the screen. It calls the Draw() function of the application's
|
||||
// root primitive and then syncs the screen buffer.
|
||||
// Draw refreshes the screen (during the next update cycle). It calls the Draw()
|
||||
// function of the application's root primitive and then syncs the screen
|
||||
// buffer.
|
||||
func (a *Application) Draw() *Application {
|
||||
a.QueueUpdate(func() {
|
||||
a.draw()
|
||||
})
|
||||
return a
|
||||
}
|
||||
|
||||
// ForceDraw refreshes the screen immediately. Use this function with caution as
|
||||
// it may lead to race conditions with updates to primitives in other
|
||||
// goroutines. It is always preferrable to use Draw() instead. Never call this
|
||||
// function from a goroutine.
|
||||
//
|
||||
// It is safe to call this function during queued updates and direct event
|
||||
// handling.
|
||||
func (a *Application) ForceDraw() *Application {
|
||||
return a.draw()
|
||||
}
|
||||
|
||||
// draw actually does what Draw() promises to do.
|
||||
func (a *Application) draw() *Application {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
@@ -404,3 +471,35 @@ func (a *Application) GetFocus() Primitive {
|
||||
defer a.RUnlock()
|
||||
return a.focus
|
||||
}
|
||||
|
||||
// QueueUpdate is used to synchronize access to primitives from non-main
|
||||
// goroutines. The provided function will be executed as part of the event loop
|
||||
// and thus will not cause race conditions with other such update functions or
|
||||
// the Draw() function.
|
||||
//
|
||||
// Note that Draw() is not implicitly called after the execution of f as that
|
||||
// may not be desirable. You can call Draw() from f if the screen should be
|
||||
// refreshed after each update. Alternatively, use QueueUpdateDraw() to follow
|
||||
// up with an immediate refresh of the screen.
|
||||
func (a *Application) QueueUpdate(f func()) *Application {
|
||||
a.updates <- f
|
||||
return a
|
||||
}
|
||||
|
||||
// QueueUpdateDraw works like QueueUpdate() except it refreshes the screen
|
||||
// immediately after executing f.
|
||||
func (a *Application) QueueUpdateDraw(f func()) *Application {
|
||||
a.QueueUpdate(func() {
|
||||
f()
|
||||
a.draw()
|
||||
})
|
||||
return a
|
||||
}
|
||||
|
||||
// QueueEvent sends an event to the Application event loop.
|
||||
//
|
||||
// It is not recommended for event to be nil.
|
||||
func (a *Application) QueueEvent(event tcell.Event) *Application {
|
||||
a.events <- event
|
||||
return a
|
||||
}
|
||||
|
||||
13
vendor/github.com/rivo/tview/box.go
generated
vendored
13
vendor/github.com/rivo/tview/box.go
generated
vendored
@@ -106,7 +106,11 @@ func (b *Box) GetInnerRect() (int, int, int, int) {
|
||||
height - b.paddingTop - b.paddingBottom
|
||||
}
|
||||
|
||||
// SetRect sets a new position of the primitive.
|
||||
// SetRect sets a new position of the primitive. Note that this has no effect
|
||||
// if this primitive is part of a layout (e.g. Flex, Grid) or if it was added
|
||||
// like this:
|
||||
//
|
||||
// application.SetRoot(b, true)
|
||||
func (b *Box) SetRect(x, y, width, height int) {
|
||||
b.x = x
|
||||
b.y = y
|
||||
@@ -162,6 +166,13 @@ func (b *Box) InputHandler() func(event *tcell.EventKey, setFocus func(p Primiti
|
||||
// be called.
|
||||
//
|
||||
// Providing a nil handler will remove a previously existing handler.
|
||||
//
|
||||
// Note that this function will not have an effect on primitives composed of
|
||||
// other primitives, such as Form, Flex, or Grid. Key events are only captured
|
||||
// by the primitives that have focus (e.g. InputField) and only one primitive
|
||||
// can have focus at a time. Composing primitives such as Form pass the focus on
|
||||
// to their contained primitives and thus never receive any key events
|
||||
// themselves. Therefore, they cannot intercept key events.
|
||||
func (b *Box) SetInputCapture(capture func(event *tcell.EventKey) *tcell.EventKey) *Box {
|
||||
b.inputCapture = capture
|
||||
return b
|
||||
|
||||
27
vendor/github.com/rivo/tview/doc.go
generated
vendored
27
vendor/github.com/rivo/tview/doc.go
generated
vendored
@@ -21,6 +21,7 @@ The package implements the following widgets:
|
||||
- Form: Forms composed of input fields, drop down selections, checkboxes, and
|
||||
buttons.
|
||||
- Modal: A centered window with a text message and one or more buttons.
|
||||
- Grid: A grid based layout manager.
|
||||
- Flex: A Flexbox based layout manager.
|
||||
- Pages: A page based layout manager.
|
||||
|
||||
@@ -137,6 +138,32 @@ Unicode Support
|
||||
|
||||
This package supports unicode characters including wide characters.
|
||||
|
||||
Concurrency
|
||||
|
||||
Many functions in this package are not thread-safe. For many applications, this
|
||||
may not be an issue: If your code makes changes in response to key events, it
|
||||
will execute in the main goroutine and thus will not cause any race conditions.
|
||||
|
||||
If you access your primitives from other goroutines, however, you will need to
|
||||
synchronize execution. The easiest way to do this is to call
|
||||
Application.QueueUpdate() or Application.QueueUpdateDraw() (see the function
|
||||
documentation for details):
|
||||
|
||||
go func() {
|
||||
app.QueueUpdateDraw(func() {
|
||||
table.SetCellSimple(0, 0, "Foo bar")
|
||||
})
|
||||
}()
|
||||
|
||||
One exception to this is the io.Writer interface implemented by TextView. You
|
||||
can safely write to a TextView from any goroutine. See the TextView
|
||||
documentation for details.
|
||||
|
||||
You can also call Application.Draw() from any goroutine without having to wrap
|
||||
it in QueueUpdate(). And, as mentioned above, key event callbacks are executed
|
||||
in the main goroutine and thus should not use QueueUpdate() as that may lead to
|
||||
deadlocks.
|
||||
|
||||
Type Hierarchy
|
||||
|
||||
All widgets listed above contain the Box type. All of Box's functions are
|
||||
|
||||
5
vendor/github.com/rivo/tview/form.go
generated
vendored
5
vendor/github.com/rivo/tview/form.go
generated
vendored
@@ -507,8 +507,10 @@ func (f *Form) Draw(screen tcell.Screen) {
|
||||
// Focus is called by the application when the primitive receives focus.
|
||||
func (f *Form) Focus(delegate func(p Primitive)) {
|
||||
if len(f.items)+len(f.buttons) == 0 {
|
||||
f.hasFocus = true
|
||||
return
|
||||
}
|
||||
f.hasFocus = false
|
||||
|
||||
// Hand on the focus to one of our child elements.
|
||||
if f.focusedElement < 0 || f.focusedElement >= len(f.items)+len(f.buttons) {
|
||||
@@ -550,6 +552,9 @@ func (f *Form) Focus(delegate func(p Primitive)) {
|
||||
|
||||
// HasFocus returns whether or not this primitive has focus.
|
||||
func (f *Form) HasFocus() bool {
|
||||
if f.hasFocus {
|
||||
return true
|
||||
}
|
||||
for _, item := range f.items {
|
||||
if item.GetFocusable().HasFocus() {
|
||||
return true
|
||||
|
||||
43
vendor/github.com/rivo/tview/grid.go
generated
vendored
43
vendor/github.com/rivo/tview/grid.go
generated
vendored
@@ -307,6 +307,7 @@ func (g *Grid) InputHandler() func(event *tcell.EventKey, setFocus func(p Primit
|
||||
func (g *Grid) Draw(screen tcell.Screen) {
|
||||
g.Box.Draw(screen)
|
||||
x, y, width, height := g.GetInnerRect()
|
||||
screenWidth, screenHeight := screen.Size()
|
||||
|
||||
// Make a list of items which apply.
|
||||
items := make(map[Primitive]*gridItem)
|
||||
@@ -555,10 +556,10 @@ func (g *Grid) Draw(screen tcell.Screen) {
|
||||
}
|
||||
item.x -= offsetX
|
||||
item.y -= offsetY
|
||||
if item.x+item.w > width {
|
||||
if item.x+item.w > x+width {
|
||||
item.w = width - item.x
|
||||
}
|
||||
if item.y+item.h > height {
|
||||
if item.y+item.h > y+height {
|
||||
item.h = height - item.y
|
||||
}
|
||||
if item.x < 0 {
|
||||
@@ -573,7 +574,7 @@ func (g *Grid) Draw(screen tcell.Screen) {
|
||||
item.visible = false
|
||||
continue
|
||||
}
|
||||
primitive.SetRect(x+item.x, y+item.y, item.w, item.h)
|
||||
primitive.SetRect(item.x, item.y, item.w, item.h)
|
||||
|
||||
// Draw primitive.
|
||||
if item == focus {
|
||||
@@ -585,46 +586,46 @@ func (g *Grid) Draw(screen tcell.Screen) {
|
||||
// Draw border around primitive.
|
||||
if g.borders {
|
||||
for bx := item.x; bx < item.x+item.w; bx++ { // Top/bottom lines.
|
||||
if bx < 0 || bx >= width {
|
||||
if bx < 0 || bx >= screenWidth {
|
||||
continue
|
||||
}
|
||||
by := item.y - 1
|
||||
if by >= 0 && by < height {
|
||||
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.Horizontal, g.bordersColor)
|
||||
if by >= 0 && by < screenHeight {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.Horizontal, g.bordersColor)
|
||||
}
|
||||
by = item.y + item.h
|
||||
if by >= 0 && by < height {
|
||||
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.Horizontal, g.bordersColor)
|
||||
if by >= 0 && by < screenHeight {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.Horizontal, g.bordersColor)
|
||||
}
|
||||
}
|
||||
for by := item.y; by < item.y+item.h; by++ { // Left/right lines.
|
||||
if by < 0 || by >= height {
|
||||
if by < 0 || by >= screenHeight {
|
||||
continue
|
||||
}
|
||||
bx := item.x - 1
|
||||
if bx >= 0 && bx < width {
|
||||
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.Vertical, g.bordersColor)
|
||||
if bx >= 0 && bx < screenWidth {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.Vertical, g.bordersColor)
|
||||
}
|
||||
bx = item.x + item.w
|
||||
if bx >= 0 && bx < width {
|
||||
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.Vertical, g.bordersColor)
|
||||
if bx >= 0 && bx < screenWidth {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.Vertical, g.bordersColor)
|
||||
}
|
||||
}
|
||||
bx, by := item.x-1, item.y-1 // Top-left corner.
|
||||
if bx >= 0 && bx < width && by >= 0 && by < height {
|
||||
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.TopLeft, g.bordersColor)
|
||||
if bx >= 0 && bx < screenWidth && by >= 0 && by < screenHeight {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.TopLeft, g.bordersColor)
|
||||
}
|
||||
bx, by = item.x+item.w, item.y-1 // Top-right corner.
|
||||
if bx >= 0 && bx < width && by >= 0 && by < height {
|
||||
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.TopRight, g.bordersColor)
|
||||
if bx >= 0 && bx < screenWidth && by >= 0 && by < screenHeight {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.TopRight, g.bordersColor)
|
||||
}
|
||||
bx, by = item.x-1, item.y+item.h // Bottom-left corner.
|
||||
if bx >= 0 && bx < width && by >= 0 && by < height {
|
||||
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.BottomLeft, g.bordersColor)
|
||||
if bx >= 0 && bx < screenWidth && by >= 0 && by < screenHeight {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.BottomLeft, g.bordersColor)
|
||||
}
|
||||
bx, by = item.x+item.w, item.y+item.h // Bottom-right corner.
|
||||
if bx >= 0 && bx < width && by >= 0 && by < height {
|
||||
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.BottomRight, g.bordersColor)
|
||||
if bx >= 0 && bx < screenWidth && by >= 0 && by < screenHeight {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.BottomRight, g.bordersColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
31
vendor/github.com/rivo/tview/inputfield.go
generated
vendored
31
vendor/github.com/rivo/tview/inputfield.go
generated
vendored
@@ -102,6 +102,7 @@ func NewInputField() *InputField {
|
||||
// SetText sets the current text of the input field.
|
||||
func (i *InputField) SetText(text string) *InputField {
|
||||
i.text = text
|
||||
i.cursorPos = len(text)
|
||||
if i.changed != nil {
|
||||
i.changed(text)
|
||||
}
|
||||
@@ -359,21 +360,22 @@ func (i *InputField) InputHandler() func(event *tcell.EventKey, setFocus func(p
|
||||
i.cursorPos = len(i.text) - len(regexp.MustCompile(`^\s*\S+\s*`).ReplaceAllString(i.text[i.cursorPos:], ""))
|
||||
}
|
||||
|
||||
// Add character function. Returns whether or not the rune character is
|
||||
// accepted.
|
||||
add := func(r rune) bool {
|
||||
newText := i.text[:i.cursorPos] + string(r) + i.text[i.cursorPos:]
|
||||
if i.accept != nil && !i.accept(newText, r) {
|
||||
return false
|
||||
}
|
||||
i.text = newText
|
||||
i.cursorPos += len(string(r))
|
||||
return true
|
||||
}
|
||||
|
||||
// Process key event.
|
||||
switch key := event.Key(); key {
|
||||
case tcell.KeyRune: // Regular character.
|
||||
modifiers := event.Modifiers()
|
||||
if modifiers == tcell.ModNone {
|
||||
ch := string(event.Rune())
|
||||
newText := i.text[:i.cursorPos] + ch + i.text[i.cursorPos:]
|
||||
if i.accept != nil {
|
||||
if !i.accept(newText, event.Rune()) {
|
||||
break
|
||||
}
|
||||
}
|
||||
i.text = newText
|
||||
i.cursorPos += len(ch)
|
||||
} else if modifiers&tcell.ModAlt > 0 {
|
||||
if event.Modifiers()&tcell.ModAlt > 0 {
|
||||
// We accept some Alt- key combinations.
|
||||
switch event.Rune() {
|
||||
case 'a': // Home.
|
||||
@@ -385,6 +387,11 @@ func (i *InputField) InputHandler() func(event *tcell.EventKey, setFocus func(p
|
||||
case 'f': // Move word right.
|
||||
moveWordRight()
|
||||
}
|
||||
} else {
|
||||
// Other keys are simply accepted as regular characters.
|
||||
if !add(event.Rune()) {
|
||||
break
|
||||
}
|
||||
}
|
||||
case tcell.KeyCtrlU: // Delete all.
|
||||
i.text = ""
|
||||
|
||||
13
vendor/github.com/rivo/tview/list.go
generated
vendored
13
vendor/github.com/rivo/tview/list.go
generated
vendored
@@ -44,6 +44,9 @@ type List struct {
|
||||
// The background color for selected items.
|
||||
selectedBackgroundColor tcell.Color
|
||||
|
||||
// If true, the selection is only shown when the list has focus.
|
||||
selectedFocusOnly bool
|
||||
|
||||
// An optional function which is called when the user has navigated to a list
|
||||
// item.
|
||||
changed func(index int, mainText, secondaryText string, shortcut rune)
|
||||
@@ -128,6 +131,14 @@ func (l *List) SetSelectedBackgroundColor(color tcell.Color) *List {
|
||||
return l
|
||||
}
|
||||
|
||||
// SetSelectedFocusOnly sets a flag which determines when the currently selected
|
||||
// list item is highlighted. If set to true, selected items are only highlighted
|
||||
// when the list has focus. If set to false, they are always highlighted.
|
||||
func (l *List) SetSelectedFocusOnly(focusOnly bool) *List {
|
||||
l.selectedFocusOnly = focusOnly
|
||||
return l
|
||||
}
|
||||
|
||||
// ShowSecondaryText determines whether or not to show secondary item texts.
|
||||
func (l *List) ShowSecondaryText(show bool) *List {
|
||||
l.showSecondaryText = show
|
||||
@@ -263,7 +274,7 @@ func (l *List) Draw(screen tcell.Screen) {
|
||||
Print(screen, item.MainText, x, y, width, AlignLeft, l.mainTextColor)
|
||||
|
||||
// Background color of selected text.
|
||||
if index == l.currentItem {
|
||||
if index == l.currentItem && (!l.selectedFocusOnly || l.HasFocus()) {
|
||||
textWidth := StringWidth(item.MainText)
|
||||
for bx := 0; bx < textWidth && bx < width; bx++ {
|
||||
m, c, style, _ := screen.GetContent(x+bx, y)
|
||||
|
||||
29
vendor/github.com/rivo/tview/table.go
generated
vendored
29
vendor/github.com/rivo/tview/table.go
generated
vendored
@@ -389,7 +389,7 @@ func (t *Table) SetDoneFunc(handler func(key tcell.Key)) *Table {
|
||||
}
|
||||
|
||||
// SetCell sets the content of a cell the specified position. It is ok to
|
||||
// directly instantiate a TableCell object. If the cell has contain, at least
|
||||
// directly instantiate a TableCell object. If the cell has content, at least
|
||||
// the Text and Color fields should be set.
|
||||
//
|
||||
// Note that setting cells in previously unknown rows and columns will
|
||||
@@ -422,7 +422,7 @@ func (t *Table) SetCellSimple(row, column int, text string) *Table {
|
||||
}
|
||||
|
||||
// GetCell returns the contents of the cell at the specified position. A valid
|
||||
// TableCell object is always returns but it will be uninitialized if the cell
|
||||
// TableCell object is always returned but it will be uninitialized if the cell
|
||||
// was not previously set.
|
||||
func (t *Table) GetCell(row, column int) *TableCell {
|
||||
if row >= len(t.cells) || column >= len(t.cells[row]) {
|
||||
@@ -431,6 +431,31 @@ func (t *Table) GetCell(row, column int) *TableCell {
|
||||
return t.cells[row][column]
|
||||
}
|
||||
|
||||
// RemoveRow removes the row at the given position from the table. If there is
|
||||
// no such row, this has no effect.
|
||||
func (t *Table) RemoveRow(row int) *Table {
|
||||
if row < 0 || row >= len(t.cells) {
|
||||
return t
|
||||
}
|
||||
|
||||
t.cells = append(t.cells[:row], t.cells[row+1:]...)
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// RemoveColumn removes the column at the given position from the table. If
|
||||
// there is no such column, this has no effect.
|
||||
func (t *Table) RemoveColumn(column int) *Table {
|
||||
for row := range t.cells {
|
||||
if column < 0 || column >= len(t.cells[row]) {
|
||||
continue
|
||||
}
|
||||
t.cells[row] = append(t.cells[row][:column], t.cells[row][column+1:]...)
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// GetRowCount returns the number of rows in the table.
|
||||
func (t *Table) GetRowCount() int {
|
||||
return len(t.cells)
|
||||
|
||||
71
vendor/github.com/rivo/tview/textview.go
generated
vendored
71
vendor/github.com/rivo/tview/textview.go
generated
vendored
@@ -31,7 +31,7 @@ type textViewIndex struct {
|
||||
// TextView is a box which displays text. It implements the io.Writer interface
|
||||
// so you can stream text to it. This does not trigger a redraw automatically
|
||||
// but if a handler is installed via SetChangedFunc(), you can cause it to be
|
||||
// redrawn.
|
||||
// redrawn. (See SetChangedFunc() for more details.)
|
||||
//
|
||||
// Navigation
|
||||
//
|
||||
@@ -260,8 +260,20 @@ func (t *TextView) SetRegions(regions bool) *TextView {
|
||||
}
|
||||
|
||||
// SetChangedFunc sets a handler function which is called when the text of the
|
||||
// text view has changed. This is typically used to cause the application to
|
||||
// redraw the screen.
|
||||
// text view has changed. This is useful when text is written to this io.Writer
|
||||
// in a separate goroutine. This does not automatically cause the screen to be
|
||||
// refreshed so you may want to use the "changed" handler to redraw the screen.
|
||||
//
|
||||
// Note that to avoid race conditions or deadlocks, there are a few rules you
|
||||
// should follow:
|
||||
//
|
||||
// - You can call Application.Draw() from this handler.
|
||||
// - You can call TextView.HasFocus() from this handler.
|
||||
// - During the execution of this handler, access to any other variables from
|
||||
// this primitive or any other primitive should be queued using
|
||||
// Application.QueueUpdate().
|
||||
//
|
||||
// See package description for details on dealing with concurrency.
|
||||
func (t *TextView) SetChangedFunc(handler func()) *TextView {
|
||||
t.changed = handler
|
||||
return t
|
||||
@@ -441,13 +453,33 @@ func (t *TextView) GetRegionText(regionID string) string {
|
||||
return escapePattern.ReplaceAllString(buffer.String(), `[$1$2]`)
|
||||
}
|
||||
|
||||
// Focus is called when this primitive receives focus.
|
||||
func (t *TextView) Focus(delegate func(p Primitive)) {
|
||||
// Implemented here with locking because this is used by layout primitives.
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
t.hasFocus = true
|
||||
}
|
||||
|
||||
// HasFocus returns whether or not this primitive has focus.
|
||||
func (t *TextView) HasFocus() bool {
|
||||
// Implemented here with locking because this may be used in the "changed"
|
||||
// callback.
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
return t.hasFocus
|
||||
}
|
||||
|
||||
// Write lets us implement the io.Writer interface. Tab characters will be
|
||||
// replaced with TabSize space characters. A "\n" or "\r\n" will be interpreted
|
||||
// as a new line.
|
||||
func (t *TextView) Write(p []byte) (n int, err error) {
|
||||
// Notify at the end.
|
||||
if t.changed != nil {
|
||||
defer t.changed()
|
||||
t.Lock()
|
||||
changed := t.changed
|
||||
t.Unlock()
|
||||
if changed != nil {
|
||||
defer changed() // Deadlocks may occur if we lock here.
|
||||
}
|
||||
|
||||
t.Lock()
|
||||
@@ -840,18 +872,21 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
||||
// Print the line.
|
||||
var colorPos, regionPos, escapePos, tagOffset, skipped int
|
||||
iterateString(strippedText, func(main rune, comb []rune, textPos, textWidth, screenPos, screenWidth int) bool {
|
||||
// Get the color.
|
||||
if colorPos < len(colorTags) && textPos+tagOffset >= colorTagIndices[colorPos][0] && textPos+tagOffset < colorTagIndices[colorPos][1] {
|
||||
foregroundColor, backgroundColor, attributes = styleFromTag(foregroundColor, backgroundColor, attributes, colorTags[colorPos])
|
||||
tagOffset += colorTagIndices[colorPos][1] - colorTagIndices[colorPos][0]
|
||||
colorPos++
|
||||
}
|
||||
|
||||
// Get the region.
|
||||
if regionPos < len(regionIndices) && textPos+tagOffset >= regionIndices[regionPos][0] && textPos+tagOffset < regionIndices[regionPos][1] {
|
||||
regionID = regions[regionPos][1]
|
||||
tagOffset += regionIndices[regionPos][1] - regionIndices[regionPos][0]
|
||||
regionPos++
|
||||
// Process tags.
|
||||
for {
|
||||
if colorPos < len(colorTags) && textPos+tagOffset >= colorTagIndices[colorPos][0] && textPos+tagOffset < colorTagIndices[colorPos][1] {
|
||||
// Get the color.
|
||||
foregroundColor, backgroundColor, attributes = styleFromTag(foregroundColor, backgroundColor, attributes, colorTags[colorPos])
|
||||
tagOffset += colorTagIndices[colorPos][1] - colorTagIndices[colorPos][0]
|
||||
colorPos++
|
||||
} else if regionPos < len(regionIndices) && textPos+tagOffset >= regionIndices[regionPos][0] && textPos+tagOffset < regionIndices[regionPos][1] {
|
||||
// Get the region.
|
||||
regionID = regions[regionPos][1]
|
||||
tagOffset += regionIndices[regionPos][1] - regionIndices[regionPos][0]
|
||||
regionPos++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Skip the second-to-last character of an escape tag.
|
||||
@@ -894,7 +929,7 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
||||
}
|
||||
|
||||
// Stop at the right border.
|
||||
if posX+screenWidth >= width {
|
||||
if posX+screenWidth > width {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/rivo/tview/treeview.go
generated
vendored
2
vendor/github.com/rivo/tview/treeview.go
generated
vendored
@@ -569,7 +569,7 @@ func (t *TreeView) Draw(screen tcell.Screen) {
|
||||
|
||||
// Draw the tree.
|
||||
posY := y
|
||||
lineStyle := tcell.StyleDefault.Foreground(t.graphicsColor)
|
||||
lineStyle := tcell.StyleDefault.Background(t.backgroundColor).Foreground(t.graphicsColor)
|
||||
for index, node := range t.nodes {
|
||||
// Skip invisible parts.
|
||||
if posY >= y+height+1 {
|
||||
|
||||
5
vendor/github.com/rivo/tview/util.go
generated
vendored
5
vendor/github.com/rivo/tview/util.go
generated
vendored
@@ -51,6 +51,9 @@ var (
|
||||
|
||||
// Package initialization.
|
||||
func init() {
|
||||
// We'll use zero width joiners.
|
||||
runewidth.ZeroWidthJoiner = true
|
||||
|
||||
// Initialize the predefined input field handlers.
|
||||
InputFieldInteger = func(text string, ch rune) bool {
|
||||
if text == "-" {
|
||||
@@ -513,7 +516,7 @@ func iterateString(text string, callback func(main rune, comb []rune, textPos, t
|
||||
}
|
||||
|
||||
for index, r := range text {
|
||||
if unicode.In(r, unicode.Lm, unicode.M) || r == '\u200d' {
|
||||
if unicode.In(r, unicode.M) || r == '\u200d' {
|
||||
lastZeroWidthJoiner = r == '\u200d'
|
||||
} else {
|
||||
// We have a rune that's not a modifier. It could be the beginning of a
|
||||
|
||||
Reference in New Issue
Block a user