on master help sign in
fix: buffer-close ensuring writes
a5a9318Skyler Hawthorne
helix-term/src/application.rs+2
@@ -310,6 +310,8 @@ impl Application {
310 self.render();
310 self.render();
311 }
311 }
312 event = self.editor.wait_event() => {
312 event = self.editor.wait_event() => {
313+ log::debug!("received editor event: {:?}", event);
314+
313 match event {
315 match event {
314 EditorEvent::DocumentSave(event) => {
316 EditorEvent::DocumentSave(event) => {
315 self.handle_document_write(event);
317 self.handle_document_write(event);
helix-term/src/commands/typed.rs+1
@@ -151,6 +151,7 @@ fn buffer_close(
151 }
151 }
152
152
153 let document_ids = buffer_gather_paths_impl(cx.editor, args);
153 let document_ids = buffer_gather_paths_impl(cx.editor, args);
154+ log::debug!("closing buffers: {:?}", document_ids);
154 buffer_close_by_ids_impl(cx.editor, &document_ids, false)
155 buffer_close_by_ids_impl(cx.editor, &document_ids, false)
155}
156}
156
157
helix-term/tests/test/commands.rs−1
@@ -26,7 +26,6 @@ async fn test_write_quit_fail() -> anyhow::Result<()> {
26}
26}
27
27
28#[tokio::test]
28#[tokio::test]
29−#[ignore]
30async fn test_buffer_close_concurrent() -> anyhow::Result<()> {
29async fn test_buffer_close_concurrent() -> anyhow::Result<()> {
31 test_key_sequences(
30 test_key_sequences(
32 &mut Application::new(Args::default(), Config::default())?,
31 &mut Application::new(Args::default(), Config::default())?,
helix-view/src/document.rs+55−11
@@ -616,6 +616,10 @@ impl Document {
616 }
616 }
617
617
618 pub async fn await_save(&mut self) -> Option<DocumentSaveEventResult> {
618 pub async fn await_save(&mut self) -> Option<DocumentSaveEventResult> {
619+ self.await_save_impl(true).await
620+ }
621+
622+ async fn await_save_impl(&mut self, block: bool) -> Option<DocumentSaveEventResult> {
619 let mut current_save = self.current_save.lock().await;
623 let mut current_save = self.current_save.lock().await;
620 if let Some(ref mut save) = *current_save {
624 if let Some(ref mut save) = *current_save {
621 let result = save.await;
625 let result = save.await;
@@ -627,7 +631,15 @@ impl Document {
627 // return early if the receiver is closed
631 // return early if the receiver is closed
628 self.save_receiver.as_ref()?;
632 self.save_receiver.as_ref()?;
629
633
630− let save = match self.save_receiver.as_mut().unwrap().recv().await {
634+ let rx = self.save_receiver.as_mut().unwrap();
635+
636+ let save_req = if block {
637+ rx.recv().await
638+ } else {
639+ rx.try_recv().ok()
640+ };
641+
642+ let save = match save_req {
631 Some(save) => save,
643 Some(save) => save,
632 None => {
644 None => {
633 self.save_receiver = None;
645 self.save_receiver = None;
@@ -648,19 +660,24 @@ impl Document {
648 Some(result)
660 Some(result)
649 }
661 }
650
662
651− /// Prepares the Document for being closed by stopping any new writes
652− /// and flushing through the queue of pending writes. If any fail,
663+ /// Flushes the queue of pending writes. If any fail,
653− /// it stops early before emptying the rest of the queue. Callers
664+ /// it stops early before emptying the rest of the queue.
654− /// should keep calling until it returns None.
655− pub async fn close(&mut self) -> Option<DocumentSaveEventResult> {
665+ pub async fn try_flush_saves(&mut self) -> Option<DocumentSaveEventResult> {
656− if self.save_sender.is_some() {
666+ self.flush_saves_impl(false).await
657− self.save_sender = None;
658− }
667+ }
659
668
669+ async fn flush_saves_impl(&mut self, block: bool) -> Option<DocumentSaveEventResult> {
660 let mut final_result = None;
670 let mut final_result = None;
661
671
662− while let Some(save_event) = self.await_save().await {
672+ while let Some(save_event) = self.await_save_impl(block).await {
663− let is_err = save_event.is_err();
673+ let is_err = match &save_event {
674+ Ok(event) => {
675+ self.set_last_saved_revision(event.revision);
676+ false
677+ }
678+ Err(_) => true,
679+ };
680+
664 final_result = Some(save_event);
681 final_result = Some(save_event);
665
682
666 if is_err {
683 if is_err {
@@ -671,6 +688,17 @@ impl Document {
671 final_result
688 final_result
672 }
689 }
673
690
691+ /// Prepares the Document for being closed by stopping any new writes
692+ /// and flushing through the queue of pending writes. If any fail,
693+ /// it stops early before emptying the rest of the queue.
694+ pub async fn close(&mut self) -> Option<DocumentSaveEventResult> {
695+ if self.save_sender.is_some() {
696+ self.save_sender = None;
697+ }
698+
699+ self.flush_saves_impl(true).await
700+ }
701+
674 /// Detect the programming language based on the file type.
702 /// Detect the programming language based on the file type.
675 pub fn detect_language(&mut self, config_loader: Arc<syntax::Loader>) {
703 pub fn detect_language(&mut self, config_loader: Arc<syntax::Loader>) {
676 if let Some(path) = &self.path {
704 if let Some(path) = &self.path {
@@ -1023,6 +1051,11 @@ impl Document {
1023 let history = self.history.take();
1051 let history = self.history.take();
1024 let current_revision = history.current_revision();
1052 let current_revision = history.current_revision();
1025 self.history.set(history);
1053 self.history.set(history);
1054+ log::debug!(
1055+ "modified - last saved: {}, current: {}",
1056+ self.last_saved_revision,
1057+ current_revision
1058+ );
1026 current_revision != self.last_saved_revision || !self.changes.is_empty()
1059 current_revision != self.last_saved_revision || !self.changes.is_empty()
1027 }
1060 }
1028
1061
@@ -1036,9 +1069,20 @@ impl Document {
1036
1069
1037 /// Set the document's latest saved revision to the given one.
1070 /// Set the document's latest saved revision to the given one.
1038 pub fn set_last_saved_revision(&mut self, rev: usize) {
1071 pub fn set_last_saved_revision(&mut self, rev: usize) {
1072+ log::debug!(
1073+ "doc {} revision updated {} -> {}",
1074+ self.id,
1075+ self.last_saved_revision,
1076+ rev
1077+ );
1039 self.last_saved_revision = rev;
1078 self.last_saved_revision = rev;
1040 }
1079 }
1041
1080
1081+ /// Get the document's latest saved revision.
1082+ pub fn get_last_saved_revision(&mut self) -> usize {
1083+ self.last_saved_revision
1084+ }
1085+
1042 /// Get the current revision number
1086 /// Get the current revision number
1043 pub fn get_current_revision(&mut self) -> usize {
1087 pub fn get_current_revision(&mut self) -> usize {
1044 let history = self.history.take();
1088 let history = self.history.take();
helix-view/src/editor.rs+5
@@ -1101,6 +1101,11 @@ impl Editor {
1101 None => return Err(CloseError::DoesNotExist),
1101 None => return Err(CloseError::DoesNotExist),
1102 };
1102 };
1103
1103
1104+ // flush out any pending writes first to clear the modified status
1105+ if let Some(save_result) = doc.try_flush_saves().await {
1106+ save_result?;
1107+ }
1108+
1104 if !force && doc.is_modified() {
1109 if !force && doc.is_modified() {
1105 return Err(CloseError::BufferModified(doc.display_name().into_owned()));
1110 return Err(CloseError::BufferModified(doc.display_name().into_owned()));
1106 }
1111 }