termbox / termbox2

suckless terminal rendering library
MIT License
364 stars 28 forks source link

FR: support "inline TUIs" #74

Open sullyj3 opened 1 month ago

sullyj3 commented 1 month ago

Currently tb_init always clears the screen and switches to the alternate screen buffer. This means that you can only write TUIs which use the whole terminal screen.

Some TUIs instead operate inline in the shell, rendering below the current command prompt. Fzf is a great example, it provides scripts which allow you to press ctrl-t to get an inline tui for selecting a file path to insert into your command. Another use case is providing dynamically updating progress for a running command, eg loading bars, spinners, etc.

My feature request is an alternate api to tb_init (or a change to the tb_init api) which doesn't clear the screen and doesn't switch to the alternate screen, to support these kinds of UIs.

Is this something you'd be willing to incorporate?

trapexit commented 1 month ago

I think that would be a worthy addition.

adsr commented 1 month ago

Hello, thanks for the FR. I like the idea and agree a separate API or library is the right choice.

I've thought it would be cool to pair this with an alternative to readline, which has a lot of room for improvement IMO. The main alternatives are editline, tecla, and linenoise. I don't know much about the first two, but they appear to be similar to readline. linenoise is tight and simple but IMO lacks some important features, like being able to interleave a prompt with other i/o.

I wonder how useful it'd be without a prompt feature. I'm curious what others think.

If you don't need to support exotic terminals, and you just want to reposition the cursor, you can get by with a few very portable escape codes. Here's a spinner for example:

#!/bin/bash

spinner=('-' '\' '|' '/')
si=0
n=100

printf '\x1b7' # save cursor

while true; do
  s=${spinner[si % ${#spinner[@]}]}
  let si+=1
  printf '\x1b8' # restore cursor
  printf '%s spinning' "$s"
  let n-=1
  test $n -gt 0 || break
  sleep 0.05
done

printf '\x1b8' # restore cursor
printf '\x1b[K' # clear line

echo done