diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index d9d0380781925..f5a9146db9a27 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -269,6 +269,8 @@ pub use self::buffered::{BufReader, BufWriter, LineWriter}; pub use self::cursor::Cursor; #[stable(feature = "rust1", since = "1.0.0")] pub use self::error::{Error, ErrorKind, Result}; +#[unstable(feature = "io_input", issue = "none")] +pub use self::stdio::read_line; #[stable(feature = "rust1", since = "1.0.0")] pub use self::stdio::{stderr, stdin, stdout, Stderr, Stdin, Stdout}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 61ccc6f13c8da..a2d59fbb5a163 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -7,7 +7,9 @@ use crate::io::prelude::*; use crate::cell::RefCell; use crate::fmt; -use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter}; +use crate::io::{ + self, BufReader, Error, ErrorKind, Initializer, IoSlice, IoSliceMut, LineWriter, Result, Write, +}; use crate::lazy::SyncOnceCell; use crate::sync::{Mutex, MutexGuard}; use crate::sys::stdio; @@ -873,6 +875,52 @@ impl fmt::Debug for StderrLock<'_> { } } +/// Reads a [`String`] from [standard input](Stdin). The trailing +/// newline is stripped. Gives an error on EOF (end of file). +/// +/// # Note +/// +/// If you require more explicit control over capturing +/// user input, see the [`Stdin::read_line`] method. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(io_input)] +/// use std::io; +/// +/// fn main() -> io::Result<()> { +/// print!("Enter name: "); +/// +/// let name: String = io::read_line()?; +/// +/// println!("Your name is {}!", name); +/// +/// Ok(()) +/// } +/// ``` +#[unstable( + feature = "io_input", + reason = "this function may be replaced with a more general mechanism", + issue = "none" +)] +pub fn read_line() -> Result { + stdout().flush()?; // print!() does not flush :( + let mut input = String::new(); + match stdin().read_line(&mut input)? { + 0 => Err(Error::new(ErrorKind::UnexpectedEof, "input reached eof unexpectedly")), + _ => { + if input.ends_with('\n') { + input.pop(); + if cfg!(windows) && input.ends_with('\r') { + input.pop(); + } + } + Ok(input) + } + } +} + /// Resets the thread-local stderr handle to the specified writer /// /// This will replace the current thread's stderr handle, returning the old