From 6c0084e164366df22acdd3c8438e0b84f352c58b Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Mon, 23 Nov 2020 18:08:06 +0000 Subject: [PATCH] save on proxy --- core/src/command.rs | 3 +++ core/src/editor.rs | 47 +++++++++++++++++++++++++++++++++++++++++++ core/src/proxy.rs | 10 +++++++++ core/src/split.rs | 9 +++++++++ proxy/src/buffer.rs | 27 ++++++++++++++++++++++++- proxy/src/dispatch.rs | 9 +++++++++ 6 files changed, 104 insertions(+), 1 deletion(-) diff --git a/core/src/command.rs b/core/src/command.rs index 380719d0..bf50ec8c 100644 --- a/core/src/command.rs +++ b/core/src/command.rs @@ -1,7 +1,9 @@ use std::collections::HashMap; +use anyhow::Result; use druid::{Rect, Selector, Size, WidgetId}; use lsp_types::{Location, TextEdit}; +use serde_json::Value; use strum; use strum_macros::{Display, EnumProperty, EnumString}; use tree_sitter_highlight::Highlight; @@ -186,6 +188,7 @@ pub enum LapceUICommand { CloseBuffers(Vec), RequestPaintRect(Rect), ApplyEdits(usize, u64, Vec), + ApplyEditsAndSave(usize, u64, Result), UpdateHighlights(BufferId, u64, Vec<(usize, usize, Highlight)>), CenterOfWindow, UpdateLineChanges(BufferId), diff --git a/core/src/editor.rs b/core/src/editor.rs index 296510fc..9c445560 100644 --- a/core/src/editor.rs +++ b/core/src/editor.rs @@ -50,6 +50,7 @@ }; use serde_json::Value; use std::str::FromStr; +use std::sync::mpsc::channel; use std::thread; use std::{cmp::Ordering, iter::Iterator, path::PathBuf}; use std::{collections::HashMap, sync::Arc}; @@ -1598,6 +1599,26 @@ pub fn request_layout(&self) { ); } + pub fn apply_edits_and_save( + &mut self, + ctx: &mut EventCtx, + ui_state: &mut LapceUIState, + offset: usize, + rev: u64, + result: &Result, + ) -> Option<()> { + if let Ok(res) = result { + let edits: Result, serde_json::Error> = + serde_json::from_value(res.clone()); + if let Ok(edits) = edits { + if edits.len() > 0 { + self.apply_edits(ctx, ui_state, rev, &edits); + } + } + } + None + } + pub fn apply_edits( &mut self, ctx: &mut EventCtx, @@ -2323,7 +2344,33 @@ pub fn run_command( let editor = self.editors.get_mut(&self.active)?; let buffer_id = editor.buffer_id.clone()?; let buffer = self.buffers.get_mut(&buffer_id)?; + let window_id = self.window_id; + let tab_id = self.tab_id; let rev = buffer.rev; + let offset = editor.selection.get_cursor_offset(); + let state = + LAPCE_APP_STATE.get_tab_state(&self.window_id, &self.tab_id); + state + .clone() + .proxy + .lock() + .as_ref() + .unwrap() + .get_document_formatting( + buffer.id, + Box::new(move |result| { + let result = match result { + Ok(r) => Ok(r), + Err(e) => Err(anyhow!("{:?}", e)), + }; + LAPCE_APP_STATE.submit_ui_command( + LapceUICommand::ApplyEditsAndSave( + offset, rev, result, + ), + state.editor_split.lock().widget_id, + ); + }), + ); // if let Some(edits) = { // let state = diff --git a/core/src/proxy.rs b/core/src/proxy.rs index 37314d14..aa2dde43 100644 --- a/core/src/proxy.rs +++ b/core/src/proxy.rs @@ -66,6 +66,16 @@ pub fn update(&self, buffer_id: BufferId, delta: &RopeDelta, rev: u64) { ) } + pub fn save(&self, rev: u64, buffer_id: BufferId, f: Box) { + self.peer.send_rpc_request_async( + "save", + &json!({ + "buffer_id": buffer_id, + }), + f, + ); + } + pub fn get_completion( &self, request_id: usize, diff --git a/core/src/split.rs b/core/src/split.rs index 2de54804..fd4e4a4d 100644 --- a/core/src/split.rs +++ b/core/src/split.rs @@ -205,6 +205,15 @@ fn event( } editor_split.apply_edits(ctx, data, *rev, edits); } + LapceUICommand::ApplyEditsAndSave(offset, rev, result) => { + LAPCE_APP_STATE + .get_tab_state(&self.window_id, &self.tab_id) + .editor_split + .lock() + .apply_edits_and_save( + ctx, data, *offset, *rev, result, + ); + } LapceUICommand::GotoLocation(location) => { let state = LAPCE_APP_STATE .get_tab_state(&self.window_id, &self.tab_id); diff --git a/proxy/src/buffer.rs b/proxy/src/buffer.rs index cbe65beb..1d3ea237 100644 --- a/proxy/src/buffer.rs +++ b/proxy/src/buffer.rs @@ -1,9 +1,12 @@ -use anyhow::Result; +use anyhow::{anyhow, Result}; use crossbeam_channel::Sender; use std::borrow::Cow; +use std::ffi::OsString; use std::fs::File; use std::io::Read; +use std::io::Write; use std::path::PathBuf; +use std::{fs, str::FromStr}; use lsp_types::*; use serde::{Deserialize, Deserializer, Serialize}; @@ -46,6 +49,28 @@ pub fn new( } } + pub fn save(&self, rev: u64) -> Result<()> { + if self.rev != rev { + return Err(anyhow!("not the right rev")); + } + let tmp_extension = self.path.extension().map_or_else( + || OsString::from("swp"), + |ext| { + let mut ext = ext.to_os_string(); + ext.push(".swp"); + ext + }, + ); + let tmp_path = &self.path.with_extension(tmp_extension); + + let mut f = File::create(tmp_path)?; + for chunk in self.rope.iter_chunks(..self.rope.len()) { + f.write_all(chunk.as_bytes())?; + } + fs::rename(tmp_path, &self.path)?; + Ok(()) + } + pub fn update( &mut self, delta: &RopeDelta, diff --git a/proxy/src/dispatch.rs b/proxy/src/dispatch.rs index d8b6e667..1b9526a8 100644 --- a/proxy/src/dispatch.rs +++ b/proxy/src/dispatch.rs @@ -61,6 +61,10 @@ pub enum Request { GetDocumentFormatting { buffer_id: BufferId, }, + Save { + rev: u64, + buffer_id: BufferId, + }, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -235,6 +239,11 @@ fn handle_request(&self, id: RequestId, rpc: Request) { let buffer = buffers.get(&buffer_id).unwrap(); self.lsp.lock().get_document_formatting(id, buffer); } + Request::Save { rev, buffer_id } => { + let buffers = self.buffers.lock(); + let buffer = buffers.get(&buffer_id).unwrap(); + self.respond(id, buffer.save(rev).map(|r| json!({}))); + } } } }