Skip to content

blessed 1.42 curses and singleton-free update - #41

Merged
vxgmichel merged 19 commits into
vxgmichel:mainfrom
jquast:jq/blessed-1.40-integration
May 25, 2026
Merged

blessed 1.42 curses and singleton-free update#41
vxgmichel merged 19 commits into
vxgmichel:mainfrom
jquast:jq/blessed-1.40-integration

Conversation

@jquast

@jquast jquast commented May 22, 2026

Copy link
Copy Markdown
Collaborator

Integrate with blessed 1.42, removes REMOTE_TERMINAL_TYPE = "xterm-256color".

  • blessed no longer imports the python 'curses' module, now it always depends on the "curses-free" replacement library, jinxed
    • previously only required for windows platform, for legacy ConHost.exe compatibility, it is now used for all python platforms.
    • jinxed is "Singleton-free"
    • this allows unique terminal capability initialization per process
    • and also to support initializing with TERM=rio, foot, contour, kitty, ghostty, et al. without requiring their capability database installed on the system.
    • (but it is of little actual effect to gambaterm, as it uses very few capabilities and the 'xterm-256color' fallback is perfectly fine. This is also the new default fallback in blessed)
  • small non-fix, we set term.number_of_colors when cycling with TAB key, although no blessed color capabilities are used at this time.
  • small bugfix that telnet server did not forward use_cpr_sync config

Also,

jquast added 6 commits May 22, 2026 11:57
Integrate with blessed 1.42, since 1.40, blessed no longer imports the
python 'curses' module, depending on the "curses-free" replacement
library, jinxed, as documented here:
https://jinxed.readthedocs.io/en/stable/capabilities.html#singleton-free

jinxed is "Singleton-free", allowing initialization of ~50 of the most
common types of terminal capability databases in the same process,
including those supporting kitty protocol, TERM=rio, foot, contour,
kitty, ghostty, et al. without requiring an up-to-date terminfo(5)
capability database on the host.

This requires overriding the ``blessed.Terminal.__init__streams()``,
a sub-call of `blessed.Terminal.__init__()`, to "connect" the streams at
the right time before the other sub-call of ``__init__()`` to
``__init__xtgettcap()``, allowing XTGETTCAP to define preferred TN
terminal name, and 24-bit color support, and a few minor capabilities
like 'blink' not otherwise used , https://github.com/jquast/blessed/blob/master/blessed/_capabilities.py#L192

This resolves COLORTERM not being SendEnv'd over ssh. Many terminals
support reporting "RGB" value over XTGETTCAP: contour, foot, ghostty,
rio, and wezterm among kitty keyboard protocol supporters.

Terminals supporting kitty keyboard protocol that do not support
XTGETTCAP are:

 - zellij, no support zellij-org/zellij#4320
 - alacritty, refuses support https://github.com/alacritty/vte/issues/980
 - kitty, does not report 'RGB' for any reason
 - libvterm, no support https://github.com/neovim/libvterm/blob/934bc2fbf21800ac3458a499df8820ca5fb45fd3/doc/seqs.txt#L230
 - xterm.js (proposed xtermjs/xterm.js#4107)
also, no such thing as "unknown" terminal (blessed handles it)
@jquast jquast changed the title blessed 1.40+ curses/singleton-free update blessed 1.42 curses and singleton-free update May 22, 2026
@jquast
jquast marked this pull request as ready for review May 22, 2026 23:06
@jquast
jquast force-pushed the jq/blessed-1.40-integration branch from 588a833 to 6b8d93e Compare May 23, 2026 20:36

@vxgmichel vxgmichel left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

A couple of comments here and there, LGTM otherwise 👍

Let me know when you're done, and I'll take it from here.

I'll try to finish my work on #40 in the next couple of days, so I can make a release and deploy on a new demo server, I'll let you know how this goes.

Thanks again for your help :)

Comment thread gambaterm/colors.py
Comment thread gambaterm/remote_terminal.py
Comment thread gambaterm/remote_terminal.py Outdated
Comment thread gambaterm/run.py Outdated
Comment thread gambaterm/ssh.py
Co-authored-by: Vincent Michel <vxgmichel@gmail.com>
@jquast

jquast commented May 24, 2026

Copy link
Copy Markdown
Collaborator Author

All set, good luck with the demo server! I think we're both heading towards the same goal :)

I'd like to see a small "frontend", like telnet nethack.alt.org dgamelaunch, to pick a game, edit settings, watch other player's games, etc.

But it really needs an audio protocol! https://gist.github.com/sopyb/ec682c9dbb1899f70039b6e81b0b546c

@vxgmichel
vxgmichel force-pushed the jq/blessed-1.40-integration branch from 336ddb3 to 4a09a5c Compare May 25, 2026 08:29
@vxgmichel
vxgmichel merged commit 1287f8f into vxgmichel:main May 25, 2026
8 checks passed
@vxgmichel

Copy link
Copy Markdown
Owner

I'd like to see a small "frontend"

That's a very good point. I think I'll add a common frontend callback to both ssh and telnet server, so one can easily write custom frontends for specific needs (the demo server is definitely one of those).

watch other player's games

Oh I haven't thought of that, that'd be really cool.

I have continued to enable 24-bit color unconditionally for ssh and telnet, even though we can more accurately identify it with XTGETTCAP, because it would cause the following kitty keyboard supported terminals to fail to report 'RGB' or detect 24-bit color support [...]

I was thinking about this. Now that blessed uses the jinxed database, isn't it very reliable to detect color support? Instead of using 24-bit color unconditionally, we could use term.number_of_colors right? Unless there are some cases where ssh and telnet clients do not report TERM correctly?

@jquast

jquast commented May 25, 2026

Copy link
Copy Markdown
Collaborator Author

I have continued to enable 24-bit color unconditionally for ssh and telnet, even though we can more accurately identify it with XTGETTCAP, because it would cause the following kitty keyboard supported terminals to fail to report 'RGB' or detect 24-bit color support [...]

I was thinking about this. Now that blessed uses the jinxed database, isn't it very reliable to detect color support? Instead of using 24-bit color unconditionally, we could use term.number_of_colors right? Unless there are some cases where ssh and telnet clients do not report TERM correctly

sadly, not, because I believe of integer size limitations, or legacy compatibility of other sorts, the “colors” capability string is limited to 256. See for example “alacritty”, https://github.com/Rockhopper-Technologies/jinxed/blob/536505505e2d52d6073c8548408305b4fbb71ccb/jinxed/terminfo/alacritty.py#L27

though, blessed can probably make some exception rule about contour, rio, alacritty, kitty, and ghostty TERM types can also set 24-bit color.

@vxgmichel

Copy link
Copy Markdown
Owner

I see. I was surprised that the terminfo database does not contain information about true color support, and while looking for more information I ran into the -direct suffix, as in xterm-direct.

That made me realize that blessed 1.40 introduces a regression:

% uv pip install blessed==1.39 && COLORTERM="" TERM="xterm-direct" uv run python -c "import blessed; print(blessed.Terminal().number_of_colors)"
16777216
[vinmic:~/repos/test-blessed]
% uv pip install blessed==1.40 && COLORTERM="" TERM="xterm-direct" uv run python -c "import blessed; print(blessed.Terminal().number_of_colors)"
256

Note that I had to install ncurses-term to have the corresponding terminfo file.

Is that something we should report in jinxed? Or is it something that is not supported on purpose?

@jquast

jquast commented May 25, 2026

Copy link
Copy Markdown
Collaborator Author

Yeah, it's a bit of a grenade!

no single terminal emulator is configured by default to use the "-direct" TERM variant, and I have not found any recommendation to use it. I collect 'TERM' environment values on public telnet and ssh servers, and I have never yet seen any use of -direct, not even once! I often forget it exists, though I did rediscover and redecide again to ignore it when I last updated jinxed.

jinxed could very easily support them, just add to terminals.toml and regenerate. I have found some desire to use python in constrained environments (like micropython), and I have been more mindful about "code generation abuse", to chose to support the 99.9% uses for 10% of the size -- the full termcap.src file could create megabytes of python code, certainly thousands of files.

However, I can do some analysis that if TERM="*-direct" is used, we can probably safely assume 24-bit color, it is harmless enough, and, also that DECRQSS is recommended by some others instead of the RGB XTGETTCAP, I have already collected data for 40 terminals about this, so you have inspired me to generate a new chart "Truecolor detection" for https://ucs-detect.readthedocs.io/results.html so look for that soon, but the summary is: every terminal that reports RGB via XTGETTCAP also supports at least one other method, and, only cmd.exe and windows Terminal.exe supports only DECRQSS.

Blessed currently hardcodes truecolor support by the local windows platform build version, so that fixes them for local execution, but you have helped me discover this is necessary for remote detection, so i will propose to add that to blessed and here, to be able to detect Terminal.exe over ssh is important.

@jquast
jquast deleted the jq/blessed-1.40-integration branch May 25, 2026 16:34
@jquast

jquast commented May 25, 2026

Copy link
Copy Markdown
Collaborator Author

Created jquast/blessed#386

@vxgmichel

vxgmichel commented May 25, 2026

Copy link
Copy Markdown
Owner

Oh very interesting. There is one thing I don't understand tho:

To my understanding, the terminfo definitions are split between, say, kitty and kitty-direct because an old application might no be able to parse colors#0x1000000 properly. So it's safer to use TERM=kitty, but one can use TERM=kitty-direct to ignore this risk:

± infocmp kitty-direct | grep colors#
	colors#0x1000000, cols#80, it#8, lines#24, pairs#0x10000,

But in the case of jinxed, the terminfo database is embedded and directly exposed using python. So in this case there is no reason to "lie" about the true color capability of the terminal right? Why not use terminals.toml to patch the terminal emulators that do support true color with 'colors': 0x1000000?

@jquast

jquast commented May 25, 2026

Copy link
Copy Markdown
Collaborator Author

yes I think you are right, we already patch away or correct legacy capabilities, described in section https://jinxed.readthedocs.io/en/stable/capabilities.html#missing-legacy-codes

It's probably OK to also patch colors values with terminals known to support it.

@jquast

jquast commented May 25, 2026

Copy link
Copy Markdown
Collaborator Author

and yes, it is legacy (16-bit!) application compatibility for the reason that 'colors' could not be larger than 32768, the termcap database file can be in 32-bit encoding, a few of them are, https://github.com/jquast/ttyscan/blob/master/ttyscan.py#L510

@vxgmichel

vxgmichel commented May 25, 2026

Copy link
Copy Markdown
Owner

All set, good luck with the demo server!

It's up and running at gambaterm.vxgmichel.xyz with both telnet and ssh if you want to give it a try 🎉

You'll have to type not@bot for ssh authentication, but I should probably add a robot check instead like we have for telnet. Maybe not having a password at all will discourage bots from trying to brute-force it. I tried to configure my service to not run the container at all when no one is accessing it to save a bit of money, but it seems pretty naive in retrospect, since I have about 1.5 bots connected at any time on average..

Also no custom frontend for the moment, but as a first step I would like for terminal emulators that don't support the kitty keyboard protocol to fallback on playing a tool assisted speedrun instead. That means I'll have to detect the number of colors supported remotely (hello XTGETTCAP) :)

@jquast

jquast commented May 25, 2026

Copy link
Copy Markdown
Collaborator Author

Great!

I did just find a possible ghostty bug: if I press and hold a direction key, then alt+tab, then return, the "RELEASE" event appears to never be transmitted, I have to press the same key again to get a RELEASE event to make it stop repeating while I'm in another window. ghostty is really hard to build and work with, it's a zig language i know nothing about

@jquast

jquast commented May 25, 2026

Copy link
Copy Markdown
Collaborator Author

It looks really great. I ran an ssh and telnet simultaneously, they both jitter or delay a few dozen frames now and then, that's just realtime packets on internet at work, but its almost imperceptible.

gambaterm-ssh.mp4

@jquast

jquast commented May 25, 2026

Copy link
Copy Markdown
Collaborator Author

Also of note, that Ctrl+]quit\r and \r~. to disconnect from telnet and ssh clients do not work, because of the kitty mode enabled but that's for the better, you want clients to press ^C so we can send them a goodbyte "disable kitty mode" sequence. But it is an interesting thought, that you can make a client unable to disconnect ..

@vxgmichel

Copy link
Copy Markdown
Owner

ghostty is really hard to build and work with, it's a zig language i know nothing about

Yea it took me a while to rebuild the project when I was reporting Report IntlBackslash as < alternate key

I ran an ssh and telnet simultaneously, they both jitter or delay a few dozen frames now and then, that's just realtime packets on internet at work, but its almost imperceptible.

Great! I'll think I'll add a delay measurement to the window title, this can be done by counting the number of CPR that are currently in flight. Also note that I changed the demo server ports to 22022 and 23023, so that my remote machine can be suspended most of the time. I might revert this later but for the moment it's fine to use custom ports.

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.

2 participants