@@ -9,7 +9,9 @@ import (
"net/http"
"os"
"path/filepath"
+ "regexp"
"slices"
+ "strconv"
"strings"
"charm.land/bubbles/v2/help"
@@ -1917,6 +1919,25 @@ func (m *UI) handlePasteMsg(msg tea.PasteMsg) tea.Cmd {
return nil
}
+ // If pasted text has more than 2 newlines, treat it as a file attachment.
+ if strings.Count(msg.Content, "\n") > 2 {
+ return func() tea.Msg {
+ content := []byte(msg.Content)
+ if int64(len(content)) > maxAttachmentSize {
+ return uiutil.ReportWarn("Paste is too big (>5mb)")
+ }
+ name := fmt.Sprintf("paste_%d.txt", m.pasteIdx())
+ mimeBufferSize := min(512, len(content))
+ mimeType := http.DetectContentType(content[:mimeBufferSize])
+ return message.Attachment{
+ FileName: name,
+ FilePath: name,
+ MimeType: mimeType,
+ Content: content,
+ }
+ }
+ }
+
var cmd tea.Cmd
path := strings.ReplaceAll(msg.Content, "\\ ", " ")
// Try to get an image.
@@ -1966,6 +1987,23 @@ func (m *UI) handlePasteMsg(msg tea.PasteMsg) tea.Cmd {
}
}
+var pasteRE = regexp.MustCompile(`paste_(\d+).txt`)
+
+func (m *UI) pasteIdx() int {
+ result := 0
+ for _, at := range m.attachments.List() {
+ found := pasteRE.FindStringSubmatch(at.FileName)
+ if len(found) == 0 {
+ continue
+ }
+ idx, err := strconv.Atoi(found[1])
+ if err == nil {
+ result = max(result, idx)
+ }
+ }
+ return result + 1
+}
+
// renderLogo renders the Crush logo with the given styles and dimensions.
func renderLogo(t *styles.Styles, compact bool, width int) string {
return logo.Render(version.Version, compact, logo.Opts{