aboutsummaryrefslogtreecommitdiff
path: root/helix-term
diff options
context:
space:
mode:
Diffstat (limited to 'helix-term')
-rw-r--r--helix-term/src/application.rs20
-rw-r--r--helix-term/src/commands.rs3
-rw-r--r--helix-term/src/commands/typed.rs88
-rw-r--r--helix-term/src/compositor.rs22
4 files changed, 92 insertions, 41 deletions
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index 2e49e6d1..6010e745 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -1,5 +1,5 @@
use arc_swap::{access::Map, ArcSwap};
-use futures_util::Stream;
+use futures_util::{Stream, StreamExt};
use helix_core::{
diagnostic::{DiagnosticTag, NumberOrString},
path::get_relative_path,
@@ -968,6 +968,24 @@ impl Application {
// errors along the way
let mut errs = Vec::new();
+ // TODO: deduplicate with ctx.block_try_flush_writes
+ tokio::task::block_in_place(|| {
+ helix_lsp::block_on(async {
+ while let Some(save_event) = self.editor.save_queue.next().await {
+ match &save_event {
+ Ok(event) => {
+ let doc = doc_mut!(self.editor, &event.doc_id);
+ doc.set_last_saved_revision(event.revision);
+ }
+ Err(err) => {
+ log::error!("error saving document: {}", err);
+ }
+ };
+ // TODO: if is_err: break?
+ }
+ })
+ });
+
if let Err(err) = self
.jobs
.finish(&mut self.editor, Some(&mut self.compositor))
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index f6d583f5..87bbd6c6 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -2541,7 +2541,8 @@ async fn make_format_callback(
}
if let Some((path, force)) = write {
- if let Err(err) = doc.save(path, force) {
+ let id = doc.id();
+ if let Err(err) = editor.save(id, path, force) {
editor.set_error(format!("Error saving: {}", err));
}
}
diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs
index 070215cb..ef774256 100644
--- a/helix-term/src/commands/typed.rs
+++ b/helix-term/src/commands/typed.rs
@@ -79,12 +79,28 @@ fn buffer_close_by_ids_impl(
doc_ids: &[DocumentId],
force: bool,
) -> anyhow::Result<()> {
+ // TODO: deduplicate with ctx.block_try_flush_writes
+ tokio::task::block_in_place(|| {
+ helix_lsp::block_on(async {
+ while let Some(save_event) = editor.save_queue.next().await {
+ match &save_event {
+ Ok(event) => {
+ let doc = doc_mut!(editor, &event.doc_id);
+ doc.set_last_saved_revision(event.revision);
+ }
+ Err(err) => {
+ log::error!("error saving document: {}", err);
+ }
+ };
+ // TODO: if is_err: break?
+ }
+ })
+ });
+
let (modified_ids, modified_names): (Vec<_>, Vec<_>) = doc_ids
.iter()
.filter_map(|&doc_id| {
- if let Err(CloseError::BufferModified(name)) = tokio::task::block_in_place(|| {
- helix_lsp::block_on(editor.close_document(doc_id, force))
- }) {
+ if let Err(CloseError::BufferModified(name)) = editor.close_document(doc_id, force) {
Some((doc_id, name))
} else {
None
@@ -289,7 +305,8 @@ fn write_impl(
};
if fmt.is_none() {
- doc.save(path, force)?;
+ let id = doc.id();
+ cx.editor.save(id, path, force)?;
}
Ok(())
@@ -569,40 +586,45 @@ fn write_all_impl(
return Ok(());
}
- let mut errors: Option<String> = None;
+ let mut errors: Vec<&'static str> = Vec::new();
let auto_format = cx.editor.config().auto_format;
let jobs = &mut cx.jobs;
// save all documents
- for doc in &mut cx.editor.documents.values_mut() {
- if doc.path().is_none() {
- errors = errors
- .or_else(|| Some(String::new()))
- .map(|mut errs: String| {
- errs.push_str("cannot write a buffer without a filename\n");
- errs
- });
-
- continue;
- }
+ let saves: Vec<_> = cx
+ .editor
+ .documents
+ .values()
+ .filter_map(|doc| {
+ if doc.path().is_none() {
+ errors.push("cannot write a buffer without a filename\n");
+ return None;
+ }
- if !doc.is_modified() {
- continue;
- }
+ if !doc.is_modified() {
+ return None;
+ }
- let fmt = if auto_format {
- doc.auto_format().map(|fmt| {
- let callback =
- make_format_callback(doc.id(), doc.version(), fmt, Some((None, force)));
- jobs.add(Job::with_callback(callback).wait_before_exiting());
- })
- } else {
+ let fmt = if auto_format {
+ doc.auto_format().map(|fmt| {
+ let callback =
+ make_format_callback(doc.id(), doc.version(), fmt, Some((None, force)));
+ jobs.add(Job::with_callback(callback).wait_before_exiting());
+ })
+ } else {
+ None
+ };
+
+ if fmt.is_none() {
+ return Some(doc.id());
+ }
None
- };
+ })
+ .collect();
- if fmt.is_none() {
- doc.save::<PathBuf>(None, force)?;
- }
+ // manually call save for the rest of docs that don't have a formatter
+ for id in saves {
+ cx.editor.save::<PathBuf>(id, None, force)?;
}
if quit {
@@ -619,10 +641,8 @@ fn write_all_impl(
}
}
- if let Some(errs) = errors {
- if !force {
- bail!(errs);
- }
+ if !errors.is_empty() && !force {
+ bail!("{:?}", errors);
}
Ok(())
diff --git a/helix-term/src/compositor.rs b/helix-term/src/compositor.rs
index 35b9d054..a4ffaff2 100644
--- a/helix-term/src/compositor.rs
+++ b/helix-term/src/compositor.rs
@@ -1,3 +1,4 @@
+use futures_util::StreamExt;
// Each component declares it's own size constraints and gets fitted based on it's parent.
// Q: how does this work with popups?
// cursive does compositor.screen_mut().add_layer_at(pos::absolute(x, y), <component>)
@@ -33,11 +34,22 @@ impl<'a> Context<'a> {
pub fn block_try_flush_writes(&mut self) -> anyhow::Result<()> {
tokio::task::block_in_place(|| helix_lsp::block_on(self.jobs.finish(self.editor, None)))?;
- for doc in &mut self.editor.documents.values_mut() {
- tokio::task::block_in_place(|| helix_lsp::block_on(doc.try_flush_saves()))
- .map(|result| result.map(|_| ()))
- .unwrap_or(Ok(()))?;
- }
+ tokio::task::block_in_place(|| {
+ helix_lsp::block_on(async {
+ while let Some(save_event) = self.editor.save_queue.next().await {
+ match &save_event {
+ Ok(event) => {
+ let doc = doc_mut!(self.editor, &event.doc_id);
+ doc.set_last_saved_revision(event.revision);
+ }
+ Err(err) => {
+ log::error!("error saving document: {}", err);
+ }
+ };
+ // TODO: if is_err: break?
+ }
+ })
+ });
Ok(())
}