microsoft / terminal

The new Windows Terminal and the original Windows console host, all in the same place!
MIT License
94.97k stars 8.22k forks source link

Feature Request: Clients of terminal need a way to inquire about the capabilities of the terminal #1040

Open rkeithhill opened 5 years ago

rkeithhill commented 5 years ago

Summary of the new feature/enhancement

Maybe this is as simple as an environment variable like VSCode uses for its terminal e.g. TERM_PROGRAM=WindowsTerminal / TERM_PROGRAM_VERSION=0.0.1.0.

Proposed technical implementation details (optional)

Start by creating the environment variables above so those of us using PowerShell can adapt our user experience (via PowerShell profiles) to Windows Terminal.

DHowett-MSFT commented 5 years ago

As of #897, you can look for $Env:WT_SESSION

oising commented 5 years ago

@dhowett-msft why not use TERM_PROGRAM also, like vs code, hyper and fluentterminal already do? Not too late to change :)

vexx32 commented 5 years ago

Agreed. We can't keep creating new environment variables every single time a new terminal program comes out. Linux already uses $env:TERM and if we have to check several per platform it's just terrible from a UX standpoint. Why reinvent the wheel yet again?

Jaykul commented 5 years ago

An application-specific variable like WT_SESSION is really awful for anyone trying to determine what features they can use. I certainly don't want to have to check a dozen different environment variables to figure out what terminal I'm running in.

TERM_PROGRAM is slightly better, but is really just a lazy version of TERM, which is what all of these terminals should be setting.

Eventually, we're going to get a curses library and a real terminfo database with @TIC@ and @INFOCMP@ macros, shouldn't we start behaving well now?

DHowett-MSFT commented 5 years ago

Hold up, I think there's been a misunderstanding here. I'm sorry about that.

We should definitely support TERM or TERM_PROGRAM. Unfortunately, TERM has become somewhat like a user agent: "I work like this terminal, I promise" -- right up until it doesn't. TERM_PROGRAM, I've never heard of. What does it do? Who is expected to use it, and for what?

WT_SESSION is something else. Today, it can be used to detect Windows Terminal. It is informative, not normative, as a detection mechanism. WT_SESSION tags an individual session -- it is a GUID that the shell (or some other enlightened application) can use in coordination with the terminal to support application state resumption. This feature was inspired by both Terminal.app (the stock terminal emulator on OS X) and its featureful replacement, iTerm2. There's no new and divergent art here.

The idea there is that if WT eventually supports reloading and showing a session's history, that resumed state will use the same session GUID so the shell can do additional things like restoring the working directory or anything else it might have saved off.

DHowett-MSFT commented 5 years ago

informative, not normative

This is why I threw it out as an example and didn't close the feature request. I'll seek to communicate things that are rattling around in my head a bit better going forward.

heaths commented 5 years ago

It would be nice if conhost would define new TERM values as well, so that we can know if we can use larger color palettes (of course, the fact it gets defined would imply that since it would be only in newer versions), differentiate conhost vs. Terminal, etc. In compiled code, it's easy enough to figure out via GetConsoleMode, but in shell scripts (cmd, powershell, etc.) not so much. For examples, flavors of linux define xterm, xterm-color, and xterm-256color, as well as many others. Some convention similar to that indicating color palette (level of VT support) or even Unicode support would be helpful to provide rich console experiences.

be5invis commented 5 years ago

@DHowett-MSFT Maybe both? TERM_PROGRAM for the application name, and TERM for "feature detection"?

Tyriar commented 4 years ago

AFAIK the majority of (non-Windows?) terminals support TERM_PROGRAM and TERM_PROGRAM_VERSION, it's one of the few environment variables vscode's terminal touches (alongside TERM, LANG, COLORTERM). Whether WT should support TERM is another discussion.

bcdev-com commented 4 years ago

I just stumbled across an, obvious in retrospect, but irksome problem with using WT_SESSION as an indicator that you're running inside Windows Terminal. Since it is just a normal environment variable, it propagates as you'd expect, which means if you've launched VSCode from inside Windows Terminal, then the integrated terminal there also has WT_SESSION set, and to the parent value, which would stomp on the intended use for application state resumption.

That's behaving as expected, but certainly isn't desirable. Seems like more reason to need TERM_PROGRAM set as well.

DHowett-MSFT commented 4 years ago

Consider that TERM_PROGRAM would be inherited if you spawn another terminal emulator from WT- like, for example, :terminal in gvim. I’m not sure the heritability of environment variables makes the case for TERM_PROGRAM stronger exactly.

bcdev-com commented 4 years ago

True, but if the defacto protocol is that all terminal emulators set TERM_PROGRAM (and presumably TERM_PROGRAM_VERSION) in the child environment that's a non-issue. That would make it a bug in gvim's :terminal support if it isn't overwriting those environment variables before spawning it's own shell process.

mixmastamyk commented 4 years ago

+1 vote for TERM_PROGRAM, it is also used on Apple and iTerm terminals.

Also, I just checked and WT_SESSION is set for CMD but not for WSL/bash. Whatever var y'all choose, it should be available from every shell for terminal detection to be reliable.

DHowett-MSFT commented 4 years ago

Thanks for that report; I split it out into #3948.

gerardog commented 4 years ago

In my case I don't care much about what terminal program the end user is using, except that I want to know if I can send VT sequences or not. It would be nice if GetConsoleMode api returns the ENABLE_VIRTUAL_TERMINAL_PROCESSING flag enabled when called within a Windows Terminal console or other consoles that already supports VT. If it is possible for the Windows Terminal team implement this it may also be possible to request that on Cmder/ConEmu and have a standard windows way to determine that particular console capability. Using WT_SESSION environment variable already gave me a false positive because I am used to just use start cmd to spawn new consoles, and they inherit the env variable even when running on the regular ConHost.

DHowett-MSFT commented 4 years ago

The presence of Windows Terminal, or any other terminal, does not indicate that the ENABLE_VIRTUAL_TERMINAL_PROCESSING flag is set. Because it is possible to store raw escape sequences in the text buffer with that flag turned off, it must be possible (and even, in some instances, recommended for legacy compatibility) to turn it off. Allowing the connected terminal to parse VT sequences that the console did not parse will lead to visual artifacting ala #1965 #2130 #2759 #1960.

Richienb commented 4 years ago

I propose the following spec:

As well as setting the WT_TERMINAL environmental variable, use a similar strategy to set TERM_PROGRAM to WindowsTerminal.

cc @DHowett-MSFT @heaths @Tyriar

Please get this out of the backlog.

DHowett-MSFT commented 4 years ago

Please get this out of the backlog.

I appreciate that there are folks who care about this, but I’m just not convinced of its value. TERM_PROGRAM has been likened to a browser user agent string, which makes good sense to me if you’re going to use a user agent string to do feature detection. By and large, the past 25 years of web development have shown us that that was almost certainly the wrong thing to do.

If somebody can come up with a legitimately compelling use case apart from “I want my shell to act differently if I’m in different terminals” (which is easily achievable through other means), I’m all ears!

Also: please don’t get in the habit of calling out contributors and community members by name when you want to be heard. If everyone did this for every one of our hundreds of open workitems that someone cares about, we would be deep in emails indeed. Most of us already are: we generally get an email for every comment on every bug in this repo.

Richienb commented 4 years ago

@DHowett-MSFT

A big thing is compatibility detection. Especially for the new Emoji support.

If the script knows it's running in the Windows Terminal, it uses fancy emojis. If not, it uses legacy emojis pulled from Code page 437. At this point, using !!process.env.WT_SESSION to detect this just seems like a weird hack that isn't being used for its true purpose.

See https://github.com/sindresorhus/figures/pull/27#issuecomment-504764201

I need at least a thumbs up from a collaborator for this repository that WT_SESSION will be sticking around for a long time and that I can confidently rely on it.

gerardog commented 4 years ago

Environment variables are not a perfect solution since you can 'start cmd' and that will open an old ConHost with WT_SESSION set.

Tyriar commented 4 years ago

@DHowett-MSFT for basically every other nix terminal and many on Windows, you can look at TERM_PROGRAM to see what terminal the app is being run within, but now anything that does this also needs to check WT_SESSION as well? And what if another terminal is launched from WT, then you have both TERM_PROGRAM and WT_SESSION so it's impossible to tell which value was set by the "inner" terminal (WT might create a fresh env block in which case this might not apply).

This feature was inspired by both Terminal.app (the stock terminal emulator on OS X) and its featureful replacement, iTerm2. There's no new and divergent art here.

You say it's inspired but why not do exactly what they did which is extend the TERM and TERM_PROGRAM variables with exactly what they did; adding TERM_SESSION_ID? imo you should replace WT_TERMINAL with TERM_SESSION_ID, add TERM_PROGRAM and TERM_PROGRAM_VERSION as there is already a standard and there is zero reason AFAICT to deviate from it.

DHowett-MSFT commented 4 years ago

It is invalid to consider a terminal that does not set TERM_PROGRAM and TERM_PROGRAM_VERSION wrong. It stands, then, that any terminal started from another terminal that has set TERM_PROGRAM will inherit that value, and confuse all downstream shells.

There is no standard for session IDs: at my last check, Apple's Terminal.app used TERM_SESSION_ID and iTerm2.app uses ITERM_SESSION. Perhaps that has changed.

Tyriar commented 4 years ago

that any terminal started from another terminal that has set TERM_PROGRAM will inherit that value, and confuse all downstream shells.

The new terminal sets the value when it starts the process, so no confusion.

There is no standard for session IDs: at my last check, Apple's Terminal.app used TERM_SESSION_ID and iTerm2.app uses ITERM_SESSION. Perhaps that has changed.

Looks like iterm made a mistake and can't break backwards compat (iterm left, terminal.app right):

Screen Shot 2020-01-15 at 12 03 10 PM
Tyriar commented 4 years ago

Join us

Screen Shot 2020-01-15 at 12 12 52 PM
gerardog commented 4 years ago

This should be set in both Windows Terminal and the windows built-in ConHost, to minimize the 'false positive' scenarios. I am pretty confident that other terminals will join too (Cmder/ConEmu,etc).

DHowett-MSFT commented 4 years ago

There's a problem with that one, too. conhost cannot set an environment variable in the process it's hosting, because it is actually spawned BY the process it is hosting. That's just not a capability that's afforded to Windows applications. ConEmu supports two launch modes- one where it launches the shell and the conhost and attaches to the conhost, and one where it attaches to an existing conhost. It will not be able to set environment variables in the second case.

There's a lot more issues here than may initially meet the eye.

eryksun commented 4 years ago

There's a problem with that one, too. conhost cannot set an environment variable in the process it's hosting, because it is actually spawned BY the process it is hosting.

The Windows team could modify the allocate/attach code in kernelbase.dll to query the console host name and version and set those environment variables.

garyo commented 4 years ago

So as a user, to get 24bit support in apps in WSL with Windows Terminal, is this the recommended method:

[[ -n "$WT_SESSION" ]] && export COLORTERM=24bit

at least for now?

DHowett commented 4 years ago

Definitely not. Client of Terminal will want to use the same means of detecting 24-bit color they were using for years before Windows Terminal came out. The traditional Windows console host has supported 24-bit color for some time now.

garyo commented 4 years ago

OK @DHowett -- what is the recommended method for a user then? I have a number of Linux utilities that assume that a 24bit terminal sets COLORTERM (they may have other methods I don't know about). They do not currently autodetect 24-bit support in Windows Terminal, even though it does support it. When I add COLORTERM=24bit they work OK. Is there some alternative method I should use?

DHowett commented 4 years ago

So, COLORTERM should be safe to set for all terminals on Windows as of 1803. No need to check WT_SESSION, just set it if you're using WSL at all. :smile:

garyo commented 4 years ago

I guess that's what I mean. I have a .bashrc which I use on Windows, Linux (incl WSL) and Mac. I want it to work everywhere. So I can either check that I'm on Windows (but then I still might be in Msys using some term emulator), or just check for WT_SESSION. I do think it would be nice if Windows Terminal would just set COLORTERM like many other terminal apps (terminator, iTerm2, konsole, hyper, etc.).

DHowett commented 4 years ago

Fair request.

I would, though, hope that iTerm/Terminal.app and whatever terminal emulator you use on Linux would support 24-bit color by now. Perhaps if TERM == xterm-256color, you can set it?

heaths commented 4 years ago

Would it make more sense, then, to just have conhost and openconsole define TERM even if they are "xterm-256color" assuming ENABLE_VIRTUAL_TERMINAL_PROCESSING is enabled?

DHowett commented 4 years ago

WSL already does this.

image

garyo commented 4 years ago

Sure, that's reasonable. It's likely most terminal emulators claiming 256-color support actually support 24bit at this point. There's a list at https://gist.github.com/XVilka/8346728 if anyone's interested.

heaths commented 4 years ago

WSL does, yes, but that doesn't help my many PowerShell scripts (cross-plat, or Windows-only) where emitting vterm sequences would be easier than chaining Write-Host with various -ForegroundColor or -BackgroundColor parameters.

musm commented 4 years ago

Just chiming in that in my case, we have a program that probes COLORTERM and checks if it it's 24-bit or 256 to determine which color mode to enable.

I'm still confused/unclear on how to go about this for Windows users?

Should we just uniformly assume a 24-bit terminal if WT_SESSION is detected? (That doesn't seem right because 24-bit colors are supported by just launching cmd.exe directly so this test would fail for this case)

Or is it better to probe the console mode to confirm ENABLE_VIRTUAL_TERMINAL_PROCESSING is set (not ideal, extra code for this)

musm commented 4 years ago

Is it safe to emulate by setting TERM=xterm-256color if console mode has ENABLE_VIRTUAL_TERMINAL_PROCESSING set?

zadjii-msft commented 4 years ago

Is it safe to emulate by setting TERM=xterm-256color if console mode has ENABLE_VIRTUAL_TERMINAL_PROCESSING set?

That's certainly the TERM that we've been aiming to emulate, yea. If you can set ENABLE_VIRTUAL_TERMINAL_PROCESSING, then you should assume that the Console (and terminal) will be able to support 256/rgb colors. There's like, 1 build of Windows 10 (RS1, 14393 I think) where that won't work for you, but that was also just about 4 years ago, so I wouldn't worry about that too much.

garyo commented 4 years ago

Would be great if there were a built-in env var or a way to do this query without having to write a separate binary. Maybe Windows Terminal could ship with this little utility?

tracker1 commented 4 years ago

More details on color support

mixmastamyk commented 4 years ago

Just a note that I've recently discovered that the modern terminfo name for terminals that support direct, aka "true" color is TERM=xterm-direct not TERM=xterm-256color .

In fact a number of terminals have -direct aliases. To compare them:

⏵ infocmp xterm-256color xterm-direct
DHowett commented 4 years ago

Unfortunately, until we land #4321 we're actually +indirect 😦 (since we use the legacy syntax popularized by a misreading of the direct color spec!)

mixmastamyk commented 4 years ago

Yes, got it. Since the comment was meant as more of a goal than a current status, it shouldn't be in conflict. Simply a note that, while in most threads folks are mentioning TERM=*-256color, those profiles have been surpassed for a number of years.

dropsonic commented 3 years ago

Please also make a PR to supports-hyperlinks that is intended to detect embedded hyperlinks support. Right now it is not possible to detect that Windows Terminal has v1.4 or higher so it is not possible to properly implement the terminal&version check.

Delta456 commented 3 years ago

It will be handy to have COLORTERM environment variable to detect true color support.

potatoqualitee commented 3 years ago

Excellent and useful additions, thank you so much.

heaths commented 3 years ago

@dropsonic why would detection be necessary? If vterm sequences are implemented correctly - and according to discussions for hyperlink support, Terminal is - if older Terminals don't support it hyperlinks will just show up as text (the URL, that is).

dropsonic commented 3 years ago

@heaths thanks for pointing it out, will try