Add a tput based computation of terminal size (#283)

This commit is contained in:
Canop 2019-11-01 17:13:56 +01:00 committed by Timon
parent 3e82d6ae1c
commit c23a6ddf38
2 changed files with 37 additions and 4 deletions

View File

@ -28,10 +28,10 @@
- Rename `Attribute::NoInverse` to `NoReverse`
- `Crossterm::style()` and `Crossterm::color()`
- Remove re-exports from style module at at root and only expose those in the `crossterm::style` module.
- Remove `TerminalColor` (/style.rs),
- Remove `TerminalColor` (/style.rs),
- Remove `color` (style.rs)
- Update documentation
- Made `Colored` private, user should use commands instead.
- Made `Colored` private, user should use commands instead.
- Rename `SetFg` -> `SetForegroundColor`
- Rename `SetBg` -> `SetBackgroundColor`
- Rename `SetAttr` -> `SetAttribute`

View File

@ -1,6 +1,6 @@
//! UNIX related logic for terminal manipulation.
use libc::{ioctl, winsize, STDOUT_FILENO, TIOCGWINSZ};
use std::process;
use crate::utils::sys::unix::wrap_with_result;
use crate::utils::Result;
@ -10,6 +10,39 @@ pub fn exit() {
::std::process::exit(0);
}
/// execute tput with the given argument and parse
/// the output as a u16.
///
/// The arg should be "cols" or "lines"
fn tput_value(arg: &str) -> Option<u16> {
match process::Command::new("tput").arg(arg).output() {
Ok(process::Output { stdout, .. }) => {
let value = stdout
.iter()
.map(|&b| b as u16)
.take_while(|&b| b >= 48 && b <= 58)
.fold(0, |v, b| v * 10 + (b - 48));
if value > 0 {
Some(value)
} else {
None
}
}
_ => None,
}
}
/// return the size of the screen as determined by tput
///
/// This alternate way of computing the size is useful
/// when in a subshell.
fn tput_size() -> Option<(u16, u16)> {
match (tput_value("cols"), tput_value("lines")) {
(Some(w), Some(h)) => Some((w, h)),
_ => None,
}
}
/// Returns the terminal size `(columns, rows)`.
///
/// The top left cell is represented `1,1`.
@ -26,6 +59,6 @@ pub fn size() -> Result<(u16, u16)> {
{
return Ok((size.ws_col, size.ws_row));
} else {
Err(std::io::Error::last_os_error().into())
tput_size().ok_or_else(|| std::io::Error::last_os_error().into())
}
}