So admittedly i'm spoiled by Visual Studio and the Rust plugin for it is fantastic but I would like to 'elegantly' make the program pause at the end before closing, similar to C/C++'s "Press any key to continue" which is provided by System('pause').
I know I could just ask for additional input at the end, but that seems a little clunky to me. Is there such a thing in Rust lang at the moment?
use std::process::Command;
let _ = Command::new("pause").status();
This constructs a new Command object to execute an external command, and executes it, discarding the result since we don't really care what it returned. I say "probably" because I'm not on Windows and can't test it; it's possible that this won't work if pause is a shell builtin rather than an external command.
Of course, this isn't portable, but I don't know if there is any portable way to get a single character of input for a "Press any key to continue" prompt.
Calling an OS-specific shell command to prompt for input for you is more clunky than just doing it yourself, IMO.
use std::io;
use std::io::prelude::*;
fn pause() {
let mut stdin = io::stdin();
let mut stdout = io::stdout();
// We want the cursor to stay at the end of the line, so we print without a newline and flush manually.
write!(stdout, "Press any key to continue...").unwrap();
stdout.flush().unwrap();
// Read a single byte and discard
let _ = stdin.read(&mut [0u8]).unwrap();
}
fn main() {
// Do some stuff
pause();
}
The problem is that without platform-specific methods to enable raw input, you'll only see input once "enter" has been pressed. So "Press any key to continue..." isn't accurate here. You could do this and say "Press enter to continue..." or "Press return to continue...", but you need something platform specific if you want any key to be able to dismiss it.
extern crate termion;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
use std::io::{stdout, stdin, Write};
fn main() {
println!("Press any key to continue...");
let mut stdout = stdout().into_raw_mode().unwrap();
stdout.flush().unwrap();
stdin().events().next();
}
I'm not particularly fond of this hack, but for completeness's sake, I'd like to mention that someone on the unofficial Rust community Discord server wrote a crate for this Windows problem: dont_disappear.
The difference is that on Windows a console window is opened up and then disappears after the program exits, whereas on unices a terminal program does nothing visible when opened from a GUI.
Also, Windows users are far less likely to know how to open a terminal in the first place.
In the contrary, Windows has an operating system feature in which it creates a terminal when a console program is double clicked on so the user can see the output. Other operating systems do not have this feature. Using this operating system feature properly requires certain behavior of console programs, namely that they don't exit until after the user has had an opportunity to view any important output. This makes the issue inherently an operating system issue.
Trying to be smarter than the user and fail with this is an operating system issue, yes.
Not knowing how to operate the system properly is still a user issue.
If windows would keep all those windows open that pop up during login at my office box and I had to close them manually... I had already quit my job...
I'm already annoyed by them popping up at all. Why can't they just run silently? Why isn't this default behaviour?
If an application needs to run without a console it's the developer's responsibility to compile it with the correct subsystem. If the developer didn't do that then Windows can't tell if standard I/O is important to the user or not. In my opinion Windows' behavior is the correct one.
I previously noted that I would implement this behavior into crossterm. Crossterm 5.0 is now live with the ability to pause the terminal. See this example for more information.