From 3f707c19f46284d745568c632a57103eb1be4dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Fri, 30 Oct 2020 17:00:30 +0900 Subject: [PATCH] Save command --- Cargo.lock | 1 + helix-term/src/main.rs | 12 +++--------- helix-view/Cargo.toml | 2 ++ helix-view/src/commands.rs | 12 ++++++++++-- helix-view/src/document.rs | 25 +++++++++++++++++++++++++ 5 files changed, 41 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28fc503cb..e89696adf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -523,6 +523,7 @@ dependencies = [ "crossterm", "helix-core", "once_cell", + "smol", "tui", "url", ] diff --git a/helix-term/src/main.rs b/helix-term/src/main.rs index f91c1c8f4..9378d3eef 100644 --- a/helix-term/src/main.rs +++ b/helix-term/src/main.rs @@ -70,16 +70,10 @@ fn main() -> Result<(), Error> { std::thread::spawn(move || smol::block_on(EX.run(smol::future::pending::<()>()))); } - // let mut lsp = helix_lsp::Client::start(&EX, "rust-analyzer", &[]); + let mut app = Application::new(args, &EX).unwrap(); - smol::block_on(async { - // let res = lsp.initialize().await; - // let state = helix_core::State::load("test.rs".into(), &[]).unwrap(); - // let res = lsp.text_document_did_open(&state).await; - // loop {} - - Application::new(args, &EX).unwrap().run().await; - }); + // we use the thread local executor to spawn the application task separately from the work pool + smol::block_on(app.run()); Ok(()) } diff --git a/helix-view/Cargo.toml b/helix-view/Cargo.toml index 9d53f929d..0a48b7217 100644 --- a/helix-view/Cargo.toml +++ b/helix-view/Cargo.toml @@ -20,3 +20,5 @@ tui = { git = "https://github.com/fdehau/tui-rs", default-features = false, feat crossterm = { version = "0.18", features = ["event-stream"], optional = true} once_cell = "1.4" url = "2" + +smol = "1" diff --git a/helix-view/src/commands.rs b/helix-view/src/commands.rs index 26c7a1901..c135a3da2 100644 --- a/helix-view/src/commands.rs +++ b/helix-view/src/commands.rs @@ -331,8 +331,7 @@ pub fn append_mode(cx: &mut Context) { } // TODO: I, A, o and O can share a lot of the primitives. - -pub fn command_mode(_view: &mut View, _count: usize) { +pub fn command_mode(_cx: &mut Context) { unimplemented!() } @@ -670,3 +669,12 @@ pub fn indent_selection(_cx: &mut Context) { // loop over each line and recompute proper indentation unimplemented!() } + +// + +pub fn save(cx: &mut Context) { + // Spawns an async task to actually do the saving. This way we prevent blocking. + + // TODO: handle save errors somehow? + cx.executor.spawn(cx.view.doc.save()).detach(); +} diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index 710ea4f83..1587de8b5 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -1,4 +1,5 @@ use anyhow::Error; +use std::future::Future; use std::path::PathBuf; use helix_core::{ @@ -97,6 +98,30 @@ impl Document { Ok(doc) } + pub fn save(&self) -> impl Future> { + // we clone and move text + path into the future so that we asynchronously save the current + // state without blocking any further edits. + + let text = self.text().clone(); + let path = self.path.clone().expect("Can't save with no path set!"); // TODO: handle no path + + // TODO: mark changes up to now as saved + // TODO: mark dirty false + + async move { + use smol::{fs::File, prelude::*}; + let mut file = File::create(path).await?; + + // write all the rope chunks to file + for chunk in text.chunks() { + file.write_all(chunk.as_bytes()).await?; + } + // TODO: flush? + + Ok(()) + } // and_then(// lsp.send_text_saved_notification()) + } + pub fn set_language(&mut self, scope: &str, scopes: &[String]) { if let Some(language_config) = LOADER.language_config_for_scope(scope) { let highlight_config = language_config.highlight_config(scopes).unwrap().unwrap();