diff --git a/spellcheck.dic b/spellcheck.dic index e9f7eec22f6..faa855921b4 100644 --- a/spellcheck.dic +++ b/spellcheck.dic @@ -1,4 +1,4 @@ -299 +300 & + < @@ -263,6 +263,7 @@ tokio Tokio tokio's Tokio's +tty tuple Tuple tx diff --git a/tokio/src/io/blocking.rs b/tokio/src/io/blocking.rs index 1af5065456d..4d366c85f72 100644 --- a/tokio/src/io/blocking.rs +++ b/tokio/src/io/blocking.rs @@ -50,6 +50,13 @@ cfg_io_blocking! { } } +impl<T> Blocking<T> { + #[cfg_attr(not(feature = "io-std"), allow(dead_code))] + pub(crate) fn inner(&self) -> Option<&T> { + self.inner.as_ref() + } +} + impl<T> AsyncRead for Blocking<T> where T: Read + Unpin + Send + 'static, diff --git a/tokio/src/io/stderr.rs b/tokio/src/io/stderr.rs index 0988e2d9da0..6c82d141b75 100644 --- a/tokio/src/io/stderr.rs +++ b/tokio/src/io/stderr.rs @@ -3,6 +3,7 @@ use crate::io::stdio_common::SplitByUtf8BoundaryIfWindows; use crate::io::AsyncWrite; use std::io; +use std::io::IsTerminal; use std::pin::Pin; use std::task::Context; use std::task::Poll; @@ -132,3 +133,14 @@ impl AsyncWrite for Stderr { Pin::new(&mut self.std).poll_shutdown(cx) } } + +impl Stderr { + /// Returns true if the descriptor/handle refers to a terminal/tty. + pub fn is_terminal(&self) -> bool { + self.std + .inner() + .inner() + .map(|stderr| stderr.is_terminal()) + .unwrap_or_default() + } +} diff --git a/tokio/src/io/stdin.rs b/tokio/src/io/stdin.rs index 877c48b30fb..1031745f51e 100644 --- a/tokio/src/io/stdin.rs +++ b/tokio/src/io/stdin.rs @@ -1,7 +1,7 @@ use crate::io::blocking::Blocking; use crate::io::{AsyncRead, ReadBuf}; -use std::io; +use std::io::{self, IsTerminal}; use std::pin::Pin; use std::task::Context; use std::task::Poll; @@ -96,3 +96,13 @@ impl AsyncRead for Stdin { Pin::new(&mut self.std).poll_read(cx, buf) } } + +impl Stdin { + /// Returns true if the descriptor/handle refers to a terminal/tty. + pub fn is_terminal(&self) -> bool { + self.std + .inner() + .map(|stdin| stdin.is_terminal()) + .unwrap_or_default() + } +} diff --git a/tokio/src/io/stdio_common.rs b/tokio/src/io/stdio_common.rs index 4adbfe23606..2d8064d27fc 100644 --- a/tokio/src/io/stdio_common.rs +++ b/tokio/src/io/stdio_common.rs @@ -17,6 +17,10 @@ impl<W> SplitByUtf8BoundaryIfWindows<W> { pub(crate) fn new(inner: W) -> Self { Self { inner } } + + pub(crate) fn inner(&self) -> &W { + &self.inner + } } // this constant is defined by Unicode standard. diff --git a/tokio/src/io/stdout.rs b/tokio/src/io/stdout.rs index f46ca0f05c4..0d779999b13 100644 --- a/tokio/src/io/stdout.rs +++ b/tokio/src/io/stdout.rs @@ -2,6 +2,7 @@ use crate::io::blocking::Blocking; use crate::io::stdio_common::SplitByUtf8BoundaryIfWindows; use crate::io::AsyncWrite; use std::io; +use std::io::IsTerminal; use std::pin::Pin; use std::task::Context; use std::task::Poll; @@ -181,3 +182,14 @@ impl AsyncWrite for Stdout { Pin::new(&mut self.std).poll_shutdown(cx) } } + +impl Stdout { + /// Returns true if the descriptor/handle refers to a terminal/tty. + pub fn is_terminal(&self) -> bool { + self.std + .inner() + .inner() + .map(|stdout| stdout.is_terminal()) + .unwrap_or_default() + } +} diff --git a/tokio/src/process/mod.rs b/tokio/src/process/mod.rs index 565795ac4e6..ecd0d39201f 100644 --- a/tokio/src/process/mod.rs +++ b/tokio/src/process/mod.rs @@ -1381,6 +1381,11 @@ impl ChildStdin { inner: imp::stdio(inner)?, }) } + + /// Returns true if the descriptor/handle refers to a terminal/tty. + pub fn is_terminal(&self) -> bool { + self.inner.is_terminal() + } } impl ChildStdout { @@ -1396,6 +1401,11 @@ impl ChildStdout { inner: imp::stdio(inner)?, }) } + + /// Returns true if the descriptor/handle refers to a terminal/tty. + pub fn is_terminal(&self) -> bool { + self.inner.is_terminal() + } } impl ChildStderr { @@ -1411,6 +1421,11 @@ impl ChildStderr { inner: imp::stdio(inner)?, }) } + + /// Returns true if the descriptor/handle refers to a terminal/tty. + pub fn is_terminal(&self) -> bool { + self.inner.is_terminal() + } } impl AsyncWrite for ChildStdin { diff --git a/tokio/src/process/unix/mod.rs b/tokio/src/process/unix/mod.rs index c9d1035f53d..4203a620522 100644 --- a/tokio/src/process/unix/mod.rs +++ b/tokio/src/process/unix/mod.rs @@ -41,7 +41,7 @@ use mio::unix::SourceFd; use std::fmt; use std::fs::File; use std::future::Future; -use std::io; +use std::io::{self, IsTerminal}; use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use std::pin::Pin; use std::process::{Child as StdChild, ExitStatus, Stdio}; @@ -279,6 +279,10 @@ impl ChildStdio { pub(super) fn into_owned_fd(self) -> io::Result<OwnedFd> { convert_to_blocking_file(self).map(OwnedFd::from) } + + pub(crate) fn is_terminal(&self) -> bool { + self.as_fd().is_terminal() + } } impl fmt::Debug for ChildStdio { diff --git a/tokio/src/process/windows.rs b/tokio/src/process/windows.rs index db3c15790ce..c06a3fc4c90 100644 --- a/tokio/src/process/windows.rs +++ b/tokio/src/process/windows.rs @@ -24,7 +24,10 @@ use std::fmt; use std::fs::File as StdFile; use std::future::Future; use std::io; -use std::os::windows::prelude::{AsRawHandle, IntoRawHandle, OwnedHandle, RawHandle}; +use std::io::IsTerminal; +use std::os::windows::prelude::{ + AsHandle, AsRawHandle, BorrowedHandle, IntoRawHandle, OwnedHandle, RawHandle, +}; use std::pin::Pin; use std::process::Stdio; use std::process::{Child as StdChild, Command as StdCommand, ExitStatus}; @@ -199,6 +202,10 @@ impl ChildStdio { pub(super) fn into_owned_handle(self) -> io::Result<OwnedHandle> { convert_to_file(self).map(OwnedHandle::from) } + + pub(crate) fn is_terminal(&self) -> bool { + self.as_handle().is_terminal() + } } impl AsRawHandle for ChildStdio { @@ -207,6 +214,12 @@ impl AsRawHandle for ChildStdio { } } +impl AsHandle for ChildStdio { + fn as_handle(&self) -> BorrowedHandle<'_> { + self.raw.as_handle() + } +} + impl AsyncRead for ChildStdio { fn poll_read( mut self: Pin<&mut Self>,