commit c19e012

delthas  ·  2025-12-23 16:34:11 +0000 UTC
parent 6df1449
Fix uploading drag-and-drop files on some terminals

Actually a workaround :P

ghostty and iTerm2 escape the file path before passing it to senpai.
If the file cannot be resolved, try again after un-escaping the
file path. Not great, but better than a switch on terminal ID.

Also, make sure to trim any extra newline, even if passed as Ctrl+j
(for you, ghostty!).

See: https://github.com/ghostty-org/ghostty/discussions/10029
Fixes: https://todo.sr.ht/~delthas/senpai/209
1 files changed,  +32, -9
M app.go
M app.go
+32, -9
 1@@ -613,14 +613,20 @@ func (app *App) handleUIEvent(ev interface{}) bool {
 2 		app.pastingInputOnly = len(app.win.InputContent()) == 0
 3 	case vaxis.PasteEndEvent:
 4 		app.pasting = false
 5-		if app.pastingInputOnly {
 6-			app.pastingInputOnly = false
 7+		if !app.pastingInputOnly {
 8+			break
 9+		}
10+		app.pastingInputOnly = false
11 
12-			path := string(app.win.InputContent())
13-			if _, err := os.Stat(path); err == nil {
14-				app.win.InputSet(fmt.Sprintf("/upload %v", path))
15+		path := string(app.win.InputContent())
16+		path = strings.TrimRight(path, "\n")
17+		if _, err := os.Stat(path); err != nil {
18+			path = dropBackslash(path)
19+			if _, err := os.Stat(path); err != nil {
20+				break
21 			}
22 		}
23+		app.win.InputSet(fmt.Sprintf("/upload %v", path))
24 	case vaxis.Mouse:
25 		app.handleMouseEvent(ev)
26 	case vaxis.Key:
27@@ -1119,10 +1125,12 @@ func (app *App) handleKeyEvent(ev vaxis.Key) {
28 	}
29 
30 	if ev.EventType == vaxis.EventPaste {
31-		for _, keycode := range []rune{'\n', '\r', vaxis.KeyKeyPadEnter} {
32-			k := keyMatch{
33-				keycode: keycode,
34-			}
35+		for _, k := range []keyMatch{
36+			{keycode: '\n'},
37+			{keycode: '\r'},
38+			{keycode: vaxis.KeyKeyPadEnter},
39+			{keycode: 'j', mods: vaxis.ModCtrl},
40+		} {
41 			for _, km := range keyMatches(ev) {
42 				if km == k {
43 					app.win.InputRune('\n')
44@@ -2648,6 +2656,21 @@ func formatSize(v int64) string {
45 	panic("unreachable")
46 }
47 
48+func dropBackslash(s string) string {
49+	// Naive implementation, just enough to unescape file paths escaped by some terminals.
50+	var sb strings.Builder
51+	esc := false
52+	for _, r := range s {
53+		if !esc && r == '\\' {
54+			esc = true
55+			continue
56+		}
57+		sb.WriteRune(r)
58+		esc = false
59+	}
60+	return sb.String()
61+}
62+
63 func BuildVersion() (string, bool) {
64 	if bi, ok := debug.ReadBuildInfo(); ok {
65 		return bi.Main.Version, true