Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 3 commits into from
Mar 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
- Impl Display for MoveToColumn, MoveToNextLine, MoveToPreviousLine
- Make unix event reader always use `/dev/tty`.
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ see [Tested Terminals](#tested-terminals) for more info).
- Detailed documentation
- Few dependencies
- Full control over writing and flushing output buffer
- Is tty
- Cursor
- Move the cursor N times (up, down, left, right)
- Move to previous / next line
Expand Down Expand Up @@ -139,7 +140,7 @@ To optional feature flags.

```toml
[dependencies.crossterm]
version = "0.14"
version = "0.17"
features = ["event-stream"]
```

Expand Down
3 changes: 2 additions & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ The examples are compatible with the latest release.
| :------- | :------- | :------- |
| `examples/interactive-test` | interactive, walk trough, demo | cursor, style, event
| `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

Expand Down
10 changes: 10 additions & 0 deletions examples/is_tty.rs
Original file line number Diff line number Diff line change
@@ -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");
}
}
20 changes: 12 additions & 8 deletions src/event/sys/unix/file_descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,18 @@ impl Drop for FileDesc {

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

Ok(FileDesc::new(fd, close_on_drop))
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ pub mod style;
/// A module to work with the terminal.
pub mod terminal;

/// A module to query if the current instance is a tty.
pub mod tty;

mod ansi;
#[cfg(windows)]
pub(crate) mod ansi_support;
Expand Down
38 changes: 38 additions & 0 deletions src/tty.rs
Original file line number Diff line number Diff line change
@@ -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
}
}