How to get the width of the terminal?

Hi everyone!
What’s the easiest way to get the width of the terminal in Crystal ?

I didn’t have any luck finding any shards that would handle this either.

Thanks in advance!

My libremiliacr library has that. But it might be easier just to copy-paste this snippit somewhere.


lib LibC
    # Bare minimum for the ioctl stuff we need

    TIOCGWINSZ = 0x5413u32

    struct Winsize
      ws_row    : UInt16
      ws_col    : UInt16
      ws_xpixel : UInt16
      ws_ypixel : UInt16
    end

    fun ioctl(fd : LibC::Int, what : LibC::ULong, ...) : LibC::Int
end

# Gets the width and height of the terminal.
def getWinSize : Tuple(UInt16, UInt16)
  thing = LibC::Winsize.new
  LibC.ioctl(STDOUT.fd, LibC::TIOCGWINSZ, pointerof(thing))
  {thing.ws_row, thing.ws_col}
end

height, width = getWinSize

The Winsize struct and ioctrl function might already be in the standard library… I don’t think it was when I wrote this, and I haven’t checked since.

5 Likes

thanks @MistressRemilia , this works great!

1 Like

This works on MacOS and BSD’s as well:

{% if flag?(:linux) %}
  TIOCGWINSZ = 0x5413u32
{% elsif flag?(:darwin) || flag?(:bsd) %}
  TIOCGWINSZ = 0x40087468u32
{% end %}
1 Like

This is what I use for the console component; it handles MacOS, BSD, Unix, Solaris, and Windows:

Then the usages of the bindings are in:

Related: How to get Terminal width? · Issue #2061 · crystal-lang/crystal · GitHub

1 Like

@Blacksmoke16 that is great, thanks :slight_smile:

Also worth mentioning is SIGWINCH: signal for terminal size change - in case the terminal is resized after program startup.

Signal::WINCH.trap do
  # get new terminal size
end

Full example: Terminal size and resize in Crystal · GitHub

3 Likes