summaryrefslogtreecommitdiffstats
path: root/src/edit.rs
diff options
context:
space:
mode:
authorNora <nora.widdecke@tu-bs.de>2019-01-20 13:24:13 +0100
committerNora <nora.widdecke@tu-bs.de>2019-01-20 16:29:27 +0100
commitd6195b29fa8a7369cfa47b288f55efa8ad4d656d (patch)
tree62381cbf6b818f82e97b4156630a908f07e040ff /src/edit.rs
parent16f95ae751e3c96f3f4f335139ab07ab8234f1e6 (diff)
edit: refactor for legibility
Diffstat (limited to 'src/edit.rs')
-rw-r--r--src/edit.rs88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/edit.rs b/src/edit.rs
new file mode 100644
index 0000000..549b7b7
--- /dev/null
+++ b/src/edit.rs
@@ -0,0 +1,88 @@
+use std::env;
+use std::fs;
+use std::path::Path;
+use std::process::Command;
+use tempfile::NamedTempFile;
+
+use backup::backup;
+use khline::KhLine;
+use utils::fileutil;
+use KhResult;
+
+pub fn edit(khline: &KhLine) -> KhResult<()> {
+ let tempfile = NamedTempFile::new()?;
+ let calendar = khline.to_cal()?;
+
+ fileutil::write_file(tempfile.path(), &calendar.to_string())?;
+ edit_loop(&tempfile.path())?;
+
+ let backup_path = backup(&khline).unwrap();
+ info!("Backup written to {}", backup_path.display());
+
+ let edited_cal = KhLine::new(tempfile.path(), None).to_cal()?.with_dtstamp_now().with_last_modified_now();
+ fileutil::write_file(&khline.path, &edited_cal.to_string())?;
+ info!("Successfully edited file {}", khline.path.display());
+
+ Ok(())
+}
+
+fn edit_loop(path: &Path) -> KhResult<()> {
+ loop {
+ edit_file(path)?;
+ let edited_cal = KhLine::new(path, None).to_cal()?;
+ if let Some(errors) = edited_cal.check_for_errors() {
+ if !ask_continue_editing(&errors) {
+ return Err("editing aborted by user")?;
+ }
+ } else {
+ return Ok(());
+ }
+ }
+}
+
+fn edit_file(path: &Path) -> KhResult<()> {
+ if cfg!(test) { return Ok(()) };
+
+ let editor = env::var("EDITOR").unwrap_or_else(|_| "vim".to_string());
+
+ Command::new(&editor)
+ .arg(path.as_os_str())
+ .stdin(fs::File::open("/dev/tty").unwrap())
+ .status()?;
+
+ Ok(())
+}
+
+fn ask_continue_editing(error: &[String]) -> bool {
+ println!("Calendar contains errors:\n{}", error.join("\n"));
+ println!("Continue editing? y/n:");
+
+ match fileutil::read_single_char_from_stdin().unwrap() {
+ 'y' => true,
+ _ => false
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ use testutils::prepare_testdir;
+ use icalwrap::IcalComponent;
+
+ #[test]
+ fn edit_test() {
+ let _testdir = prepare_testdir("testdir");
+
+ let khline = "twodaysacrossbuckets.ics".parse::<KhLine>().unwrap();
+
+ assert!(edit(&khline).is_ok());
+ let event = khline.to_event().unwrap();
+
+ let dtstamp_prop = ical::icalproperty_kind_ICAL_DTSTAMP_PROPERTY;
+ assert_eq!("20130101T010203Z", event.get_property(dtstamp_prop).unwrap().get_value());
+
+ let last_modified_kind = ical::icalproperty_kind_ICAL_LASTMODIFIED_PROPERTY;
+ assert_eq!("20130101T010203Z", event.get_property(last_modified_kind).unwrap().get_value());
+ }
+}