use std::path::{ Path, PathBuf }; use pico_args::Arguments; // - HELPER - const DRIVE: &str = "/mnt/c/"; // - ENV - const DISTRO: &str = "WSL_DISTRO_NAME"; // - FLAGS - const HELP: [&str;2] = [ "-h", "--help" ]; const NET_PATH: [&str;2] = [ "-n", "--network" ]; const NO_SPACES: [&str;2] = [ "-s", "--no-space" ]; const QUOTED: [&str;2] = [ "-q", "--quotes" ]; pub fn main() { let mut args = Arguments::from_env(); // handle help flag if args.contains(HELP) { help_text(); return; } // handle quote flag let quotes: &str = if args.contains(QUOTED) { if args.contains(QUOTED) { "\"" } // -qq -> "..." (output with double quotes) else { "'" } // -q -> '...' (output with single quotes) } else { "" }; // _ -> ... (output with no quotes) // consume simple flags let no_spaces = args.contains(NO_SPACES); let network_path = args.contains(NET_PATH); loop { let next = args.subcommand().unwrap(); if let Some(arg) = next { let mut output: String; // canonicalize; windows doesn't recognize symlinks let path = Path::new(&arg).canonicalize(); if let Ok(target) = path { output = target.to_string_lossy().to_string(); } else { output = arg; } // handle no-space flag if no_spaces { let tmp = output.clone(); let parts = tmp.split('/'); let mut current = PathBuf::new(); current.push("/"); for part in parts { if part.is_empty() { continue; } let space = part.chars().position(|c| c == ' '); let len = part.len(); // if space is found, use short version if let Some(index) = space { // find cut point and make slice let cut = usize::min(len, index).min(6); let replace = &(part[..cut]); // determine number for shortening let mut index = 0; let children = current.read_dir(); if !children.is_ok() { continue; } for child in children.unwrap() { if let Ok(child) = child { let name: String = child.file_name().to_string_lossy().into(); // matches increment if name.to_lowercase().starts_with(&replace.to_lowercase()) { index += 1; } // ... and break when we hit the target if name == part { break; } } } output = output.replacen(part, &format!("{replace}~{index}"), 1); } current.push(part); } } // simple C-drive substitution if output.starts_with(DRIVE) { output = output.replace(DRIVE, "C:\\"); } else if network_path { let name = std::env::var(DISTRO); if let Ok(name) = name { output = format!("//wsl.localhost/{name}{output}"); } } // switch out separators output = output.replace("/", "\\"); // emit to stdout println!("{quotes}{output}{quotes}"); } else { break; } } } pub fn help_text() { println!("path-convert v{} Valerie Wolfe Canonicalize and convert Unix paths for DOS programs. usage: path-convert [flags] args: One or more paths to convert flags: -h, --help Show this help text -n, --network Add the network path where appropriate -q, --quotes Surround the output strings with quotes (-qq for double quotes) -s, --no-space Don't allow paths to have spaces ", env!("CARGO_PKG_VERSION")); }