mirror of
https://github.com/rivo/tview.git
synced 2025-04-24 13:48:56 +08:00
Enabled bracketed pasting.
This commit is contained in:
parent
007cbb1d13
commit
c9421b4bd9
@ -1,6 +1,7 @@
|
||||
package tview
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -83,6 +84,9 @@ type Application struct {
|
||||
// Set to true if mouse events are enabled.
|
||||
enableMouse bool
|
||||
|
||||
// Set to true if paste events are enabled.
|
||||
enablePaste bool
|
||||
|
||||
// An optional capture function which receives a key event and returns the
|
||||
// event to be forwarded to the default input handler (nil if nothing should
|
||||
// be forwarded).
|
||||
@ -145,6 +149,9 @@ func NewApplication() *Application {
|
||||
// forward the Ctrl-C event to primitives down the hierarchy, return a new
|
||||
// key event with the same key and modifiers, e.g.
|
||||
// tcell.NewEventKey(tcell.KeyCtrlC, 0, tcell.ModNone).
|
||||
//
|
||||
// Pasted key events are not forwarded to the input capture function if pasting
|
||||
// is enabled (see [Application.EnablePaste]).
|
||||
func (a *Application) SetInputCapture(capture func(event *tcell.EventKey) *tcell.EventKey) *Application {
|
||||
a.inputCapture = capture
|
||||
return a
|
||||
@ -216,6 +223,26 @@ func (a *Application) EnableMouse(enable bool) *Application {
|
||||
return a
|
||||
}
|
||||
|
||||
// EnablePaste enables the capturing of paste events or disables them (if
|
||||
// "false" is provided). This must be supported by the terminal.
|
||||
//
|
||||
// Widgets won't interpret paste events for navigation or selection purposes.
|
||||
// Paste events are typically only used to insert a block of text into an
|
||||
// [InputField] or a [TextArea].
|
||||
func (a *Application) EnablePaste(enable bool) *Application {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
if enable != a.enablePaste && a.screen != nil {
|
||||
if enable {
|
||||
a.screen.EnablePaste()
|
||||
} else {
|
||||
a.screen.DisablePaste()
|
||||
}
|
||||
}
|
||||
a.enablePaste = enable
|
||||
return a
|
||||
}
|
||||
|
||||
// Run starts the application and thus the event loop. This function returns
|
||||
// when Stop() was called.
|
||||
func (a *Application) Run() error {
|
||||
@ -239,6 +266,13 @@ func (a *Application) Run() error {
|
||||
}
|
||||
if a.enableMouse {
|
||||
a.screen.EnableMouse()
|
||||
} else {
|
||||
a.screen.DisableMouse()
|
||||
}
|
||||
if a.enablePaste {
|
||||
a.screen.EnablePaste()
|
||||
} else {
|
||||
a.screen.DisablePaste()
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,7 +317,7 @@ func (a *Application) Run() error {
|
||||
screen = <-a.screenReplacement
|
||||
if screen == nil {
|
||||
// No new screen. We're done.
|
||||
a.QueueEvent(nil)
|
||||
a.QueueEvent(nil) // Stop the event loop.
|
||||
return
|
||||
}
|
||||
|
||||
@ -291,6 +325,7 @@ func (a *Application) Run() error {
|
||||
a.Lock()
|
||||
a.screen = screen
|
||||
enableMouse := a.enableMouse
|
||||
enablePaste := a.enablePaste
|
||||
a.Unlock()
|
||||
|
||||
// Initialize and draw this screen.
|
||||
@ -299,15 +334,27 @@ func (a *Application) Run() error {
|
||||
}
|
||||
if enableMouse {
|
||||
screen.EnableMouse()
|
||||
} else {
|
||||
screen.DisableMouse()
|
||||
}
|
||||
if enablePaste {
|
||||
screen.EnablePaste()
|
||||
} else {
|
||||
screen.DisablePaste()
|
||||
}
|
||||
a.draw()
|
||||
}
|
||||
}()
|
||||
|
||||
// Start event loop.
|
||||
var (
|
||||
pasteBuffer strings.Builder
|
||||
pasting bool // Set to true while we receive paste key events.
|
||||
)
|
||||
EventLoop:
|
||||
for {
|
||||
select {
|
||||
// If we received an event, handle it.
|
||||
case event := <-a.events:
|
||||
if event == nil {
|
||||
break EventLoop
|
||||
@ -315,6 +362,19 @@ EventLoop:
|
||||
|
||||
switch event := event.(type) {
|
||||
case *tcell.EventKey:
|
||||
// If we are pasting, collect runes, nothing else.
|
||||
if pasting {
|
||||
switch event.Key() {
|
||||
case tcell.KeyRune:
|
||||
pasteBuffer.WriteRune(event.Rune())
|
||||
case tcell.KeyEnter:
|
||||
pasteBuffer.WriteRune('\n')
|
||||
case tcell.KeyTab:
|
||||
pasteBuffer.WriteRune('\t')
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
a.RLock()
|
||||
root := a.root
|
||||
inputCapture := a.inputCapture
|
||||
@ -327,7 +387,7 @@ EventLoop:
|
||||
event = inputCapture(event)
|
||||
if event == nil {
|
||||
a.draw()
|
||||
continue // Don't forward event.
|
||||
break // Don't forward event.
|
||||
}
|
||||
draw = true
|
||||
}
|
||||
@ -352,6 +412,30 @@ EventLoop:
|
||||
if draw {
|
||||
a.draw()
|
||||
}
|
||||
case *tcell.EventPaste:
|
||||
if !a.enablePaste {
|
||||
break
|
||||
}
|
||||
if event.Start() {
|
||||
pasting = true
|
||||
pasteBuffer.Reset()
|
||||
} else if event.End() {
|
||||
pasting = false
|
||||
a.RLock()
|
||||
root := a.root
|
||||
a.RUnlock()
|
||||
if root != nil && root.HasFocus() && pasteBuffer.Len() > 0 {
|
||||
// Pass paste event to the root primitive.
|
||||
if handler := root.PasteHandler(); handler != nil {
|
||||
handler(pasteBuffer.String(), func(p Primitive) {
|
||||
a.SetFocus(p)
|
||||
})
|
||||
}
|
||||
|
||||
// Redraw.
|
||||
a.draw()
|
||||
}
|
||||
}
|
||||
case *tcell.EventResize:
|
||||
if time.Since(lastRedraw) < redrawPause {
|
||||
if redrawTimer != nil {
|
||||
@ -365,7 +449,7 @@ EventLoop:
|
||||
screen := a.screen
|
||||
a.RUnlock()
|
||||
if screen == nil {
|
||||
continue
|
||||
break
|
||||
}
|
||||
lastRedraw = time.Now()
|
||||
screen.Clear()
|
||||
|
29
box.go
29
box.go
@ -153,8 +153,8 @@ func (b *Box) GetDrawFunc() func(screen tcell.Screen, x, y, width, height int) (
|
||||
return b.draw
|
||||
}
|
||||
|
||||
// WrapInputHandler wraps an input handler (see InputHandler()) with the
|
||||
// functionality to capture input (see SetInputCapture()) before passing it
|
||||
// WrapInputHandler wraps an input handler (see [Box.InputHandler]) with the
|
||||
// functionality to capture input (see [Box.SetInputCapture]) before passing it
|
||||
// on to the provided (default) input handler.
|
||||
//
|
||||
// This is only meant to be used by subclassing primitives.
|
||||
@ -169,11 +169,25 @@ func (b *Box) WrapInputHandler(inputHandler func(*tcell.EventKey, func(p Primiti
|
||||
}
|
||||
}
|
||||
|
||||
// InputHandler returns nil.
|
||||
// InputHandler returns nil. Box has no default input handling.
|
||||
func (b *Box) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
|
||||
return b.WrapInputHandler(nil)
|
||||
}
|
||||
|
||||
// WrapPasteHandler wraps a paste handler (see [Box.PasteHandler]).
|
||||
func (b *Box) WrapPasteHandler(pasteHandler func(string, func(p Primitive))) func(string, func(p Primitive)) {
|
||||
return func(text string, setFocus func(p Primitive)) {
|
||||
if pasteHandler != nil {
|
||||
pasteHandler(text, setFocus)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PasteHandler returns nil. Box has no default paste handling.
|
||||
func (b *Box) PasteHandler() func(pastedText string, setFocus func(p Primitive)) {
|
||||
return b.WrapPasteHandler(nil)
|
||||
}
|
||||
|
||||
// SetInputCapture installs a function which captures key events before they are
|
||||
// forwarded to the primitive's default key event handler. This function can
|
||||
// then choose to forward that key event (or a different one) to the default
|
||||
@ -184,6 +198,9 @@ func (b *Box) InputHandler() func(event *tcell.EventKey, setFocus func(p Primiti
|
||||
//
|
||||
// This function can also be used on container primitives (like Flex, Grid, or
|
||||
// Form) as keyboard events will be handed down until they are handled.
|
||||
//
|
||||
// Pasted key events are not forwarded to the input capture function if pasting
|
||||
// is enabled (see [Application.EnablePaste]).
|
||||
func (b *Box) SetInputCapture(capture func(event *tcell.EventKey) *tcell.EventKey) *Box {
|
||||
b.inputCapture = capture
|
||||
return b
|
||||
@ -195,8 +212,8 @@ func (b *Box) GetInputCapture() func(event *tcell.EventKey) *tcell.EventKey {
|
||||
return b.inputCapture
|
||||
}
|
||||
|
||||
// WrapMouseHandler wraps a mouse event handler (see MouseHandler()) with the
|
||||
// functionality to capture mouse events (see SetMouseCapture()) before passing
|
||||
// WrapMouseHandler wraps a mouse event handler (see [Box.MouseHandler]) with the
|
||||
// functionality to capture mouse events (see [Box.SetMouseCapture]) before passing
|
||||
// them on to the provided (default) event handler.
|
||||
//
|
||||
// This is only meant to be used by subclassing primitives.
|
||||
@ -212,7 +229,7 @@ func (b *Box) WrapMouseHandler(mouseHandler func(MouseAction, *tcell.EventMouse,
|
||||
}
|
||||
}
|
||||
|
||||
// MouseHandler returns nil.
|
||||
// MouseHandler returns nil. Box has no default mouse handling.
|
||||
func (b *Box) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
|
||||
return b.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
|
||||
if action == MouseLeftDown && b.InRect(event.Position()) {
|
||||
|
@ -20,7 +20,7 @@ func main() {
|
||||
app.Stop()
|
||||
})
|
||||
form.SetBorder(true).SetTitle("Enter some data").SetTitleAlign(tview.AlignLeft)
|
||||
if err := app.SetRoot(form, true).EnableMouse(true).Run(); err != nil {
|
||||
if err := app.SetRoot(form, true).EnableMouse(true).EnablePaste(true).Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ func main() {
|
||||
SetDoneFunc(func(key tcell.Key) {
|
||||
app.Stop()
|
||||
})
|
||||
if err := app.SetRoot(inputField, true).EnableMouse(true).Run(); err != nil {
|
||||
if err := app.SetRoot(inputField, true).EnableMouse(true).EnablePaste(true).Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
A presentation of the tview package, implemented with tview.
|
||||
|
||||
Navigation
|
||||
# Navigation
|
||||
|
||||
The presentation will advance to the next slide when the primitive demonstrated
|
||||
in the current slide is left (usually by hitting Enter or Escape). Additionally,
|
||||
@ -97,7 +97,7 @@ func main() {
|
||||
})
|
||||
|
||||
// Start the application.
|
||||
if err := app.SetRoot(layout, true).EnableMouse(true).Run(); err != nil {
|
||||
if err := app.SetRoot(layout, true).EnableMouse(true).EnablePaste(true).Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ func main() {
|
||||
updateInfos()
|
||||
|
||||
mainView := tview.NewGrid().
|
||||
SetRows(3, 0).
|
||||
SetRows(0, 1).
|
||||
AddItem(textArea, 0, 0, 1, 2, 0, 0, true).
|
||||
AddItem(helpInfo, 1, 0, 1, 1, 0, 0, false).
|
||||
AddItem(position, 1, 1, 1, 1, 0, 0, false)
|
||||
@ -128,8 +128,7 @@ Double-click to select a word.
|
||||
return event
|
||||
})
|
||||
|
||||
if err := app.SetRoot(pages,
|
||||
true).EnableMouse(true).Run(); err != nil {
|
||||
if err := app.SetRoot(pages, true).EnableMouse(true).EnablePaste(true).Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
14
flex.go
14
flex.go
@ -259,3 +259,17 @@ func (f *Flex) InputHandler() func(event *tcell.EventKey, setFocus func(p Primit
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// PasteHandler returns the handler for this primitive.
|
||||
func (f *Flex) PasteHandler() func(pastedText string, setFocus func(p Primitive)) {
|
||||
return f.WrapPasteHandler(func(pastedText string, setFocus func(p Primitive)) {
|
||||
for _, item := range f.items {
|
||||
if item.Item != nil && item.Item.HasFocus() {
|
||||
if handler := item.Item.PasteHandler(); handler != nil {
|
||||
handler(pastedText, setFocus)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
23
form.go
23
form.go
@ -867,3 +867,26 @@ func (f *Form) InputHandler() func(event *tcell.EventKey, setFocus func(p Primit
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// PasteHandler returns the handler for this primitive.
|
||||
func (f *Form) PasteHandler() func(pastedText string, setFocus func(p Primitive)) {
|
||||
return f.WrapPasteHandler(func(pastedText string, setFocus func(p Primitive)) {
|
||||
for _, item := range f.items {
|
||||
if item != nil && item.HasFocus() {
|
||||
if handler := item.PasteHandler(); handler != nil {
|
||||
handler(pastedText, setFocus)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, button := range f.buttons {
|
||||
if button.HasFocus() {
|
||||
if handler := button.PasteHandler(); handler != nil {
|
||||
handler(pastedText, setFocus)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
13
frame.go
13
frame.go
@ -220,3 +220,16 @@ func (f *Frame) InputHandler() func(event *tcell.EventKey, setFocus func(p Primi
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// PasteHandler returns the handler for this primitive.
|
||||
func (f *Frame) PasteHandler() func(pastedText string, setFocus func(p Primitive)) {
|
||||
return f.WrapPasteHandler(func(pastedText string, setFocus func(p Primitive)) {
|
||||
if f.primitive == nil {
|
||||
return
|
||||
}
|
||||
if handler := f.primitive.PasteHandler(); handler != nil {
|
||||
handler(pastedText, setFocus)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
112
grid.go
112
grid.go
@ -266,55 +266,6 @@ func (g *Grid) HasFocus() bool {
|
||||
return g.Box.HasFocus()
|
||||
}
|
||||
|
||||
// InputHandler returns the handler for this primitive.
|
||||
func (g *Grid) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
|
||||
return g.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) {
|
||||
if !g.hasFocus {
|
||||
// Pass event on to child primitive.
|
||||
for _, item := range g.items {
|
||||
if item != nil && item.Item.HasFocus() {
|
||||
if handler := item.Item.InputHandler(); handler != nil {
|
||||
handler(event, setFocus)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Process our own key events if we have direct focus.
|
||||
switch event.Key() {
|
||||
case tcell.KeyRune:
|
||||
switch event.Rune() {
|
||||
case 'g':
|
||||
g.rowOffset, g.columnOffset = 0, 0
|
||||
case 'G':
|
||||
g.rowOffset = math.MaxInt32
|
||||
case 'j':
|
||||
g.rowOffset++
|
||||
case 'k':
|
||||
g.rowOffset--
|
||||
case 'h':
|
||||
g.columnOffset--
|
||||
case 'l':
|
||||
g.columnOffset++
|
||||
}
|
||||
case tcell.KeyHome:
|
||||
g.rowOffset, g.columnOffset = 0, 0
|
||||
case tcell.KeyEnd:
|
||||
g.rowOffset = math.MaxInt32
|
||||
case tcell.KeyUp:
|
||||
g.rowOffset--
|
||||
case tcell.KeyDown:
|
||||
g.rowOffset++
|
||||
case tcell.KeyLeft:
|
||||
g.columnOffset--
|
||||
case tcell.KeyRight:
|
||||
g.columnOffset++
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (g *Grid) Draw(screen tcell.Screen) {
|
||||
g.Box.DrawForSubclass(screen, g)
|
||||
@ -714,3 +665,66 @@ func (g *Grid) MouseHandler() func(action MouseAction, event *tcell.EventMouse,
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
// InputHandler returns the handler for this primitive.
|
||||
func (g *Grid) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
|
||||
return g.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) {
|
||||
if !g.hasFocus {
|
||||
// Pass event on to child primitive.
|
||||
for _, item := range g.items {
|
||||
if item != nil && item.Item.HasFocus() {
|
||||
if handler := item.Item.InputHandler(); handler != nil {
|
||||
handler(event, setFocus)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Process our own key events if we have direct focus.
|
||||
switch event.Key() {
|
||||
case tcell.KeyRune:
|
||||
switch event.Rune() {
|
||||
case 'g':
|
||||
g.rowOffset, g.columnOffset = 0, 0
|
||||
case 'G':
|
||||
g.rowOffset = math.MaxInt32
|
||||
case 'j':
|
||||
g.rowOffset++
|
||||
case 'k':
|
||||
g.rowOffset--
|
||||
case 'h':
|
||||
g.columnOffset--
|
||||
case 'l':
|
||||
g.columnOffset++
|
||||
}
|
||||
case tcell.KeyHome:
|
||||
g.rowOffset, g.columnOffset = 0, 0
|
||||
case tcell.KeyEnd:
|
||||
g.rowOffset = math.MaxInt32
|
||||
case tcell.KeyUp:
|
||||
g.rowOffset--
|
||||
case tcell.KeyDown:
|
||||
g.rowOffset++
|
||||
case tcell.KeyLeft:
|
||||
g.columnOffset--
|
||||
case tcell.KeyRight:
|
||||
g.columnOffset++
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// PasteHandler returns the handler for this primitive.
|
||||
func (g *Grid) PasteHandler() func(pastedText string, setFocus func(p Primitive)) {
|
||||
return g.WrapPasteHandler(func(pastedText string, setFocus func(p Primitive)) {
|
||||
for _, item := range g.items {
|
||||
if item != nil && item.Item.HasFocus() {
|
||||
if handler := item.Item.PasteHandler(); handler != nil {
|
||||
handler(pastedText, setFocus)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -63,6 +63,11 @@ var (
|
||||
//
|
||||
// - Tab, BackTab, Enter, Escape: Finish editing.
|
||||
//
|
||||
// Note that while pressing Tab or Enter is intercepted by the input field, it
|
||||
// is possible to paste such characters into the input field, possibly resulting
|
||||
// in multi-line input. You can use [InputField.SetAcceptanceFunc] to prevent
|
||||
// this.
|
||||
//
|
||||
// If autocomplete functionality is configured:
|
||||
//
|
||||
// - Down arrow: Open the autocomplete drop-down.
|
||||
@ -386,6 +391,8 @@ func (i *InputField) Autocomplete() *InputField {
|
||||
// This package defines a number of variables prefixed with InputField which may
|
||||
// be used for common input (e.g. numbers, maximum text length). See for example
|
||||
// [InputFieldInteger].
|
||||
//
|
||||
// When text is pasted, lastChar is 0.
|
||||
func (i *InputField) SetAcceptanceFunc(handler func(textToCheck string, lastChar rune) bool) *InputField {
|
||||
i.accept = handler
|
||||
return i
|
||||
@ -587,6 +594,11 @@ func (i *InputField) InputHandler() func(event *tcell.EventKey, setFocus func(p
|
||||
i.autocompleteListMutex.Lock()
|
||||
case tcell.KeyEnter, tcell.KeyEscape, tcell.KeyTab, tcell.KeyBacktab:
|
||||
finish(key)
|
||||
case tcell.KeyCtrlV:
|
||||
if i.accept != nil && !i.accept(i.textArea.getTextBeforeCursor()+i.textArea.GetClipboardText()+i.textArea.getTextAfterCursor(), 0) {
|
||||
return
|
||||
}
|
||||
i.textArea.InputHandler()(event, setFocus)
|
||||
case tcell.KeyRune:
|
||||
if event.Modifiers()&tcell.ModAlt == 0 && i.accept != nil {
|
||||
// Check if this rune is accepted.
|
||||
@ -660,3 +672,28 @@ func (i *InputField) MouseHandler() func(action MouseAction, event *tcell.EventM
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
// PasteHandler returns the handler for this primitive.
|
||||
func (i *InputField) PasteHandler() func(pastedText string, setFocus func(p Primitive)) {
|
||||
return i.WrapPasteHandler(func(pastedText string, setFocus func(p Primitive)) {
|
||||
// Input field may be disabled.
|
||||
if i.textArea.GetDisabled() {
|
||||
return
|
||||
}
|
||||
|
||||
// The autocomplete drop down may be open.
|
||||
i.autocompleteListMutex.Lock()
|
||||
defer i.autocompleteListMutex.Unlock()
|
||||
if i.autocompleteList != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// We may not accept this text.
|
||||
if i.accept != nil && !i.accept(i.textArea.getTextBeforeCursor()+pastedText+i.textArea.getTextAfterCursor(), 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// Forward the pasted text to the text area.
|
||||
i.textArea.PasteHandler()(pastedText, setFocus)
|
||||
})
|
||||
}
|
||||
|
14
pages.go
14
pages.go
@ -315,3 +315,17 @@ func (p *Pages) InputHandler() func(event *tcell.EventKey, setFocus func(p Primi
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// PasteHandler returns the handler for this primitive.
|
||||
func (p *Pages) PasteHandler() func(pastedText string, setFocus func(p Primitive)) {
|
||||
return p.WrapPasteHandler(func(pastedText string, setFocus func(p Primitive)) {
|
||||
for _, page := range p.pages {
|
||||
if page.Item.HasFocus() {
|
||||
if handler := page.Item.PasteHandler(); handler != nil {
|
||||
handler(pastedText, setFocus)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
11
primitive.go
11
primitive.go
@ -55,4 +55,15 @@ type Primitive interface {
|
||||
// subclass from Box, it is recommended that you wrap your handler using
|
||||
// Box.WrapMouseHandler() so you inherit that functionality.
|
||||
MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive)
|
||||
|
||||
// PasteHandler returns a handler which receives pasted text.
|
||||
// It is called by the Application class.
|
||||
//
|
||||
// A value of nil may also be returned to stop the downward propagation of
|
||||
// paste events.
|
||||
//
|
||||
// The Box class may provide functionality to intercept paste events in the
|
||||
// future. If you subclass from Box, it is recommended that you wrap your
|
||||
// handler using Box.WrapPasteHandler() so you inherit that functionality.
|
||||
PasteHandler() func(text string, setFocus func(p Primitive))
|
||||
}
|
||||
|
44
textarea.go
44
textarea.go
@ -165,13 +165,15 @@ type textAreaUndoItem struct {
|
||||
// operating system's key bindings for copy+paste functionality may not have the
|
||||
// expected effect as tview will not be able to handle these keys. Pasting text
|
||||
// using your operating system's or terminal's own methods may be very slow as
|
||||
// each character will be pasted individually.
|
||||
// each character will be pasted individually. However, some terminals support
|
||||
// pasting text blocks which is supported by the text area, see
|
||||
// [Application.EnablePaste] for details.
|
||||
//
|
||||
// The default clipboard is an internal text buffer, i.e. the operating system's
|
||||
// clipboard is not used. If you want to implement your own clipboard (or make
|
||||
// use of your operating system's clipboard), you can use
|
||||
// [TextArea.SetClipboard] which provides all the functionality needed to
|
||||
// implement your own clipboard.
|
||||
// The default clipboard is an internal text buffer local to this text area
|
||||
// instance, i.e. the operating system's clipboard is not used. If you want to
|
||||
// implement your own clipboard (or make use of your operating system's
|
||||
// clipboard), you can use [TextArea.SetClipboard] which provides all the
|
||||
// functionality needed to implement your own clipboard.
|
||||
//
|
||||
// The text area also supports Undo:
|
||||
//
|
||||
@ -917,7 +919,8 @@ func (t *TextArea) SetOffset(row, column int) *TextArea {
|
||||
// retrieve text from the clipboard (pasteFromClipboard).
|
||||
//
|
||||
// Providing nil values will cause the default clipboard implementation to be
|
||||
// used.
|
||||
// used. Note that the default clipboard is local to this text area instance.
|
||||
// Copying text to other widgets will not work.
|
||||
func (t *TextArea) SetClipboard(copyToClipboard func(string), pasteFromClipboard func() string) *TextArea {
|
||||
t.copyToClipboard = copyToClipboard
|
||||
if t.copyToClipboard == nil {
|
||||
@ -936,6 +939,12 @@ func (t *TextArea) SetClipboard(copyToClipboard func(string), pasteFromClipboard
|
||||
return t
|
||||
}
|
||||
|
||||
// GetClipboardText returns the current text of the clipboard by calling the
|
||||
// pasteFromClipboard function set with [TextArea.SetClipboard].
|
||||
func (t *TextArea) GetClipboardText() string {
|
||||
return t.pasteFromClipboard()
|
||||
}
|
||||
|
||||
// SetChangedFunc sets a handler which is called whenever the text of the text
|
||||
// area has changed.
|
||||
func (t *TextArea) SetChangedFunc(handler func()) *TextArea {
|
||||
@ -1218,7 +1227,7 @@ func (t *TextArea) Draw(screen tcell.Screen) {
|
||||
}
|
||||
}()
|
||||
|
||||
// No text / placeholder.
|
||||
// No text, show placeholder.
|
||||
if t.length == 0 {
|
||||
t.lastHeight, t.lastWidth = height, width
|
||||
t.cursor.row, t.cursor.column, t.cursor.actualColumn, t.cursor.pos = 0, 0, 0, [3]int{1, 0, -1}
|
||||
@ -1280,6 +1289,13 @@ func (t *TextArea) Draw(screen tcell.Screen) {
|
||||
}
|
||||
}
|
||||
|
||||
// Selected tabs are a bit special.
|
||||
if cluster == "\t" && style == t.selectedStyle {
|
||||
for colX := 0; colX < clusterWidth && posX+colX-columnOffset < width; colX++ {
|
||||
screen.SetContent(x+posX+colX-columnOffset, y+posY, ' ', nil, style)
|
||||
}
|
||||
}
|
||||
|
||||
// Draw character.
|
||||
if posX+clusterWidth-columnOffset <= width && posX-columnOffset >= 0 && clusterWidth > 0 {
|
||||
screen.SetContent(x+posX-columnOffset, y+posY, runes[0], runes[1:], style)
|
||||
@ -2414,3 +2430,15 @@ func (t *TextArea) MouseHandler() func(action MouseAction, event *tcell.EventMou
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
// PasteHandler returns the handler for this primitive.
|
||||
func (t *TextArea) PasteHandler() func(pastedText string, setFocus func(p Primitive)) {
|
||||
return t.WrapPasteHandler(func(pastedText string, setFocus func(p Primitive)) {
|
||||
from, to, row := t.getSelection()
|
||||
t.cursor.pos = t.replace(from, to, pastedText, false)
|
||||
t.cursor.row = -1
|
||||
t.truncateLines(row - 1)
|
||||
t.findCursor(true, row)
|
||||
t.selectionStart = t.cursor
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user