@@ -56,7 +56,7 @@ class WebSocketTerminal implements vscode.Pseudoterminal {
5656 /** The number of characters on the line that the user can't delete */
5757 private _margin = 0 ;
5858
59- /** The text writted by the user since the last prompt/read */
59+ /** The text written by the user since the last prompt/read */
6060 private _input = "" ;
6161
6262 /** The position of the cursor within the line */
@@ -98,6 +98,7 @@ class WebSocketTerminal implements vscode.Pseudoterminal {
9898
9999 constructor (
100100 private readonly _targetUri : vscode . Uri ,
101+ private readonly _nonce : string ,
101102 private readonly _nsOverride ?: string
102103 ) { }
103104
@@ -224,7 +225,7 @@ class WebSocketTerminal implements vscode.Pseudoterminal {
224225 this . _hideCursorWrite ( "\x1b]633;P;HasRichCommandDetection=True\x07" ) ;
225226 // Print the opening message
226227 this . _hideCursorWrite (
227- `\x1b[32mConnected to \x1b[0m\x1b[4m${ api . config . host } :${ api . config . port } ${ api . config . pathPrefix } \x1b[0m\x1b[32m as \x1b[0m\x1b[3m${ api . config . username } \x1b[0m\r\n\r\n `
228+ `\x1b[32mConnected to \x1b[0m\x1b[4m${ api . config . host } :${ api . config . port } ${ api . config . pathPrefix } \x1b[0m\x1b[32m as \x1b[0m\x1b[3m${ api . config . username } \x1b[0m\r\n`
228229 ) ;
229230 // Add event handlers to the socket
230231 this . _socket
@@ -273,9 +274,7 @@ class WebSocketTerminal implements vscode.Pseudoterminal {
273274 if ( message . type == "prompt" ) {
274275 // Write the prompt to the terminal
275276 this . _hideCursorWrite (
276- `\x1b]633;D${ this . _promptExitCode } \x07${ this . _margin ? "\r\n" : "" } \x1b]633;A\x07${
277- message . text
278- } \x1b]633;B\x07`
277+ `\x1b]633;D${ this . _promptExitCode } \x07\r\n\x1b]633;A\x07${ message . text } \x1b]633;B\x07`
279278 ) ;
280279 this . _margin = this . _cursorCol = message . text . replace ( this . _colorsRegex , "" ) . length ;
281280 this . _prompt = message . text ;
@@ -366,13 +365,14 @@ class WebSocketTerminal implements vscode.Pseudoterminal {
366365 // Send the input to the server for processing
367366 this . _socket . send ( JSON . stringify ( { type : this . _state , input : this . _input } ) ) ;
368367 if ( this . _state == "prompt" ) {
369- this . _hideCursorWrite ( `\x1b]633;E;${ this . _inputEscaped ( ) } \x07\x1b]633;C\x07\r\n ` ) ;
368+ this . _hideCursorWrite ( `\x1b]633;E;${ this . _inputEscaped ( ) } ; ${ this . _nonce } \x07\r\n\ x1b]633;C\x07` ) ;
370369 if ( this . _input == "" ) {
371370 this . _promptExitCode = "" ;
372371 }
373372 }
374373 this . _input = "" ;
375374 this . _state = "eval" ;
375+ this . _margin = this . _cursorCol = 0 ;
376376 return ;
377377 }
378378 case keys . ctrlH :
@@ -561,7 +561,7 @@ class WebSocketTerminal implements vscode.Pseudoterminal {
561561 if ( this . _cursorCol == this . _margin + inputArr [ inputArr . length - 1 ] . length ) {
562562 // Move the cursor to the beginning of the input
563563 this . _moveCursor ( this . _margin - this . _cursorCol ) ;
564- // Erase everyhting to the right of the cursor
564+ // Erase everything to the right of the cursor
565565 this . _hideCursorWrite ( "\x1b[0J" ) ;
566566 inputArr [ inputArr . length - 1 ] = "" ;
567567 this . _input = inputArr . join ( "\r\n" ) ;
@@ -588,10 +588,16 @@ class WebSocketTerminal implements vscode.Pseudoterminal {
588588 // Submit the input after processing
589589 // This should only happen due to VS Code's shell integration
590590 submit = true ;
591- char = char . slice ( 0 , - 1 ) ;
592- }
593- // Replace all single \r with \r\n (prompt) or space (read)
594- char = char . replace ( / \r / g, this . _state == "prompt" ? "\r\n" : " " ) ;
591+ // Need to remove any multi-line prompts that are in the command lines
592+ // Workaround for https://github.com/microsoft/vscode/issues/258457
593+ char = char
594+ . slice ( 0 , - 1 )
595+ . split ( "\r" )
596+ . map ( ( l ) => ( l . startsWith ( this . _multiLinePrompt ) ? l . slice ( this . _multiLinePrompt . length ) : l ) )
597+ . join ( "\r" ) ;
598+ }
599+ // Replace all single \r with \r\n
600+ char = char . replace ( / \r (? ! \n ) / g, "\r\n" ) ;
595601 const inputArr = this . _input . split ( "\r\n" ) ;
596602 let eraseAfterCursor = "" ,
597603 trailingText = "" ;
@@ -613,8 +619,10 @@ class WebSocketTerminal implements vscode.Pseudoterminal {
613619 const originalCol = this . _cursorCol ;
614620 let newRow : number ;
615621 if ( char . includes ( "\r\n" ) ) {
616- char = char . replace ( / \r \n / g, `\r\n${ this . _multiLinePrompt } ` ) ;
617- this . _margin = this . _multiLinePrompt . length ;
622+ if ( this . _state == "prompt" ) {
623+ char = char . replaceAll ( "\r\n" , `\r\n${ this . _multiLinePrompt } ` ) ;
624+ this . _margin = this . _multiLinePrompt . length ;
625+ }
618626 const charLines = char . split ( "\r\n" ) ;
619627 newRow =
620628 charLines . reduce (
@@ -632,21 +640,24 @@ class WebSocketTerminal implements vscode.Pseudoterminal {
632640 const colStr = colDelta ? ( colDelta > 0 ? `\x1b[${ colDelta } C` : `\x1b[${ Math . abs ( colDelta ) } D` ) : "" ;
633641 char += trailingText ;
634642 const spaceOnCurrentLine = this . _cols - ( originalCol % this . _cols ) ;
635- if ( this . _state == "read" && char . length >= spaceOnCurrentLine ) {
643+ if ( this . _state == "read" && ( char . includes ( "\r\n" ) || char . length >= spaceOnCurrentLine ) ) {
636644 // There's no auto-line wrapping when in read mode, so we must move the cursor manually
645+ const charLines = char . split ( "\r\n" ) ;
637646 // Extract all the characters that fit on the cursor's line
638- const firstLine = char . slice ( 0 , spaceOnCurrentLine ) ;
639- const otherLines = char . slice ( spaceOnCurrentLine ) ;
640- const lines : string [ ] = [ ] ;
641- if ( otherLines . length ) {
642- // Split the rest into an array of lines that fit in the viewport
643- for ( let line = 0 , i = 0 ; line < Math . ceil ( otherLines . length / this . _cols ) ; line ++ , i += this . _cols ) {
644- lines [ line ] = otherLines . slice ( i , i + this . _cols ) ;
647+ const firstLine = charLines [ 0 ] . slice ( 0 , spaceOnCurrentLine ) ;
648+ charLines [ 0 ] = charLines [ 0 ] . slice ( spaceOnCurrentLine ) ;
649+ // Split the rest into an array of lines that fit in the viewport
650+ const lines = charLines . flatMap ( ( line , idx ) => {
651+ if ( idx == charLines . length - 1 && line == "" ) {
652+ // Add a blank " line" to move the cursor to the next viewport row
653+ return [ "" ] ;
645654 }
646- } else {
647- // Add a blank "line" to move the cursor to the next viewport row
648- lines . push ( "" ) ;
649- }
655+ const chunks = [ ] ;
656+ for ( let i = 0 ; i < line . length ; i += this . _cols ) {
657+ chunks . push ( line . slice ( i , i + this . _cols ) ) ;
658+ }
659+ return chunks ;
660+ } ) ;
650661 // Join the lines with the cursor escape code
651662 lines . unshift ( firstLine ) ;
652663 char = lines . join ( "\r\n" ) ;
@@ -678,13 +689,14 @@ class WebSocketTerminal implements vscode.Pseudoterminal {
678689 // Send the input to the server for processing
679690 this . _socket . send ( JSON . stringify ( { type : this . _state , input : this . _input } ) ) ;
680691 if ( this . _state == "prompt" ) {
681- this . _hideCursorWrite ( `\x1b]633;E;${ this . _inputEscaped ( ) } \x07\x1b]633;C\x07\r\n ` ) ;
692+ this . _hideCursorWrite ( `\x1b]633;E;${ this . _inputEscaped ( ) } ; ${ this . _nonce } \x07\r\n\ x1b]633;C\x07` ) ;
682693 if ( this . _input == "" ) {
683694 this . _promptExitCode = "" ;
684695 }
685696 }
686697 this . _input = "" ;
687698 this . _state = "eval" ;
699+ this . _margin = this . _cursorCol = 0 ;
688700 } else if ( this . _input != "" && this . _state == "prompt" && this . _syntaxColoringEnabled ( ) ) {
689701 // Syntax color input
690702 this . _socket . send ( JSON . stringify ( { type : "color" , input : this . _input } ) ) ;
@@ -747,6 +759,7 @@ function terminalConfigForUri(
747759 }
748760
749761 sendLiteTerminalTelemetryEvent ( throwErrors ? "profile" : "command" ) ;
762+ const nonce = crypto . randomUUID ( ) ;
750763 return {
751764 name : api . config . serverName && api . config . serverName != "" ? api . config . serverName : "iris" ,
752765 location :
@@ -756,9 +769,10 @@ function terminalConfigForUri(
756769 vscode . window . terminals . length > 0
757770 ? vscode . TerminalLocation . Editor
758771 : vscode . TerminalLocation . Panel ,
759- pty : new WebSocketTerminal ( targetUri , nsOverride ) ,
772+ pty : new WebSocketTerminal ( targetUri , nonce , nsOverride ) ,
760773 isTransient : true ,
761774 iconPath : iscIcon ,
775+ shellIntegrationNonce : nonce ,
762776 } ;
763777}
764778
0 commit comments