@@ -59,6 +59,11 @@ enum MouseEventMode is export (
5959 MouseAnyEvents => 1003 , # Press, release, any movement
6060);
6161
62+ enum BracketedPasteMode is export <
63+ PasteNoBrackets
64+ PasteWithBrackets
65+ > ;
66+
6267
6368class ModifiedSpecialKey {
6469 has SpecialKey $ . key ;
@@ -221,6 +226,8 @@ role Terminal::LineEditor::KeyMappable {
221226 CursorUp => ' history-prev' ,
222227 CursorDown => ' history-next' ,
223228
229+ PasteStart => ' paste-start' ,
230+
224231 Alt-b => ' move-word-back' ,
225232 Alt-c => ' tclc-word' , # Readline treats this as Capitalize
226233 Alt-d => ' delete-word-forward' ,
@@ -311,6 +318,7 @@ role Terminal::LineEditor::RawTerminalIO {
311318 has atomicint $ ! done = 0 ;
312319 has $ ! parse = make-ansi-parser(emit-item => { $ ! raw-supplier . emit ($ _ ) });
313320 has MouseEventMode: D $ ! previous-mouse-mode = MouseNoEvents;
321+ has BracketedPasteMode: D $ . current-paste-mode = PasteNoBrackets;
314322 has $ ! saved-term-config ;
315323 has $ ! saved-fd ;
316324 has @ ! active-queries ;
@@ -368,6 +376,12 @@ role Terminal::LineEditor::RawTerminalIO {
368376 $ ! previous-mouse-mode = $ mode ;
369377 }
370378
379+ # | Turn bracketed paste mode on or off
380+ method set-bracketed-paste-mode (BracketedPasteMode: D $ mode ) {
381+ $ . output . print ($ mode ?? " \e [?2004h" !! " \e [?2004l" );
382+ $ . output . flush ;
383+ $ ! current-paste-mode = $ mode ;
384+ }
371385
372386 # | Start reading input TTY and feeding the ANSI parser; parsed stream will
373387 # | appear at $!raw-supply, _in tokenized form_ (as codepoints and buffers
@@ -657,8 +671,11 @@ class Terminal::LineEditor::ScrollingSingleLineInput::ANSI
657671 # | Resolve an edit action and compute a new refresh string
658672 method do-edit ($ action , $ insert ? ) {
659673 # Do edit and determine if contents actually changed
660- my $ edited = $ insert . defined ?? self . edit-insert-string($ insert )
661- !! self . " edit-$ action" ();
674+ my $ edited = $ insert . defined
675+ ?? ($ action eq ' insert-string'
676+ ?? self . edit-insert-string($ insert )
677+ !! self . edit-paste-buffer($ insert ))
678+ !! self . " edit-$ action" ();
662679
663680 self . refresh-string($ edited )
664681 }
@@ -685,7 +702,7 @@ class Terminal::LineEditor::CLIInput
685702 constant $ special
686703 = set < abort-input abort-or-delete finish literal-next suspend
687704 history-start history-end history-next history-prev
688- complete > ;
705+ complete paste-start > ;
689706 }
690707
691708 # | Fetch completions based on current buffer contents and cursor pos
@@ -827,6 +844,8 @@ class Terminal::LineEditor::CLIInput
827844
828845 # Read raw characters and dispatch either as actions or chars to insert
829846 my $ literal-mode = False ;
847+ my $ paste-mode = False ;
848+ my @ paste-buffer ;
830849 my $ aborted = False ;
831850 react whenever $ . decoded {
832851 # note "Decoded as {.raku}"; $*ERR.flush;
@@ -840,6 +859,20 @@ class Terminal::LineEditor::CLIInput
840859 self . do-edit(' insert-string' , $ string );
841860 $ literal-mode = False ;
842861 }
862+ elsif $ paste-mode {
863+ my $ key = self . decode-keyname($ _ );
864+ if ! $ key {
865+ @ paste-buffer . push ($ _ );
866+ }
867+ elsif $ key eq ' PasteEnd' {
868+ self . do-edit(' paste-buffer' , @ paste-buffer );
869+ @ paste-buffer = Empty;
870+ $ paste-mode = False ;
871+ }
872+ else {
873+ # Intentionally ignore all other special keys
874+ }
875+ }
843876 else {
844877 my $ key = self . decode-keyname($ _ );
845878 if ! $ key {
@@ -851,6 +884,7 @@ class Terminal::LineEditor::CLIInput
851884 reset-completions;
852885
853886 when ' literal-next' { $ literal-mode = True }
887+ when ' paste-start' { $ paste-mode = True if $ . current-paste-mode }
854888 when ' history-start' { do-history-start }
855889 when ' history-prev' { do-history-prev }
856890 when ' history-next' { do-history-next }
0 commit comments