1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
// 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()
}
|