tty icon indicating copy to clipboard operation
tty copied to clipboard

Terminal dimensions

Open rchog opened this issue 10 months ago • 3 comments

I've been trying to figure out a way to get the dimensions of the current terminal in a sensible (somewhat) cross-platform way. I thought it'd be a fairly easy thing to do and I could try submitting a PR once I have something working, but it's proving to be beyond my skill/knowledge level with OCaml and terminals in general.

However, it seems like a very common thing that people would expect to see in a library like this, so I figured it could merit some discussion at the very least?

AFAIK there's a bunch of ways it could be done, but they all have downsides:

  • CSI DSR (\x1b[6n) should cause a status message ESC[n;mR to be 'printed' to STDIN. I got this kind of working[^1], but this only seems to work for certain terminals. Foot, Alacritty, URXVT and the linux console worked for me while Kitty, Wezterm, xfce-terminal and, surprisingly, xterm didnt.
  • ioctl() through Ctypes works, kind of[^2], but I could not figure out a way to access libc constants in OCaml, so I had to hardcode the value of TIOCGWINSZ, so it's the furthest thing from cross platform.
  • A separate mini-library that just exposes a couple functions to get the terminal size. Probably the most cross-platform and easiest method, but I didn't try it because submitting a PR with a bunch of C seemed like it might not be welcome. If I'd gone with this method, I'd be tempted to do some of the terminal setup/cleanup through C as well, just because IIRC dealing with things like SIGWINCH, SIGINT etc. in OCaml is much harder(?)
  • tputs and/or stty - shelling out to these seems like an easy 'cheat' but I doubt these are available on all platforms.

[^1]: with this hacky monstrosity. I had Base and Stdio opened in these experiments, in case some functions look odd. [^2]: https://gist.github.com/rchog/ac9303c0d6b4d0deb74b006534749722

rchog avatar Mar 24 '24 13:03 rchog

CSI 6n is CPR aka Report cursor position. If you want to use an escape code to get terminal size you use CSI 14, 16 and 18 t. See https://sw.kovidgoyal.net/kitty/graphics-protocol/#getting-the-window-size and https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI--ordered-by-the-final-character_s for details.

kovidgoyal avatar Mar 25 '24 02:03 kovidgoyal

CSI 6n is CPR aka Report cursor position. If you want to use an escape code to get terminal size you use CSI 14, 16 and 18 t. See https://sw.kovidgoyal.net/kitty/graphics-protocol/#getting-the-window-size and https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI--ordered-by-the-final-character_s for details.

Fair, I should've tried that too, though I was under the (apparently false) assumption that moving the cursor to the bottom right and using CSI 6n was the more widely supported method. But after some more experiments just now, it turns out most of the terminals I mentioned as "not working" do give the expected sequences to STDIN with either one - I just had to wait much longer for them. I may be able to hack something together after all nearer the weekend.

rchog avatar Mar 26 '24 03:03 rchog