Is terminal a tty and reverted feature from 0.17 which introduced a bug. (#405)

This commit is contained in:
Timon 2020-03-28 18:38:07 +01:00 committed by GitHub
parent 9c9543d454
commit 58ef32b40a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 71 additions and 10 deletions

View File

@ -1,3 +1,7 @@
# Version 0.17.1
- Reverted bug in 0.17.0: "Make terminal size function fallback to `STDOUT_FILENO` if `/dev/tty` is missing.".
- Support for querying whether the current instance is a TTY.
# Version 0.17 # Version 0.17
- Impl Display for MoveToColumn, MoveToNextLine, MoveToPreviousLine - Impl Display for MoveToColumn, MoveToNextLine, MoveToPreviousLine
- Make unix event reader always use `/dev/tty`. - Make unix event reader always use `/dev/tty`.

View File

@ -35,6 +35,7 @@ see [Tested Terminals](#tested-terminals) for more info).
- Detailed documentation - Detailed documentation
- Few dependencies - Few dependencies
- Full control over writing and flushing output buffer - Full control over writing and flushing output buffer
- Is tty
- Cursor - Cursor
- Move the cursor N times (up, down, left, right) - Move the cursor N times (up, down, left, right)
- Move to previous / next line - Move to previous / next line
@ -139,7 +140,7 @@ To optional feature flags.
```toml ```toml
[dependencies.crossterm] [dependencies.crossterm]
version = "0.14" version = "0.17"
features = ["event-stream"] features = ["event-stream"]
``` ```

View File

@ -16,7 +16,8 @@ The examples are compatible with the latest release.
| :------- | :------- | :------- | | :------- | :------- | :------- |
| `examples/interactive-test` | interactive, walk trough, demo | cursor, style, event | `examples/interactive-test` | interactive, walk trough, demo | cursor, style, event
| `event-*`| event reading demos | (async) event reading | `event-*`| event reading demos | (async) event reading
| `stderr` | crossterm over stderr demo, | raw mode, alternate screen, custom output | `stderr` | crossterm over stderr demo | raw mode, alternate screen, custom output
| `is_tty` | Is this instance a tty ? | tty |
## Run examples ## Run examples

10
examples/is_tty.rs Normal file
View File

@ -0,0 +1,10 @@
use crossterm::tty::IsTty;
use std::io::stdin;
pub fn main() {
if stdin().is_tty() {
println!("Is TTY");
} else {
println!("Is not TTY");
}
}

View File

@ -65,14 +65,18 @@ impl Drop for FileDesc {
/// Creates a file descriptor pointing to the standard input or `/dev/tty`. /// Creates a file descriptor pointing to the standard input or `/dev/tty`.
pub fn tty_fd() -> Result<FileDesc> { pub fn tty_fd() -> Result<FileDesc> {
let (fd, close_on_drop) = ( let (fd, close_on_drop) = if unsafe { libc::isatty(libc::STDIN_FILENO) == 1 } {
(libc::STDIN_FILENO, false)
} else {
(
fs::OpenOptions::new() fs::OpenOptions::new()
.read(true) .read(true)
.write(true) .write(true)
.open("/dev/tty")? .open("/dev/tty")?
.into_raw_fd(), .into_raw_fd(),
true, true,
); )
};
Ok(FileDesc::new(fd, close_on_drop)) Ok(FileDesc::new(fd, close_on_drop))
} }

View File

@ -242,6 +242,9 @@ pub mod style;
/// A module to work with the terminal. /// A module to work with the terminal.
pub mod terminal; pub mod terminal;
/// A module to query if the current instance is a tty.
pub mod tty;
mod ansi; mod ansi;
#[cfg(windows)] #[cfg(windows)]
pub(crate) mod ansi_support; pub(crate) mod ansi_support;

38
src/tty.rs Normal file
View File

@ -0,0 +1,38 @@
//! Making it a little more convenient and safe to query whether
//! something is a terminal teletype or not.
//! This module defines the IsTty trait and the is_tty method to
//! return true if the item represents a terminal.
#[cfg(unix)]
use std::os::unix::io::AsRawFd;
#[cfg(windows)]
use std::os::windows::io::AsRawHandle;
#[cfg(windows)]
use winapi::um::consoleapi::GetConsoleMode;
/// Adds the `is_tty` method to types that might represent a terminal
pub trait IsTty {
/// Returns true when an instance is a terminal teletype, otherwise false.
fn is_tty(&self) -> bool;
}
/// On unix, the `isatty()` function returns true if a file
/// descriptor is a terminal.
#[cfg(unix)]
impl<S: AsRawFd> IsTty for S {
fn is_tty(&self) -> bool {
let fd = self.as_raw_fd();
unsafe { libc::isatty(fd) == 1 }
}
}
/// On windows, `GetConsoleMode` will return true if we are in a terminal.
/// Otherwise false.
#[cfg(windows)]
impl<S: AsRawHandle> IsTty for S {
fn is_tty(&self) -> bool {
let mut mode = 0;
let ok = unsafe { GetConsoleMode(self.as_raw_handle() as *mut _, &mut mode) };
ok == 1
}
}