about summary refs log tree commit diff
path: root/library/std/src/io/stdio.rs
diff options
context:
space:
mode:
authorJosh Triplett <josh@joshtriplett.org>2022-06-12 14:10:18 -0700
committerJosh Triplett <josh@joshtriplett.org>2022-10-15 00:35:38 +0100
commit326ef470a8b379a180d6dc4bbef08990698a737a (patch)
tree1466bde52b4eb3e910ec2811981bd656f9e9c757 /library/std/src/io/stdio.rs
parentbf15a9e5263fcea065a7ae9c179b2d24c2deb670 (diff)
downloadrust-326ef470a8b379a180d6dc4bbef08990698a737a.tar.gz
rust-326ef470a8b379a180d6dc4bbef08990698a737a.zip
Add `IsTerminal` trait to determine if a descriptor or handle is a terminal
The UNIX and WASI implementations use `isatty`. The Windows
implementation uses the same logic the `atty` crate uses, including the
hack needed to detect msys terminals.

Implement this trait for `File` and for `Stdin`/`Stdout`/`Stderr` and
their locked counterparts on all platforms. On UNIX and WASI, implement
it for `BorrowedFd`/`OwnedFd`. On Windows, implement it for
`BorrowedHandle`/`OwnedHandle`.

Based on https://github.com/rust-lang/rust/pull/91121

Co-authored-by: Matt Wilkinson <mattwilki17@gmail.com>
Diffstat (limited to 'library/std/src/io/stdio.rs')
-rw-r--r--library/std/src/io/stdio.rs29
1 files changed, 29 insertions, 0 deletions
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 4ccb2bf3231..1141a957d87 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -7,6 +7,7 @@ use crate::io::prelude::*;
 
 use crate::cell::{Cell, RefCell};
 use crate::fmt;
+use crate::fs::File;
 use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines};
 use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sync::{Arc, Mutex, MutexGuard, OnceLock};
@@ -1035,6 +1036,34 @@ pub(crate) fn attempt_print_to_stderr(args: fmt::Arguments<'_>) {
     let _ = stderr().write_fmt(args);
 }
 
+/// Trait to determine if a descriptor/handle refers to a terminal/tty.
+#[unstable(feature = "is_terminal", issue = "98070")]
+pub trait IsTerminal: crate::sealed::Sealed {
+    /// Returns `true` if the descriptor/handle refers to a terminal/tty.
+    ///
+    /// On platforms where Rust does not know how to detect a terminal yet, this will return
+    /// `false`. This will also return `false` if an unexpected error occurred, such as from
+    /// passing an invalid file descriptor.
+    fn is_terminal(&self) -> bool;
+}
+
+macro_rules! impl_is_terminal {
+    ($($t:ty),*$(,)?) => {$(
+        #[unstable(feature = "sealed", issue = "none")]
+        impl crate::sealed::Sealed for $t {}
+
+        #[unstable(feature = "is_terminal", issue = "98070")]
+        impl IsTerminal for $t {
+            #[inline]
+            fn is_terminal(&self) -> bool {
+                crate::sys::io::is_terminal(self)
+            }
+        }
+    )*}
+}
+
+impl_is_terminal!(File, Stdin, StdinLock<'_>, Stdout, StdoutLock<'_>, Stderr, StderrLock<'_>);
+
 #[unstable(
     feature = "print_internals",
     reason = "implementation detail which may disappear or be replaced at any time",