-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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 rendering of tab characters in terminal #734
Comments
It's pretty hackish in gnome-terminal (and reportedly in iterm2 too). The thing is, TAB is a control character that's supposed to move the cursor, but preserve the characters (including their attributes such as background color) it jumps through. So you can only do this smart copy-pasteable TAB thingy if it's printed after the current end of the line (which is good enough in practice for most cases). You might find this (and stuff linked from there) useful: https://gitlab.com/gnachman/iterm2/issues/6193. |
Closing as designed as per above comment. I don't really want to do the copy |
What is the resolution on this? There was a downstream issue related to this that was also closed. I am interested in this functionality as I imagine others are as well. |
@hansvonn it didn't really seem like it made sense to do given how \t works behind the scenes. |
@Tyriar It depends on what perspective you come from. At least for me I expect tabs to be copied when that was what I pushed to the console. I often do this when I want to generate tab delimited data using powershell. As it is now I use regex to replace spaces with tabs which is just another step. I can understand where you are coming from in how consoles used to function. I can also understand how many other things you all have to work on. I appreciate all the good work! |
+1 |
I'm finding this issue annoying when printing ( |
@daiyam I don't think we've found a nice way to add support this so we probably wouldn't accept a PR. |
This is extremely inconvenience. I need to frequently copy data with tabs from VSCode terminal, which is the only way I get such data due to some limitations. Such replacement is unacceptably destroying productivity. |
@limbxo fyi you can pretty easily map spaces back to tabs by selecting 4 spaces for example, hitting cmd/ctrl+shift+l to select all instances of the selection in the file, delete then tab. |
@daiyam I saw it, my point is it can take seconds to get the tabs back. The PR was closed because it had too many changes, you solved most of that by putting out other PRs but it still has changes for 30 files. I think a more targeted fix that only changed how copy works would be safer and have less risk for regressions elsewhere. Looking at this a little I think a safer approach would be to not annotate the "tab filler" characters but instead add a tab hint flag for any cell containing a tab. |
I quite understand technical difficulties behind tabs, and I would be glad
to help with some elegant enough solutions.
Anyway, I have to say that my situation is more complicated, as tabs not
only appear in the beginning, which can be eaisily replaced as you stated,
they do appear in the middle, which isn’t fixed length when replaced with
spaces at all, and original data has spaces (more than one) in it as well,
which makes recovering data extremely hard. Plus, this is the ONLY way I
retrieve these data, due to some limitations. I’m not even able to reformat
data before they are print. And, I have to do that many many times, in
almost every single day. Having to recover data this way only because tabs
can’t be copied correctly is crazily insane.
…On Tue, May 31, 2022 at 11:26 PM Daniel Imms ***@***.***> wrote:
@limbxo <https://github.com/limbXo> fyi you can pretty easily map spaces
back to tabs by selecting 4 spaces for example, hitting cmd/ctrl+shift+l to
select all instances of the selection in the file, delete then tab.
—
Reply to this email directly, view it on GitHub
<#734 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AOPZXNU7ATAVXRZHOLYYPWTVMYVTPANCNFSM4DQ3Z4TA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
@limbxo since you're using VS Code you could pipe whatever you're working with into an editor: |
this got moved to its own repo fyi: https://github.com/daiyam/xterm-tab given this comment:
can we retry now a year later to resolve this? console.log( https://github.com/xtermjs/xterm.js/compare/master...brandonros:xterm.js:tab?expand=1 i made this to see how far the two projects have drifted |
As a user, how it works behind the scenes isn't really relevant to me. If the feature makes sense (and I think "copy the characters my program output instead of other characters" makes sense), then if the implementation doesn't match up with the feature request the implementation is wrong, not the feature. It could be reasonable to close this as "Too hard to solve" or "Not worth the effort", but "Working as intended" feels like the wrong answer here. |
Yeah! A feature-blocker for me. My fork is still working but since around 6 months, it's breaking some of my powerlines... |
TAB is not a character, it is a control code meant to be "executed" by the terminal. Thats what xterm.js does "as intended".
Let me translate that - if someone requests that a red traffic light should mean "go" instead of "stop" - the traffic lights are all wrong? Interesting logic, good luck with that. |
If the semantics argument is that a tab is not a character but a control code, then should it not be that instead of outputting spaces, it creates an unselectable spacing element? I'm genuinely confused about the logic here. And why doesn't the same logic apply to line feeds? Also, related on Stack Overflow: Printing tab (\t) characters in VS Code terminal. |
In VSCode, I just wonder why the tab character has a different behaviour between the editor or the terminal.
No because we don't know if a 4 spaces block was a tab or 4 spaces in the original file. |
The behavior is pretty standardized across terminal emulators and the question how to represent empty space by SP - it dates back to old DEC behavior predating any of the fancy styling/annotation possibilities with HTML/CSS or even unicode. We cannot simply use other patterns here ignoring what 99% of all other TEs would do.
The reason, why TABs are hard to impossible to replay from the terminal state, is because of the quality of the behavior it controls, not simply the fact that it is a control char. A newline (NL) for example is also a control char (more precisely 2 control chars - CR + LF), still it can be replayed, as it has a direct representation on the terminal buffer (well LF has, CR is still lost). For TAB that "moving the writing head" creates edge cases, which makes a reasonable restore handling of TABs unreasonable - most notably any jumped over content cannot be serialized in a useful way anymore. To compare with what most editor do here, a terminal has another drawback - editors mostly run in insert mode moving existing content to the right, while terminals typically run in replace mode. Example:
So the full input was |
We could indeed hack something together to guess if it's a tab, but personally I've been burned before with these designed to be flaky features such as alt+click to move the cursor which has resulted in many non-actionable issues that I need to triage/respond to/close, and will continue to until the feature is removed as I don't think it's possible to fix its flaws. I can foresee years of "tab character copied when copying in the terminal!!!" issues if we implemented this. The safest option is to go with the well defined and consistent behavior of copying exactly what the terminal is told to render. |
I agree! I would be happy to help. |
@daiyam About your
Maybe I misunderstood - returning the actual render state is exactly what xterm.js does atm. |
Or maybe me! For example, when rendering Edit: it's the title of the issue... |
Thats not correct. TAB tells the terminal to move the cursor to the next tabstop, which might be one to max tabwidth cells away in printing direction (typically to the right).
Huh? xterm.js does not insert 4 spaces, it just moves the cursor to the next tabstop. Imho that rendering behavior is correct. You are mixing terminal render state with copy&paste row serialization here. To stick with the title of the ticket - rendering of a TAB makes no sense, as it is a cursor action with no visual representation. It can only be observed by actual content around it. |
So why do I get spaces when copied? I don't remember the internals of xterm.js but, all I know is that |
@daiyam because there's a space there, as opposed to an empty cell where we would not. |
Because thats the only reliable way to advance the cursor in any editor/textfield to preserve the visual state of the terminal output. (Edit: and nope thats not done in terminal rendering, but during content serialization of the terminal buffer.) |
@jerch Thanks for the example and elaboration. It was helpful to me to understand the reasoning here. |
Tab is not a character ??? And zero is not a number, I suppose ??? |
@Eric-Polin This is not a philosophical dispute, but based on practicability. TAB cannot be replayed in a reliable fashion, unless all paste targets fully implement cursor mechs with replace mode. You will figure that yourself by re-reading the comments above and putting some effort into comprehension. |
Thank you for your diligent response. |
If thats the case, then you might also know, that the TTY/pipe distinction in unixoid OSes is much older - from around early 70s. It does not matter at that point, when POSIX finally specced it into a reliable standard. Windows is a totally different story. They better would not have dumped their old SFU extension (worked up to XP I think), which gave a much better POSIX compliant abstraction layer to windows than the patchwork we have today. Even openVMS (which is much closer to NT than any unixoid system) still gets that done.
Then work with raw terminal data. It has all the control codes incl. TAB. But again - you gonna need a parsing lib, that ideally implements terminal mechs, atleast proper cursor sequences. (e.g. |
Those are previous answers I got. In one, tabs aren't replaced by spaces. In the second one, they are replace by spaces. Look like there is an issue there. What I would like is that when a tab is printed, I should able to get it back when copying the output. (Only when the tab isn't moving over existing characters) |
As always - context matters. You successfully stripped the context in a way, that lets this look like a contradiction. Try again with the context included and you will see - there is no contradiction. |
Can you at least agree that with |
Sure I can agree, because xterm.js wont give you the TAB, when you copy the terminal output.
Nope. If you want structured data from your app, dont scrape the terminal. The terminal output is a visual representation to make sense for the human eye. Scraping the terminal is like getting text from a photo copy - it would need heuristics to translate that human eye pleasing representation back to a structured data variant (like an OCR for text from a photo copy). To keep working with TABs included and see the terminal output at once, you can do things like: $> printf 'tab=\t;\n' | tee >(python -c 'import sys; print(repr(sys.stdin.read()))')
tab= ;
'tab=\t;\n' where the first line is the "content report" by xterm.js, and the second line the content seen by your processor still containing TABs (python here). Last but not least - most TEs (except vte-based and iterm2) work exactly as xterm.js in this regard. I dont think we should change that to a wonky "might-output-TABs-under-circumstanceA-but-not-under-B,C" state. It will only cause more confusion and followup issues with ppl complaining, why they dont get TABs for B & C, or even why they get TABs for A at all. Watering the terminal state further with wonkiness never was a good idea in the past and it most likely will not be in the future. And since there are processing alternatives, I dont even see a reason to keep this dicussion going. |
Except:
Most Linux' TE are based on VTE... |
It's too hard to do this. Nevermind that every other terminal in the world preserves tabs. It's just too hard/not a good idea. |
Since we just entered the kindergarten level in this thread I gonna lock it. If anyone has something substantial to add to the topic like an impl idea addressing the edgecases, feel free to open a discussion about it and maybe link to this topic. Plz try to restrain from adding derailing or dumb comments, as it helps no one to get anywhere. Thx. |
@jerch I was very close to doing the same 👍 |
Downstream: microsoft/vscode#29523
node -e "console.log('a\tb')"
should output an actual tab. This means it's considered a single character by the selection logic and that it's copied as a\t
char not several spaces. This probably won't be too difficult to deal with by leveraging and improving upon the double width char code.This is supported by gnome-terminal, Terminal.app and iTerm2.
The text was updated successfully, but these errors were encountered: