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 88 89 90 91 92 93
use crate::Result; use app_dirs; use crev_common; use crev_data::proof; use std::fmt::Write as FmtWrite; use std::{self, env, ffi, fs, io::Write, path::Path, process}; use tempdir; pub use crev_common::{read_file_to_string, store_str_to_file, store_to_file_with}; pub const APP_INFO: app_dirs::AppInfo = app_dirs::AppInfo { name: "crev", author: "Dawid Ciężarkiewicz", }; fn get_editor_to_use() -> ffi::OsString { if let Some(v) = env::var_os("VISUAL") { return v; } else if let Some(v) = env::var_os("EDITOR") { return v; } else { return "vi".into(); } } fn edit_text_iteractively(text: &str) -> Result<String> { let editor = get_editor_to_use(); let dir = tempdir::TempDir::new("crev")?; let file_path = dir.path().join("crev.review"); let mut file = fs::File::create(&file_path)?; file.write_all(text.as_bytes())?; file.flush()?; drop(file); let status = process::Command::new(editor).arg(&file_path).status()?; if !status.success() { bail!("Editor returned {}", status); } Ok(read_file_to_string(&file_path)?) } pub fn edit_file(path: &Path) -> Result<()> { let editor = get_editor_to_use(); let status = process::Command::new(editor).arg(&path).status()?; if !status.success() { bail!("Editor returned {}", status); } Ok(()) } pub fn get_documentation_for(content: &proof::Content) -> &'static str { use crev_data::proof::Content; match content { Content::Trust(_) => include_str!("../../rc/doc/editing-trust.md"), Content::Code(_) => include_str!("../../rc/doc/editing-code-review.md"), Content::Package(_) => include_str!("../../rc/doc/editing-package-review.md"), } } pub fn edit_proof_content_iteractively(content: &proof::Content) -> Result<proof::Content> { let mut text = String::new(); text.write_str(&format!("# {}\n", content.draft_title()))?; text.write_str(&content.to_draft_string())?; text.write_str("\n\n")?; for line in get_documentation_for(content).lines() { text.write_fmt(format_args!("# {}\n", line))?; } loop { text = edit_text_iteractively(&text)?; match proof::Content::parse_draft(content, &text) { Err(e) => { eprintln!("There was an error parsing content: {}", e); if !crev_common::yes_or_no_was_y("Try again (y/n) ")? { bail!("User canceled"); } } Ok(content) => return Ok(content), } } } pub fn err_eprint_and_ignore<O, E: std::error::Error>(res: std::result::Result<O, E>) -> bool { match res { Err(e) => { eprintln!("{}", e); false } Ok(_) => true, } }