diff --git a/helix-core/src/combinators.rs b/helix-core/src/combinators.rs index dd6cd89e73f11..ecd0bdc9ff31b 100644 --- a/helix-core/src/combinators.rs +++ b/helix-core/src/combinators.rs @@ -1,7 +1,7 @@ -use anyhow::Result; use std::io::Error; use std::io::ErrorKind; use std::io::Read; +use std::io::Result; use std::io::Write; pub fn write_byte(writer: &mut W, byte: u8) -> Result<()> { @@ -60,8 +60,8 @@ pub fn write_option( pub fn read_byte(reader: &mut R) -> Result { match reader.bytes().next() { - Some(s) => Ok(s?), - None => anyhow::bail!(Error::from(ErrorKind::UnexpectedEof)), + Some(s) => s, + None => Err(Error::from(ErrorKind::UnexpectedEof)), } } @@ -70,7 +70,7 @@ pub fn read_bool(reader: &mut R) -> Result { 0 => false, 1 => true, _ => { - anyhow::bail!(Error::new( + return Err(Error::new( ErrorKind::Other, "invalid byte to bool conversion", )) diff --git a/helix-core/src/history.rs b/helix-core/src/history.rs index a97a9ddded9a5..750dbfb033ea8 100644 --- a/helix-core/src/history.rs +++ b/helix-core/src/history.rs @@ -182,6 +182,18 @@ impl std::fmt::Display for StateError { } } +impl From for StateError { + fn from(value: std::io::Error) -> Self { + Self::Other(value.into()) + } +} + +impl From for StateError { + fn from(value: std::time::SystemTimeError) -> Self { + Self::Other(value.into()) + } +} + impl From for StateError { fn from(value: anyhow::Error) -> Self { Self::Other(value) @@ -199,15 +211,14 @@ impl PartialEq for Revision { } } impl Revision { - fn serialize(&self, writer: &mut W) -> Result<(), StateError> { + fn serialize(&self, writer: &mut W) -> anyhow::Result<()> { write_usize(writer, self.parent)?; self.transaction.serialize(writer)?; self.inversion.serialize(writer)?; write_u64( writer, self.timestamp - .duration_since(std::time::UNIX_EPOCH) - .map_err(anyhow::Error::from)? + .duration_since(std::time::UNIX_EPOCH)? .as_secs(), )?; @@ -306,7 +317,7 @@ impl History { path: &Path, revision: usize, last_saved_revision: usize, - ) -> anyhow::Result<()> { + ) -> Result<(), StateError> { // Header let mtime = std::fs::metadata(path)? .modified()? diff --git a/helix-core/src/selection.rs b/helix-core/src/selection.rs index 996f614f72fc2..5fc8939368911 100644 --- a/helix-core/src/selection.rs +++ b/helix-core/src/selection.rs @@ -396,7 +396,7 @@ pub struct Selection { } impl Selection { - pub fn serialize(&self, writer: &mut W) -> anyhow::Result<()> { + pub fn serialize(&self, writer: &mut W) -> std::io::Result<()> { write_usize(writer, self.primary_index)?; write_vec(writer, self.ranges(), |writer, range| { write_usize(writer, range.anchor)?; @@ -412,7 +412,7 @@ impl Selection { Ok(()) } - pub fn deserialize(reader: &mut R) -> anyhow::Result { + pub fn deserialize(reader: &mut R) -> std::io::Result { let primary_index = read_usize(reader)?; let ranges = read_vec(reader, |reader| { let anchor = read_usize(reader)?; diff --git a/helix-core/src/transaction.rs b/helix-core/src/transaction.rs index 4307b0e6c6785..06d32bffb0668 100644 --- a/helix-core/src/transaction.rs +++ b/helix-core/src/transaction.rs @@ -508,7 +508,7 @@ pub struct Transaction { } impl Transaction { - pub fn serialize(&self, writer: &mut W) -> anyhow::Result<()> { + pub fn serialize(&self, writer: &mut W) -> std::io::Result<()> { write_option(writer, self.selection.as_ref(), |writer, selection| { selection.serialize(writer) })?; @@ -538,7 +538,7 @@ impl Transaction { Ok(()) } - pub fn deserialize(reader: &mut R) -> anyhow::Result { + pub fn deserialize(reader: &mut R) -> std::io::Result { let selection = read_option(reader, Selection::deserialize)?; let len = read_usize(reader)?; @@ -549,7 +549,7 @@ impl Transaction { 1 => Operation::Delete(read_usize(reader)?), 2 => Operation::Insert(read_string(reader)?.into()), _ => { - anyhow::bail!(std::io::Error::new( + return Err(std::io::Error::new( std::io::ErrorKind::Other, "invalid variant", )) diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 3abe9cae54ac5..e7636dafdf02a 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -570,12 +570,16 @@ impl Application { } // TODO: fix being overwritten by lsp - self.editor.set_status(format!( + let mut msg = format!( "'{}' written, {}L {}B", get_relative_path(&doc_save_event.path).to_string_lossy(), lines, bytes - )); + ); + if let Some(e) = doc_save_event.undofile_error { + msg = format!("{msg} | Could not write undofile: {e}"); + } + self.editor.set_status(msg); } #[inline(always)] diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index 6db23b3ad5b1a..6fc4e3a5dd560 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -102,6 +102,8 @@ pub struct DocumentSavedEvent { pub doc_id: DocumentId, pub path: PathBuf, pub text: Rope, + // HAXX: errors can't be cloend + pub undofile_error: Option, } pub type DocumentSavedEventResult = Result; @@ -714,6 +716,7 @@ impl Document { } doc.detect_indent_and_line_ending(); + doc.reload_history()?; Ok(doc) } @@ -903,28 +906,23 @@ impl Document { } } - // TODO: Decide on how to do error handling. IO errors are ok. Invalid undofile is not - // TODO: Remove unwraps + // TODO: Check error handling let has_valid_undofile = { let path = path.clone(); let undofile_path = undofile_path.clone(); spawn_blocking(move || -> anyhow::Result { - match helix_core::history::History::is_valid( + helix_core::history::History::is_valid( &mut std::fs::File::open(undofile_path)?, &path, - ) { - Ok(res) => Ok(res), - // Err(e) if e.downcast_ref::().is_none() => Err(e), - _ => Ok(false), - } + ) }) - .await - .unwrap() + .await? + .unwrap_or(false) }; let mut file = File::create(&path).await?; to_writer(&mut file, encoding_with_bom_info, &text).await?; - { + let undofile_res = { // helix-core does not have tokio let mut undofile = tokio::fs::OpenOptions::new() .write(true) @@ -937,24 +935,23 @@ impl Document { let path = path.clone(); spawn_blocking(move || -> anyhow::Result<()> { - let offset = if has_valid_undofile? { + let offset = if has_valid_undofile { last_saved_revision } else { undofile.set_len(0)?; 0 }; - history - .serialize(&mut undofile, &path, current_rev, offset) - .unwrap(); + history.serialize(&mut undofile, &path, current_rev, offset)?; Ok(()) }) - .await??; - } + .await? + }; let event = DocumentSavedEvent { revision: current_rev, doc_id, path, text: text.clone(), + undofile_error: undofile_res.map_err(|e| e.to_string()).err(), }; for (_, language_server) in language_servers {