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

Convert paste line endings #1094

Closed
wants to merge 7 commits into from
Closed

Convert paste line endings #1094

wants to merge 7 commits into from

Conversation

d-bingham
Copy link
Contributor

Summary of the Pull Request

Implements line-ending conversion for pasting. Specifically by introducing a new option -- convertPasteLineEndings (optional, defaults to false) -- which, when set, causes pastes from the clipboard to have CRLF pairs converted to LFs.

See here: (Top copy/paste is prior behavior or convertPasteLineEndings set to false; bottom is convertPasteLineEndings set to true; this is Terminal running WSL bash):

image

References

PR Checklist

Detailed Description of the Pull Request / Additional comments

The new option, convertPasteLineEndings does what it says -- replacing Windows-space CRLF pairs with Unix-space LFs in text pasted to the console. This option applies to both the keyboard-shortcut paste and the right-click paste. Without this most multiline text pasted into Terminal will be "double-spaced" due to the Windows-style CRLF pairs. Furthermore, any multiline text copied from Terminal (in trim whitespace mode) generates CRLF pairs, which guarantees double-spacing when copying from a WSL Terminal session.

Changes:

  • Added TermControl::_SendPastedTextToConnection which adds a pre-processing layer on top of _SendInputToConnection to allow line-ending conversion
  • Various code in Profile/TerminalSettings to support the new option "convertPasteLineEndings" (optional, defaults to false)

Notes:

@d-bingham
Copy link
Contributor Author

Windows -> Unix line-ending conversion is pretty much unavoidable for Terminal to interact happily with WSL. TextBuffer::GetTextForClipboard inserts CRLF pairs into copied text, and while this could be changed to (optionally) generate LFs instead of CRLFs, this doesn't seem to be sufficient since many/most Windows text editors (at a minimum Notepad, VS2019, and vscode) generate CRLF pairs.

I think fixing this at the paste level is the ideal location for the fix, as I'm not aware of another way for CRLFs to reasonably get into Unix-space terminal sessions that don't want them.

Fixing it as a profile-level option seems appropriate (as opposed to having separate key bindings for "raw paste" and "CRLF fixed paste"), as key bindings are app-wide and a profile-level setting allows different behavior for, say, bash vs. powershell.

@d-bingham
Copy link
Contributor Author

This has overlap with #395 -- at the least, this fix and #395 seem to want to process the pasted text at the same place.

@ivan-section-io
Copy link

Generate LFs on paste instead of CRLFs? I think this is incorrect.

If this is a terminal and we're trying to emulate typing - I believe we're likely after CRs instead of CRLFs.

Some shells (like bash) look for LF endings, and then use stty icrnl setting to convert incoming interactive keyboard CRs to LFs. This way they can accept both CR or LF endings.

Unfortunately, if you start using a (typically interactive) program (e.g. nano editor) that doesn't use stty icrnl and thus can tell the difference between CRs and LFs - you'll find that it expects a CR for [Enter]/[Return] keys, and that sending an LF will cause "strange" behavior (e.g. turning LFs to spaces).

If you test pasting to both bash and nano in a default WSL Ubuntu - you'll find that CRLF to CR works in both, whereas CRLF to CR only works for bash.

(I've just re-tested all 3 CRLF/LF/CR line-ending pasting scenarios into WSL using 880272c, and CR line-endings was the only that worked as "expected".)

@d-bingham
Copy link
Contributor Author

Updated to sending the correct character.

@d-bingham
Copy link
Contributor Author

Follow-up: Is there any reason to have more-granular settings? That is, is there a point to having an option which specifies which line-ending to use, or is \x0d sufficient? Clearly my knowledge here is lacking, because I thought bash/vim's handling of \x0a was universal...

@ivan-section-io
Copy link

Follow-up: Is there any reason to have more-granular settings?
Good question.

Consumer scenarios I can think of:
Paste where line-endings should be converted to a Return/Enter key equivalent.
Paste to something expecting raw content... I have no idea what (practically) that might be.

Producer scenarios:
I'm likely to have clipboard content with Unix LF line endings, and would want that switched to CR terminal codes for pasting to interactive applications.

I'm just ignoring bracketed paste (http://www.xfree86.org/current/ctlseqs.html#Bracketed%20Paste%20Mode) at this point

zadjii-msft
zadjii-msft previously approved these changes Jun 18, 2019
Copy link
Member

@zadjii-msft zadjii-msft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems mostly reasonable to me.

This won't really work for profiles that have the setting set to false (like cmd.exe) and then run wsl though, correct? Hopefully in the future we can work on a solution to that scenario too.

@@ -85,6 +86,7 @@ Profile::Profile(const winrt::guid& guid) :
_useAcrylic{ false },
_scrollbarState{},
_closeOnExit{ true },
_convertPasteLineEndings{},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a tangential change, do we want the WSL profiles that are auto-generated to default to having this setting set to true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that sounds like a good idea.


std::wstring::size_type pos = 0;

// Lament that the stl string does not have
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::regex_replace allows replacing all matches in a single op:

if (_settings.ConvertPasteLineEndings()) {
  const static std::wregex rgx{ L"\n\r" };
  std::wstring stripped = std::regex_replace(wstr, rgx, L"\n");
  _SendInputToConnection(stripped);
}
...

@miniksa
Copy link
Member

miniksa commented Jun 25, 2019

/azp run

@azure-pipelines
Copy link

Pull request contains merge conflicts.

Copy link
Contributor

@DHowett-MSFT DHowett-MSFT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this needs to be a setting. conpty should be turning <CR> into the right format on the other end. Maybe this is important for other types of connections?

@zadjii-msft zadjii-msft dismissed their stale review July 17, 2019 19:18

Dustin's comment about conpty has me thinking maybe conpty is the place this should be fixed, not the terminal

@miniksa miniksa mentioned this pull request Jul 24, 2019
2 tasks
@DHowett-MSFT
Copy link
Contributor

It looks like this was outmoded by #2390. Thanks again for the original inspiration!

zadjii-msft pushed a commit that referenced this pull request Nov 6, 2019
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request

<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? --> 
## References

#1091 
#1094 
#2390 
#3314

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #1091
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx

<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

Combination of the PRs #1094, #2390, and #3314, especially as discussed in #3314.

In short, this changes line endings from Windows-space \r\n to the more universal \r.

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

Copied and pasted text into the terminal without the patch, line endings were doubled.
With the patch, line endings weren't doubled.


--------------------

* Replacing \r\n line endings with \r line endings

* Fixing Formatting
@zadjii-msft zadjii-msft mentioned this pull request Nov 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Pasted text includes CRLF pairs where unneeded
7 participants