Use colors to show terminal context in Prompt
This has been shortened into a possible feature request: #233
Idea
I'd like the text color scheme of my Prompt tab to show the terminal that's receiving the commands.
I'd have a much easier time telling my Fedora container from my Ubuntu container if one appeared in bluish colors and the other brownish. And it would be fantastic if that could just switch automatically when logging in.
Here's an example... When I start Prompt on the host, I would see something like this:
Then, when I drop into the Fedora container, the window automatically changes to that container's colors.
And, when I switch over to the Ubuntu container, the palette changes again.
Finally, when I log into a remote host, the palette switches to make that blindingly obvious.
The more terminals you have open, the more useful this feature would be.
Possible Implementation
Prompt currently changes the tab title to match the remote hostname. Could it also use the hostname to set the palette?
For example, let's say I log into my wolfi container... When Prompt sets the window title to "bronson@wolfi", it would also look to see if I've specified any palettes for a host named "wolfi"...
If so, it applies it, and my tab suddenly switches to a pinkish/purpleish appearance.
If not, no problem. My tab would display in the Profile's default palette, exactly as Prompt works now.
To implement this, Prompt would need to know how to match hostnames to palettes. I picture this information being contained in a set of config files. We'll go into more detail about configuration later (count on it...) but, for now, let's stay at a higher level.
UI Changes Necessary
I picture adding a button, "Allow hostname to specify palette":
This would allow the user to turn the feature on and off.
If the user clicks on "specify palette" then Prompt would dispaly a documentation page describing how to configure the hostnames. (This is just to keep this implementation simple. In the future, this might be a button that brings up a user interface dedicated to assigning hostname-to-palette mappings, but we'll leave that can of worms closed for now)
To summarize, the user-visible parts of feature would be:
- the mentioned off/on button
- a set of config files to provide the hostname-to-palette mappings.
Antifeatures
Here are some additional features that, while well-intentioned, shouldn't be part of this implementation at this time. Keep it simple.
Recognize user as well as host?
In addition to the hostname, the remote also specifies a username. Why not make the palette change based on the username as well? That way, when you become root, the visual style would switch to something appropriately ominous.
Answer: this adds another layer of complexity. If a user specifies one palette for a username and another for the hostname, what happens? One always override the other? That would be confusing and lead to a sense of unreliability. Mix them? That'd look awful.
For now, the palette should correspond to the host receiving the terminal input.
Wildcard matches?
What if I want the fedora-cli, fedora-test, and fedora-stock containers to all show in Fedora blue? I could specify "*fedora*: blue
instead of needing to enumerate each individual hostname.
This adds some ambiguity to the mix, where now you need to deal with better and worse matches. What regex style? How about capturing?
If the need for this arises, it could probably be added in the future, but this need should probably show itself first.
Rejected Implementations
The current suggestion is to have Prompt set the palette based on hostname escape codes. There are other ways to implement this feature too. Here are some ideas.
Host explicitly tells Prompt the palette to use
I actually like this idea a lot. Instead of using a set of configuration files on my computer to tie hostnames to palettes, each host could suggest the palette to use itself, using an escape mechanism similar to the username/hostname that they currently send.
Each container would come with its suggested palette already baked-in. So simple! No need for local configuration and coordination. Just display it in the palette it asks for.
The issue is that this would need changes to be made to every container and every remote host before it would be useful. For now, it's easier to keep this feature within Prompt and use terminal escape codes as they exist today.
Prompt introspects container to find the desired color
Prompt could reach into the container and read color information out of a file like /etc/os-release
. This would be an easy and consistent place to place the desired palette.
The downside of this is that it wouldn't work for remote hosts.
Set the palette when launching prompt
Why not just use Prompt's existing --tab-with-profile=PROFILE
argument to specify a profile with the appropriate palette? Right now there's nothing stopping you from specifying a blueish profile when opening a tab onto a Fedora container, and so on.
This stops looking so attractive once you starting bouncing between hosts. If I launch a terminal on the local host, then enter a container, the palette will be wrong. And confusing.
Relying on the command line arguments would also require you to only log into containers and remote hosts by opening new tabs -- an irritating limitation. And it would get difficult to keep your keyboard shortcuts, aliases, and .desktop files in sync with your containers, all specifying the same palettes.
The palette needs to correspond to the remote host, not the local tab.
Existing Features
Would this idea conflict with anything Prompt is currently doing? Short answer: not really.
Prompt already shows a scarf when logging into a remote host. This is good, and there's no reason to change it.
The scarf probably can't be used as a basis for this feature, however. If I open a Prompt tab to a container, I see the container scarf. Good! However, when I log from there into a remote host, the scarf remains the container scarf. There's no indication that I'm typing at a remote host:
In addition, changing the scarf and the window border color don't really offer much in the way of visibility or contrast. They're good, but they're too subtle to be used for this feature.
Risks
Let's consider some ways this feature could be misunderstood or misused.
Reliability / Accuracy
To ensure a decent user experience, each environment must consistently display in its assigned color. For example, it should not matter if I ssh into a remote host from my blueish Fedora container, or my reddish Ubuntu container -- the remote host needs to always display in its own, say greenish, color.
If the host colors are unreliable, then this feature would be misleading and confusing, not useful.
Complexity
If this feature is too difficult to use, people won't use it.
For example, if I need to open Prompt's preeferences to manually assign a colorschme to every container currently on my machine, plus every remote host that I might use, I'll probably give up right there. Even if I did manage to get through that once, I wouldn't keep up with all the containers appearing and disappering in my life.
Therefore, it must come with some sensible defaults, and allow easy user customization.
Untrusted Data
The remote host might be untrustworthy... Could it send an escape sequence that could cause buffer overflows? Or, even crazier, change my profile so that attacker-controlled commands are run on my local computer?
This proposal only reads a hostname string from the remote computer. All configuration is done locally. The worst that can happen is either matching or not matching the palettes that I already have installed, neither of which increases the attack surface appreciably.
It should be reasonably straightforward to implement this feature securely.
That said, could the mere presence of this feature be a liablity?
Malignant Actors
In theory, if sending a terminal sequence can change the colorscheme, someone could fool Prompt into displaying the wrong colorscheme and causing an accident.
- I fire up a Prompt window, dispalying my host's calm colorscheme.
- I ssh into important-colo-box, so now Prompt displays a vibrant red colorscheme indicating that I need to be careful.
- An enemy agent, logged into the remote host and without permission to run executable commands, finds the pty I'm using. He uses a shell builtin "echo CHANGE-ESC-SEQUENCE > /dev/pty12" to change my window's vibrant red colorscheme back to my typical calm dark.
- I'm about to leave at the end of the day. I see my topmost terminal is calm blue and type
shutdown -h now
. To my horror, my computer doesn't shut down ... and the colo box is no longer responding. - The enemy agent laughs wickedly at the mayhem he has caused, while I hurriedly book the next airline ticket to Iceland to power the colo box back up.
So, technically, maybe? But not really.
If this scenario is a legitimate concern, we could explore some techniques to make this sort of attack more difficult. "attack"
OK, let's bring this home.
Configuration Files
Assuming the user experience is acceptable (see "UI Changes Necessary" above), how should this feature be configured?
At its simplest, it could be a single file specifying hostnames and palette names: ~/.config/prompt/palettes.yml
(I'm using YAML examples just due to inertia... JSON, TOML, CSV, just about any config file format would work.)
hosts:
fedora: 'Seafom Pastel'
ubuntu: 'Paradiso Dark'
aich: 'Alien Blood'
myst: 'Monokai Soda'
This is the minimum viable configuration file for this feature: just map hostnames to built-in palette names. Even if we stop here, this would be a fine start and a useful feature.
Let's consider some additional features that would make life easier for the user...
Multiple Config Files
Distros might want to provide their own mappings. For example, Bluefin includes the fedora
, ubuntu
, and bluefin-cli
container images... they might want to specify some default colors for these containers so the user doesn't need to bother.
Say, in /etc/prompt/palettes.d/bluefin.yml
:
hosts:
'bluefin-cli': 'Night Owl'
Prompt might want to read multiple config files: some from the user, and some from the system. They would be read in order, from most custom to most generic. First match stops and gets applied.
For example, the files might be read in this order:
~/.config/prompt/palettes.yml
~/.config/prompt/palettes/*
/etc/prompt/palettes.yml
/etc/prompt/palettes.d/*
Configuration File Q&A
Here are some more thoughts on how prompt could interact with these configuration files...
Re-read config files?
The user can change these config files at any time. What should Prompt do when the mappings have changed?
For now, it's fine if Prompt only reads the confg files when it's starting up. If you want changes to take effect, you need to restart Prompt.
In the future, Prompt could watch config files for changes, and update itself on the fly to reflect any chagnes.
Prompt-edited config file?
It would be nice if Prompt provided nice UI to set the hostname-to-palette mappings.
It should probably have ownership of a json file where the user could specify their own mappings and overrides. I'd be happy to mock this up if there's interest.
Including other config files?
The user might want to manually another file, or a whole directory of palette mappings:
include:
- "~/.dotfiles/prompt-colors.yml"
- "~/.prompt/palettes/*.yml"
This could potentially added in the future but let's not worry about it now.
Config Files with Custom Palettes?
It would be nice if we weren't restricted to only using built-in palettes. The config file could be extended to be something like this:
hosts:
aich: 'Alien Blood'
myst: 'Supercustom Solarized'
palettes:
'Supercustom Solarized':
Background: '#002B36'
Foreground: '#839496'
Cursor: '#839496'
Color0: '#073642'
Color1: '#DC322F'
Automatically Switch Light and Dark?
This should work the way Prompt does now.
(TODO: how exactly does Prompt implement this now?)
Fallback Palettes?
What about falling back to a less-specialized palette name? Let's say a config file specifies "Tomorrow Night Eighties", but Prompt has never heard of this palette... However, it does know of a "Tomorrow Night". Should it use that? Or should it fall all the way back to the Profile's default palette?
Answer: whatever is simplest to implement. Can always add this later if needed.
Possible Tasks
Here are steps that would implement this feature:
-
implement a yaml reader -
on app startup, read mappings from ~/.config/prompt/palettes.yml
-
when Prompt is changing the name of a tab, and a mapping is found, set the tab's palette too -
Minimum viable product exist. Evaluate this feature. Is it useful and pleasant? -
read config files from all locations, not just one. -
(maybe) monitor config files for changes so no reload necessary
Conclusion
"When I log into a host, I want the color palette of the current tab to change to match."
That's easy to say but opens up a ton of questions. I hope this document helps find a good way to implement this feature. Then everyone can immediately discern which terminals are connected to which hosts, and make their desktops a little more consistent, colorful, and fun.