1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
//! The inverse of [`println`] //! //! [`scanln`] is a macro that reads a line from `stdin`, [removes the trailing //! newline][0] (if present), and leaves other whitespace intact. It expands to //! an expression that returns a [`String`], so it can be assigned to a variable //! or used directly. [`scanln`] may take arguments like those to the [`print`] //! macro, which can be used to generate a prompt. //! //! # Examples //! //! ## Simple prompt //! //! ```no_run //! # #[macro_use] extern crate scanln; //! let input = scanln!("> "); //! ``` //! //! This results in a prompt that looks like this (where `_` represents where //! the user will start typing): //! //! ```text //! > _ //! ``` //! //! ## No prompt //! //! ```no_run //! # #[macro_use] extern crate scanln; //! let input = scanln!(); //! ``` //! //! Result: //! //! ```text //! _ //! ``` //! //! ## Formatted prompt //! //! ```no_run //! # #[macro_use] extern crate scanln; //! let input = scanln!("{}", 0); //! ``` //! //! Result: //! //! ```text //! 0_ //! ``` //! //! [0]: https://users.rust-lang.org/t/remove-the-new-line-from-read-line/21380 /// The inverse of [`println`] /// /// Invocations of [`scanln`] expand to an expression retuning a [`String`] that /// contains a line of input from `stdin`. It can be invoked with arguments /// identical to those of [`print`], and if so, those arguments will be used /// to generate a prompt on `stdout`. Input will begin on the same line that the /// prompt ends, if any. If no arguments are provided, input will start where /// the cursor is, which is likely to be on its own empty line. #[macro_export] macro_rules! scanln { // Get the actual input, stripping the trailing '\n' and/or '\r' if present () => {{ let mut s = ::std::string::String::new(); ::std::io::stdin().read_line(&mut s).unwrap(); // TODO fix bizarre syntax, blocked on const generics: // https://github.com/rust-lang/rust/issues/39511 s.trim_end_matches(&['\n', '\r'][..]).to_owned() }}; // Print out a prompt, possibly with format arguments ( $($args:tt)* ) => {{ print!("{}", format_args!($($args)*)); // Flush stdout because it's line buffered and we didn't print a newline use ::std::io::Write; ::std::io::stdout().flush().unwrap(); // Read input $crate::scanln!() }}; }