Skip to content
This repository was archived by the owner on Jul 10, 2026. It is now read-only.

Releases: RaphGL/TermCL

TermCL 0.10

Choose a tag to compare

@RaphGL RaphGL released this 05 Mar 13:23

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

Choose a tag to compare

@RaphGL RaphGL released this 10 Feb 17:43

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_font to the sdl3 backend
  • Added set_font_from_slice to 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_input returning true when no valid input was able to be parsed
  • Fixed input handling on sdl3

Changes

  • the read_raw and read_raw_blocking functions have had their input changed from []byte to string to better reflect what is the actual type and for better consistency between the sdl and terminal backends

TermCL 0.8

Choose a tag to compare

@RaphGL RaphGL released this 05 Oct 18:52

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_buffer dispatching wrong escape code for disabling the alternate buffer

TermCL 0.7

Choose a tag to compare

@RaphGL RaphGL released this 08 Sep 19:53

Fixes

  • Fixed reset_styles not working properly with the new optimizations

Additions

  • Added get_window_size, this should be preferred over get_term_size whenever possible
  • Added resize_window

TermCL 0.6

Choose a tag to compare

@RaphGL RaphGL released this 27 Aug 22:49

Breaking Changes

  • set_color_style_* functions were all removed and instead there's now a single set_color_style. With this a new Any_Color union type was introduced, so now the function can accept any color value supported
  • RGB_Color was renamed to Color_RGB for consistency
  • get_term_size no longer receives a ^Screen as an argument, thus no longer forcing people to store screen just to call this function

Additions

  • Added the termcl/raw package which unlike the termcl package, it provides little abstraction over the escape codes, it simply writes all escape codes to a strings.Builder which 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

Choose a tag to compare

@RaphGL RaphGL released this 21 Jul 23:26

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

Choose a tag to compare

@RaphGL RaphGL released this 09 Jul 22:06

Breakages

  • Input_Seq was renamed to Keyboard_Input for consistency with Mouse_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 pressed when the key was None

TermCL 0.3

Choose a tag to compare

@RaphGL RaphGL released this 12 Jun 13:27

Added

  • Added window_coord_from_global and global_coord_from_window so 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/ansi got moved to terminal/ansi)

Changes

  • set_color_style_rgb has been changed to set_color_style_rgb :: proc(win: $T/^Window, fg: Maybe(RGB_Color), bg: Maybe(RGB_Color)) so that it's consistent with set_color_style_8 and 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

Choose a tag to compare

@RaphGL RaphGL released this 30 May 23:20

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

Choose a tag to compare

@RaphGL RaphGL released this 30 May 14:53

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.