term.rs 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. mod c {
  2. use std::mem::zeroed;
  3. use libc::{c_int, c_ushort, c_ulong, STDOUT_FILENO};
  4. // Getting the terminal size is done using an ioctl command that
  5. // takes the file handle to the terminal (which in our case is
  6. // stdout), and populates a structure with the values.
  7. pub struct Winsize {
  8. pub ws_row: c_ushort,
  9. pub ws_col: c_ushort,
  10. }
  11. // Unfortunately the actual command is not standardised...
  12. #[cfg(any(target_os = "linux", target_os = "android"))]
  13. static TIOCGWINSZ: c_ulong = 0x5413;
  14. #[cfg(any(target_os = "macos", target_os = "ios"))]
  15. static TIOCGWINSZ: c_ulong = 0x40087468;
  16. extern {
  17. pub fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int;
  18. }
  19. pub unsafe fn dimensions() -> Winsize {
  20. let mut window: Winsize = zeroed();
  21. ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut window as *mut Winsize);
  22. window
  23. }
  24. }
  25. /// Query the current processes's output, returning its width and height as a
  26. /// number of characters. Returns None if the output isn't to a terminal.
  27. pub fn dimensions() -> Option<(usize, usize)> {
  28. let w = unsafe { c::dimensions() };
  29. if w.ws_col == 0 || w.ws_row == 0 {
  30. None
  31. }
  32. else {
  33. Some((w.ws_col as usize, w.ws_row as usize))
  34. }
  35. }