// A paste from the terminal: collected between its two marks and handed to // the window in front whole, or replayed as the keys it came as. package app import ( "strings" "github.com/gdamore/tcell/v2" ) // handlePaste marks the start and end of a bracketed paste from the terminal. // // tcell sends the pasted text as ordinary keys between the two marks, so // handleKey collects them while a paste is on, and the end mark decides // where the whole goes. An agent window in front gets it as one paste, which // is what lets a long one be kept aside as a token (acp.View.Paste). Any // other window gets the keys replayed exactly as it would have had them, so // nothing else changes: a paste into a file is typed, as it always was. func (a *App) handlePaste(ev *tcell.EventPaste) { if ev.Start() { a.pasting, a.pasted = true, nil return } keys := a.pasted a.pasting, a.pasted = false, nil if agent := a.activeAgent(); agent != nil && len(a.modals) == 0 { agent.view.Paste(pastedText(keys)) return } for _, key := range keys { a.handleKey(key) } } // pastedText puts the keys of a bracketed paste back into the text they // were: a rune for each character, a newline for each Enter, a tab for each // Tab. Anything else a terminal might send inside a paste is not text. func pastedText(keys []*tcell.EventKey) string { var text strings.Builder for _, key := range keys { switch key.Key() { case tcell.KeyRune: text.WriteRune(key.Rune()) case tcell.KeyEnter, tcell.KeyLF: text.WriteByte('\n') case tcell.KeyTab: text.WriteByte('\t') } } return text.String() }