Releases: RaphGL/TermCL
Release list
TermCL 0.10
Since we target the latest Odin tagged release and Odin's core:os/os2 has become core:os, I'm making a new release so that the library is still compatible.
Other than that, I've renamed termcl/sdl3's get_font_from_slice to get_font_from_bytes to be more inline with the core library's naming convention. I've also added signal handling for Windows and POSIX compatible systems, the signal handling is necessary to be able to properly recover the terminal once the process is killed, if this is not done you might or might not end up with a weird behaving terminal depending on how your terminal behaves.
TermCL 0.9
It's been a while since the last release. The core TermCL library is pretty much done at this point. The only reason for pushing out new updates is to fix bugs, resolve breaking changes in Odin itself or to add extra features that most people might not need to begin with :)
though if I think of something that will improve memory usage or performance I will do it
SDL3
Previously I added the ability to add custom backends, as an experiment I added an SDL3 backend that wasn't polished but that mostly seemed to work. People couldn't try it before because I was hard coding a mono font on my system, but I've now added a set_font and set_font_from_slice which allows to load fonts you've embedded with the #load directive.
Aside from that I've also worked on ironing out the input handling so that it's mostly in parity with the one in the regular terminal backend one. I bet there are still some small differences between the two but it's in a usable state now. So if you want to try making a TUI that works both on a terminal and as a GUI or you just want to make a GUI that looks like a TUI, feel free to give it a shot and let me know if you run into issues.
Terminal
On the terminal backend side things are very stable but parsing input is painful due to the many different ways different terminals choose to report different sets of keys. So for the most common terminals out there things should be working just fine. But people have reported minor issues and I've fixed those.
The library doesn't yet work on systems outside of Windows, MacOS and Linux, but that's solely because we need a way to get the terminal
cell size and change the terminal mode but this requires making a ioctl syscall and I haven't gone in and added those for other platforms. If you want to use this library on FreeBSD, OpenBSD and others, you only need to add these two things (if it's a posix system we only need to add get_term_size). I'm open to contributions for that, but if not, I'll still add them eventually.
Widgets
Odin doesn't have a TUI widgets library like others languages have. I do intend to build one built on top of TermCL eventually.
The current widgets package doesn't even work with the current version of TermCL as its been abandoned, because the odin community seems to prefer immediate mode APIs and I was doing a form of retained mode. So I will have to rethink my approach.
Additions
- Added
set_fontto the sdl3 backend - Added
set_font_from_sliceto sdl3 backend, allowing to load fonts that were embedded with#load
Fixes
- Fixed ctrl modifier not being identified for enter and backspace keys on the terminal backend
- Fixed
parse_keyboard_inputreturning true when no valid input was able to be parsed - Fixed input handling on sdl3
Changes
- the
read_rawandread_raw_blockingfunctions have had their input changed from[]bytetostringto better reflect what is the actual type and for better consistency between the sdl and terminal backends
TermCL 0.8
Breaking changes
Redefining Inputs
Manually parsing keyboard and mouse input is annoying, it also makes adding custom backends harder due to it being tied to how terminals process the inputs rather than just the inputs being given. So I've changed the signature for both read and read_blocking. They still return an Input but it's been redefined to:
Input :: union {
Keyboard_Input,
Mouse_Input,
}This makes it easier to use but it also makes it easier to extend to other backends as well.
If for some reason you still need to access the raw bytes returned from the terminal, use the raw variants: read_raw and read_raw_blocking acessible through the termcl/term package. This package also contains the parse_mouse_input and parse_keyboard_input functions so that you can still convert raw input into Input.
Custom backends
As was hinted before, the addition of cell buffers allowed for the potential use of custom backends to render to other targets, such as other escape code standards or GUIs. For now I'm adding an SDL3 backend so that TUIs can be ported to GUIs. There's still some ironing out to do so there might be some different behavior between the terminal and the backend, but as long as you test your code on both TUI and GUI, it shouldn't be too big of a problem.
How it works
The library uses a VTable with implementations for backend specific stuff. This VTable looks like this:
Backend_VTable :: struct {
init_screen: proc(allocator: runtime.Allocator) -> Screen,
destroy_screen: proc(screen: ^Screen),
get_term_size: proc() -> Window_Size,
set_term_mode: proc(screen: ^Screen, mode: Term_Mode),
blit: proc(win: ^Window),
read: proc(screen: ^Screen) -> Input,
read_blocking: proc(screen: ^Screen) -> Input,
}You set it by calling the set_backend function:
set_backend :: proc(backend: Backend_VTable) {Or by just passing the backend's vtable when calling init_screen.
All you have to do is import the backend you want to use and call it's own set_backend function. For current users, the only modification they need to do is to import termcl/term and call term.set_backend() and everything should keep working as it was before.
For people attempting to use the SDL3 backend, if you're were previously doing "frame capping" by using a timer, be aware that that will screw up the event handling on SDL3, so you should do everything besides the rendering on another thread if that is the case (like you would normally do for any SDL3 program). Other than that, most programs can easily be rendered as a GUI by just swapping the backend.
Additions
- Added SDL3 backend
Fixes
- Removed generics to rely on subtyping instead so that the binary size of the library is smaller
- Fixed
enable_alt_bufferdispatching wrong escape code for disabling the alternate buffer
TermCL 0.7
Fixes
- Fixed
reset_stylesnot working properly with the new optimizations
Additions
- Added
get_window_size, this should be preferred overget_term_sizewhenever possible - Added
resize_window
TermCL 0.6
Breaking Changes
set_color_style_*functions were all removed and instead there's now a singleset_color_style. With this a newAny_Colorunion type was introduced, so now the function can accept any color value supportedRGB_Colorwas renamed toColor_RGBfor consistencyget_term_sizeno longer receives a^Screenas an argument, thus no longer forcing people to store screen just to call this function
Additions
- Added the
termcl/rawpackage which unlike the termcl package, it provides little abstraction over the escape codes, it simply writes all escape codes to astrings.Builderwhich you can then write to the terminal - Improved performance: release builds are now 400% faster
- Added fire animation example #22 (by @via-dev)
- Added a wiki
Fixes
- Made windows retain internal state about color and text styles so that they avoid
TermCL 0.5
This is a very minor release. Just to ensure that the library is usable on Windows :(
Fixes
- Fixed missing import on Windows
Added
- Added alt detection to
parse_keyboard_input
TermCL 0.4
Breakages
Input_Seqwas renamed toKeyboard_Inputfor consistency withMouse_Input
Additions
- Added missing symbols in
parse_keyboard_input:<,>and? - Added MacOS syscall to get terminal size
Fixes
- Fixed windows of size 0 causing a floating point exception in runtime
- Fixed mouse input events being
pressedwhen the key wasNone
TermCL 0.3
Added
- Added
window_coord_from_globalandglobal_coord_from_windowso that cursors can be converted from and to window coordinates. This can be used to leverage the Window isolation to create your own custom widgets or to check that the mouse is hovering inside of a window.
Fixes
- Cbreak and Raw modes now draw to an alternate screen buffer. Preserving user terminal content and preventing undesirable scrolling in these modes on Windows.
- Fixed library not compiling on Odin 2025-06 due to breaking change in the odin compiler (
encoding/ansigot moved toterminal/ansi)
Changes
set_color_style_rgbhas been changed toset_color_style_rgb :: proc(win: $T/^Window, fg: Maybe(RGB_Color), bg: Maybe(RGB_Color))so that it's consistent withset_color_style_8and also so that fg can be set to default
Aside from these the library technically now introduces widgets under termcl/widgets but it's not advised to use them just yet unless you just want to test them or contribute changes/improvements.
At the moment only button, panel and progress widgets have been written.
TermCL 0.2
Release of shame.
This fixes a typo in the source code that was raising an error and also improves performance by avoiding allocations and printf
TermCL 0.1
This is the first "stable" release. Going forward I'll attempt to not break the API and will only do so if necessary. (though the library API has barely changed so far as it is)
Going forward what I want to do is to keep fixing bugs, improving platform compatibility if necessary and creating a widgets library on top of it using the windows as an abstraction.