From 89d6f908c49f968f36ff01a6e37efa3b48faf150 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 5 Dec 2018 14:32:43 -0600 Subject: [PATCH] Improve error handling & feedback. Change default path to minetest.exe on Windows. --- .gitignore | 1 + src/main.rs | 50 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 53eaa21..83f11f9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target **/*.rs.bk +debug.txt diff --git a/src/main.rs b/src/main.rs index 52add02..37b7174 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,15 +3,15 @@ extern crate regex; use mumble_link::*; use regex::Regex; -use std::io::{BufRead, BufReader}; +use std::io::{BufRead, BufReader, Read, Write}; use std::process::{Command, Stdio}; -fn get_data(captures: ®ex::Captures) -> Result<([f32; 3], char, char), String> { - // Function to convert float parsing errors to error strings so we can return that as a result. - fn errstr(e: std::num::ParseFloatError) -> String { - e.to_string() - } +// Function to convert errors to error strings so we can return that as a result. +fn errstr(e: T) -> String where T: ToString { + e.to_string() +} +fn get_data(captures: ®ex::Captures) -> Result<([f32; 3], char, char), String> { // Get all the named captures. Ok(([captures["x"].parse().map_err(errstr)?, captures["y"].parse().map_err(errstr)?, captures["z"].parse().map_err(errstr)?,], captures["subject"].chars().next().ok_or("unable to get vec subject")?, @@ -19,12 +19,38 @@ fn get_data(captures: ®ex::Captures) -> Result<([f32; 3], char, char), String )) } + fn main() { + match try_main() { + Ok(_) => {}, + Err(err) => { + println!("Error: {}", err); + + // print without a newline and flush to keep the cursor on the same line. + print!("Press ENTER to continue..."); + std::io::stdout().flush().unwrap(); + + // Read a single byte and discard. + let _ = std::io::stdin().read(&mut [0u8]); + } + } +} + +fn try_main() -> Result<(), String> { + println!("Starting..."); + // Hook into Mumble using the very handy crate somebody made. - let mut link = MumbleLink::new("Minetest", "Minetest positional audio using a mod and wrapper.").expect("Unable to link to Mumble. Is it running?"); + let mut link = MumbleLink::new("Minetest", "Minetest positional audio using a mod and wrapper.") + .map_err(|e| { format!("Unable to connect to Mumble. Is it running? ({})", e) })?; + + println!("Connected to Mumble successfully."); // Default command to launch. - let mut minetest_command = "/usr/bin/minetest".to_owned(); + let mut minetest_command = if cfg!(windows) { + "C:\\Program Files\\minetest\\bin\\minetest.exe" + } else { + "/usr/bin/minetest" + }.to_owned(); // Look for an argument containing "minetest" to replace default command. (But make sure it isn't this exe because that just leads to crazy recursion...) for argument in std::env::args() { @@ -33,9 +59,11 @@ fn main() { } } + println!("Launching Minetest at {}", minetest_command); + let mut child = Command::new(minetest_command) .stderr(Stdio::piped()) // We need the output to be piped. For some reason Minetest lua's print function goes to stderr... - .spawn().unwrap(); // Spawn the process, panic if it fails. + .spawn().map_err(|e| { format!("Unable to start Minetest executable: {}", e) })?; // Spawn the process, return an error if it fails. // This regex parses lines like "p l [1.0 1.0 1.0]". // the first letter (the subject) is either 'p' or 'c' denoting whether this is a player or camera vector. @@ -51,7 +79,7 @@ fn main() { let mut camera = Position::default(); // Run as long as the child proccess is running. - while child.try_wait().unwrap().is_none() { + while child.try_wait().map_err(errstr)?.is_none() { // Get the output from the child process. if let Some(ref mut child_output) = child.stderr { // Using a BufReader allows us to go through all the lines in a loop. @@ -106,4 +134,6 @@ fn main() { } } } + + Ok(()) }