vpxtool 0.31.1

Terminal based frontend and utilities for Visual Pinball
Documentation
use std::fs::metadata;
use std::io;
use std::path::{Path, PathBuf};

mod atomicwrite;
mod backglass;
pub mod fixprint;
mod frontend;
pub mod patcher;

pub mod config;

pub mod indexer;

pub mod cli;
mod colorful_theme_patched;
pub mod vpinball_config;
pub mod vpxz;

pub fn strip_cr_lf(s: &str) -> String {
    s.chars().filter(|c| !c.is_ascii_whitespace()).collect()
}

fn path_exists(path: impl AsRef<Path>) -> io::Result<PathBuf> {
    let path = path.as_ref();
    match metadata(path) {
        Ok(md) => {
            if !md.is_file() && !md.is_dir() && md.is_symlink() {
                Err(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    format!("{} is not a file", path.display()),
                ))
            } else {
                Ok(path.to_path_buf())
            }
        }
        Err(msg) => {
            let warning = format!("Failed to read metadata for {}: {}", path.display(), msg);
            Err(io::Error::new(io::ErrorKind::InvalidInput, warning))
        }
    }
}

fn os_independent_file_name(file_path: String) -> Option<String> {
    // we can't use path here as this uses the system path encoding
    // we might have to parse windows paths on mac/linux
    if file_path.is_empty() {
        return None;
    }
    file_path.rsplit(['/', '\\']).next().map(|f| f.to_string())
}

/// Path to file that will be removed when it goes out of scope
struct RemoveOnDrop {
    path: PathBuf,
}
impl RemoveOnDrop {
    fn new(path: PathBuf) -> Self {
        RemoveOnDrop { path }
    }

    fn path(&self) -> &Path {
        &self.path
    }
}

impl Drop for RemoveOnDrop {
    fn drop(&mut self) {
        if self.path.exists() {
            // silently ignore any errors
            let _ = std::fs::remove_file(&self.path);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_os_independent_file_name_windows() {
        let file_path = "C:\\Users\\user\\Desktop\\file.txt";
        let result = os_independent_file_name(file_path.to_string());
        assert_eq!(result, Some("file.txt".to_string()));
    }

    #[test]
    fn test_os_independent_file_unix() {
        let file_path = "/users/joe/file.txt";
        let result = os_independent_file_name(file_path.to_string());
        assert_eq!(result, Some("file.txt".to_string()));
    }

    #[test]
    fn test_os_independent_file_name_no_extension() {
        let file_path = "C:\\Users\\user\\Desktop\\file";
        let result = os_independent_file_name(file_path.to_string());
        assert_eq!(result, Some("file".to_string()));
    }

    #[test]
    fn test_os_independent_file_name_no_path() {
        let file_path = "file.txt";
        let result = os_independent_file_name(file_path.to_string());
        assert_eq!(result, Some("file.txt".to_string()));
    }

    #[test]
    fn test_os_independent_file_name_no_path_no_extension() {
        let file_path = "file";
        let result = os_independent_file_name(file_path.to_string());
        assert_eq!(result, Some("file".to_string()));
    }

    #[test]
    fn test_os_independent_file_name_empty() {
        let file_path = "";
        let result = os_independent_file_name(file_path.to_string());
        assert_eq!(result, None);
    }
}