Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support "Paste Bracketing" #1471

Open
TylerLeonhardt opened this issue Apr 15, 2020 · 10 comments
Open

Support "Paste Bracketing" #1471

TylerLeonhardt opened this issue Apr 15, 2020 · 10 comments
Assignees
Labels
Issue-Enhancement It's a feature request. Needs-More Investigation Initial investigation is done, but need to follow up.

Comments

@TylerLeonhardt
Copy link
Member

Description of the new feature/enhancement

For some readline experiences, they support this concept of paste bracketing.

The idea is simple:

  • First, the shell emits esc[?2004h
  • This tells the terminal that this shell wants to use paste bracketing
  • When paste bracketing is on, pasted text is prefixed by esc[200~ and followed by esc[201~ by the terminal before sending the text to the shell.

Here's an example screenshot of my version of bash on macOS with readline (which doesn't support this but you can see the effect):

MicrosoftTeams-image

  • first command tells the terminal to deactivate bracketed pasting
  • second is a paste from the clipboard
  • 3rd activates bracketed pasting
  • 4th is the same paste from the clipboard but now it has \e[200~ and \e[201~ around it

Pretty much any terminal supports this... for example, here's iTerm2's doc:
https://gitlab.com/gnachman/iterm2/-/wikis/Paste-Bracketing#control-sequences

And there's a feature request in Windows Terminal: microsoft/terminal#395

and @Tyriar was considering adding this to VS Code's terminal as well.

What does supporting this mean?

This means that on macOS and Linux (and really crossplat) we can support multi-line pasting - something that has been available on Windows in conhost.exe for a very long time.

Proposed technical implementation details (optional)

At start up, PSReadLine emits \e[?2004h to tell the terminal to use paste bracketing

When we get \e[200~ we can wait until \e[201~ before actually executing anything. (or we can wait for the ENTER after \e[201~)

@TylerLeonhardt TylerLeonhardt added the Issue-Enhancement It's a feature request. label Apr 15, 2020
@ghost ghost added the Needs-Triage 🔍 It's a new issue that core contributor team needs to triage. label Apr 15, 2020
@SteveL-MSFT SteveL-MSFT added this to the 2.1.0-Consider milestone Apr 16, 2020
@lzybkr
Copy link
Member

lzybkr commented Apr 16, 2020

This would resolve this longstanding issue too: #579.

@iSazonov
Copy link

Should it be in PowerShell consolehost too?

@Tyriar
Copy link

Tyriar commented Apr 16, 2020

Oh vscode has had this support for a long time. I was just suggesting it to use as an alternative as its what most programs do instead of listening for ctrl+v, plus it may work on windows now with conpty.

@daxian-dbw daxian-dbw added Needs-More Investigation Initial investigation is done, but need to follow up. and removed Needs-Triage 🔍 It's a new issue that core contributor team needs to triage. labels Apr 20, 2020
@daxian-dbw
Copy link
Member

For my own reference: https://cirw.in/blog/bracketed-paste

@TylerLeonhardt
Copy link
Member Author

This issue can be fixed with this
PowerShell/vscode-powershell#3087 (comment)

@daxian-dbw daxian-dbw removed this from the 2.1.0-Consider milestone Jan 5, 2021
@skyline75489
Copy link

With microsoft/terminal#9034 merged, bracketed paste is supported in Windows Terminal. I'd love to see it in PSReadLine, too.

@lzybkr
Copy link
Member

lzybkr commented Feb 15, 2021

I believe supporting this is non-trivial.

PSReadLine currently relies on Console.ReadKey to deal with the platform specifics w.r.t. input, e.g. on non-Windows, the dotnet runtime does a decent job of support the terminfo database.

As I understand bracketed paste - the dotnet runtime would likely ignore the paste begin/end sequences as Console.ReadKey doesn't have a good way to return the metainfo we would need.

PSReadLine does have limited support for mapping the VT input escape sequences, but it is currently Windows only and not used by default - but that code might be of use to someone wanting to add support for bracketed paste.

@SteveL-MSFT
Copy link
Member

So it sounds like we need .NET to support understanding this escape sequence and then have a way to inform PSReadLine rather than PSReadLine trying to parse the escape sequence itself.

@daxian-dbw
Copy link
Member

daxian-dbw commented Oct 7, 2021

Feature requesting issue opened on .NET repo: dotnet/runtime#60107
Also opened an issue to ask for clarification on the current behavior of Console.ReadKey regarding the start/end sequences of bracketed paste: dotnet/runtime#60101

In summary, the dependencies for fixing this in PowerShell are:

  1. [API Proposal]: Allow Console.ReadKey to parse VT sequences when ENABLE_VIRTUAL_TERMINAL_INPUT is set on Windows
  2. Console.ReadKey returns incomplete VT sequences for bracketed paste
  3. Support bracketed paste in conhost

Be noted that, today some key-bindings (e.g. Ctrl+[) work on Windows but not on Unix platforms because on Unix Console.ReadKey needs to parse/map VT sequences to ConsoleKeyInfo and thus those key-bindings are interpreted differently.

Assuming dotnet/runtime#60107 is addressed in .NET using the same parsing/mapping code that works on Unix, then those key-bindings will stop working on Windows once we switch to the new mode of Console.ReadKey in order to enable ENABLE_VIRTUAL_TERMINAL_INPUT on Windows. That would definitely be a breaking change. So, when working on this fix (after all dependencies are ready), we may need to consider to have this fix an opt-in feature, instead of the default.

@o-sdn-o
Copy link

o-sdn-o commented Dec 14, 2023

Since PSReadLine reads the input stream using ReadConsoleInput, could you consider adding a support for "Bracketed Paste" marks (INPUT_RECORD marks) in the following form:

Clipboard block (inbound INPUT_RECORD stream):

rec_first.EventType == MENU_EVENT;
rec_first.Event.MenuEvent.dwCommandId = 0x8001; // paste_begin

// set of recs with wchar-by-wchar binary copy
// of the block pasted from the clipboard
...
rec_n.EventType == KEY_EVENT;
rec_n.Event.KeyEvent.uChar.UnicodeChar = wchar; // Pasted data set
...

rec_last.EventType == MENU_EVENT;
rec_last.Event.MenuEvent.dwCommandId`= 0x8002; // paste_end

Here I mean placing marks on the operating system side (condrv), and not on the application side. In particular, 3p terminal emulator, receiving a clipboard block via SSH, forms on the condrv side a set of INPUT_RECORD records that PSReadLine is waiting for.

This approach greatly simplifies the task of cross-platform transferring a clipboard binary immutable block via SSH between hosts. Both from unix to windows to unix, and from windows to unix to windows.

Currently, an immutable block of even plain text requires modification before sending to PSReadLine. PSReadLine requires converting '\r' and '\n' into a VK_RETURN keystroke.

Also, if there is a requirement for binary immutability of the pasted block, the use of in-text markers \e[200~-\e[201~ creates the following issues:

  • It is not possible to paste the following piece of UTF-8 text from the clipboard:

    The following characters �������[201~207] are elements.
    
    • After applying in-text marks: �[200~The following characters �������[201~207] are elements.�[201~
    • The result is two altered fragments:
      1. The following characters ������
      2. 207] are elements.�[201~
  • There is a possibility of execution of a malicious block:

    formatt c:�[201~
    - an example to paste from clipboard
    
    • After applying in-text marks: �[200~formatt c:�[201~\n- an example to paste from clipboard�[201~
    • Result:
      1. formatt c:
      2. <VK_RETURN>
      3. - an example to paste from clipboard�[201~

Using INPUT_RECORD marks eliminates these issues.

PS: This approach is necessary on Windows hosts to receive binary immutable blocks from the clipboard (e.g. received via ssh from unix/wsl etc) by an arbitrary console application that expects it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Enhancement It's a feature request. Needs-More Investigation Initial investigation is done, but need to follow up.
Projects
None yet
Development

No branches or pull requests

9 participants