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 84 85 86 87
use std::borrow::Borrow; use std::fs; use std::path::{Path, PathBuf}; use shellexpand; pub fn make_path_buf<S: AsRef<str>>(s: S) -> ::Result<PathBuf> { shellexpand::full(s.as_ref()) .map(|s| PathBuf::from(s.borrow() as &str)) .map_err(Into::into) } #[cfg(windows)] pub fn canonicalize_pretty<P: AsRef<Path>>(path: P) -> ::Result<PathBuf> { path.as_ref() .canonicalize() .map_err(Into::into) .map(|path| { path.to_string_lossy() .trim_left_matches(r"\\?\") .replace(r"\", "/") }) .map(|s| PathBuf::from(s)) } #[cfg(not(windows))] pub fn canonicalize_pretty<P: AsRef<Path>>(path: P) -> ::Result<PathBuf> { path.as_ref().canonicalize().map_err(Into::into) } pub trait StrSkip { fn skip<'a>(&'a self, n: usize) -> &'a str; } impl StrSkip for str { fn skip<'a>(&'a self, n: usize) -> &'a str { let mut s = self.chars(); for _ in 0..n { s.next(); } s.as_str() } } #[test] fn test_skipped_1() { assert_eq!("hoge".skip(1), "oge"); assert_eq!("あいueo".skip(1), "いueo"); } pub fn write_content<P, F>(path: P, write_fn: F) -> ::Result<()> where P: AsRef<Path>, F: FnOnce(&mut fs::File) -> ::Result<()>, { fs::create_dir_all(path.as_ref().parent().unwrap())?; let mut file = fs::OpenOptions::new() .write(true) .create(true) .truncate(true) .open(&path)?; write_fn(&mut file) } pub mod process { use std::process::{Command, Stdio}; pub fn inherit(name: &str) -> Command { let mut command = Command::new(name); command.stdin(Stdio::inherit()); command.stdout(Stdio::inherit()); command.stderr(Stdio::inherit()); command } pub fn piped(name: &str) -> Command { let mut command = Command::new(name); command.stdin(Stdio::null()); command.stdout(Stdio::piped()); command.stderr(Stdio::piped()); command } }