@@ -1,20 +1,36 @@
package fsext
import (
- "runtime"
+ "os"
"strings"
)
-func PasteStringToPaths(s string) []string {
- switch runtime.GOOS {
- case "windows":
- return windowsPasteStringToPaths(s)
+func ParsePastedFiles(s string) []string {
+ s = strings.TrimSpace(s)
+
+ // NOTE: Rio on Windows adds NULL chars for some reason.
+ s = strings.ReplaceAll(s, "\x00", "")
+
+ switch {
+ case attemptStat(s):
+ return strings.Split(s, "\n")
+ case os.Getenv("WT_SESSION") != "":
+ return windowsTerminalParsePastedFiles(s)
default:
- return unixPasteStringToPaths(s)
+ return unixParsePastedFiles(s)
+ }
+}
+
+func attemptStat(s string) bool {
+ for path := range strings.SplitSeq(s, "\n") {
+ if info, err := os.Stat(path); err != nil || info.IsDir() {
+ return false
+ }
}
+ return true
}
-func windowsPasteStringToPaths(s string) []string {
+func windowsTerminalParsePastedFiles(s string) []string {
if strings.TrimSpace(s) == "" {
return nil
}
@@ -42,8 +58,10 @@ func windowsPasteStringToPaths(s string) []string {
}
case inQuotes:
current.WriteByte(ch)
+ case ch != ' ':
+ // Text outside quotes is not allowed
+ return nil
}
- // Skip characters outside quotes and spaces between quoted sections
}
// Add any remaining content if quotes were properly closed
@@ -59,7 +77,7 @@ func windowsPasteStringToPaths(s string) []string {
return paths
}
-func unixPasteStringToPaths(s string) []string {
+func unixParsePastedFiles(s string) []string {
if strings.TrimSpace(s) == "" {
return nil
}
@@ -6,8 +6,8 @@ import (
"github.com/stretchr/testify/require"
)
-func TestPasteStringToPaths(t *testing.T) {
- t.Run("Windows", func(t *testing.T) {
+func TestParsePastedFiles(t *testing.T) {
+ t.Run("WindowsTerminal", func(t *testing.T) {
tests := []struct {
name string
input string
@@ -24,7 +24,7 @@ func TestPasteStringToPaths(t *testing.T) {
expected: []string{`C:\path\my-screenshot-one.png`, `C:\path\my-screenshot-two.png`, `C:\path\my-screenshot-three.png`},
},
{
- name: "sigle with spaces",
+ name: "single with spaces",
input: `"C:\path\my screenshot one.png"`,
expected: []string{`C:\path\my screenshot one.png`},
},
@@ -46,7 +46,7 @@ func TestPasteStringToPaths(t *testing.T) {
{
name: "text outside quotes",
input: `"C:\path\file.png" some random text "C:\path\file2.png"`,
- expected: []string{`C:\path\file.png`, `C:\path\file2.png`},
+ expected: nil,
},
{
name: "multiple spaces between paths",
@@ -66,7 +66,7 @@ func TestPasteStringToPaths(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- result := windowsPasteStringToPaths(tt.input)
+ result := windowsTerminalParsePastedFiles(tt.input)
require.Equal(t, tt.expected, result)
})
}
@@ -141,7 +141,7 @@ func TestPasteStringToPaths(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- result := unixPasteStringToPaths(tt.input)
+ result := unixParsePastedFiles(tt.input)
require.Equal(t, tt.expected, result)
})
}
@@ -2915,7 +2915,7 @@ func (m *UI) handlePasteMsg(msg tea.PasteMsg) tea.Cmd {
// Attempt to parse pasted content as file paths. If possible to parse,
// all files exist and are valid, add as attachments.
// Otherwise, paste as text.
- paths := fsext.PasteStringToPaths(msg.Content)
+ paths := fsext.ParsePastedFiles(msg.Content)
allExistsAndValid := func() bool {
for _, path := range paths {
if _, err := os.Stat(path); os.IsNotExist(err) {
@@ -2956,6 +2956,9 @@ func (m *UI) handleFilePathPaste(path string) tea.Cmd {
if err != nil {
return uiutil.ReportError(err)
}
+ if fileInfo.IsDir() {
+ return uiutil.ReportWarn("Cannot attach a directory")
+ }
if fileInfo.Size() > common.MaxAttachmentSize {
return uiutil.ReportWarn("File is too big (>5mb)")
}