From df2c3df125a18ed5ec83698f2e2472502f23716b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9=20Heuillet?= Date: Wed, 20 Jul 2022 14:08:56 +0200 Subject: [PATCH] Store unsaved_buffers and fetch it on startup --- lapce-data/src/data.rs | 68 ++++++++++++++++++++++++++++++++++++ lapce-data/src/db.rs | 78 ++++++++++++++++++++++++++++++++++++++++-- lapce-ui/src/app.rs | 14 ++++++++ 3 files changed, 158 insertions(+), 2 deletions(-) diff --git a/lapce-data/src/data.rs b/lapce-data/src/data.rs index 3a3c249a..5f164419 100644 --- a/lapce-data/src/data.rs +++ b/lapce-data/src/data.rs @@ -612,6 +612,16 @@ pub fn new( let search = Arc::new(SearchData::new()); let file_picker = Arc::new(FilePickerData::new()); + let mut unsaved_buffers = match db.get_unsaved_buffers() { + Ok(val) => val, + Err(err) => { + log::warn!("Error during unsaved buffer fetching : {:}", err); + im::HashMap::new() + } + }; + + unsaved_buffers.clear(); + let mut main_split = LapceMainSplitData::new( tab_id, workspace_info.as_ref(), @@ -621,7 +631,33 @@ pub fn new( event_sink.clone(), Arc::new(workspace.clone()), db.clone(), + unsaved_buffers, ); + + let unsaved_buffers = match db.get_unsaved_buffers() { + Ok(val) => val, + Err(err) => { + log::warn!("Error during unsaved buffer fetching : {:}", err); + im::HashMap::new() + } + }; + + for (doc_path, doc) in main_split.open_docs.iter_mut() { + let doc_path_string = doc_path.to_str().unwrap().to_string(); + // if doc_path_string.contains("main.go") { + // println!("SKIPPING"); + // continue; + // } + let val = match unsaved_buffers.get(&doc_path_string) { + Some(val) => val, + None => continue, + }; + + let new_rope = Rope::from(val); + + Arc::make_mut(doc).buffer_mut().init_content(new_rope); + } + main_split.add_editor( source_control.editor_view_id, None, @@ -676,6 +712,34 @@ pub fn new( .unwrap_or_else(|| PanelData::new(panel_orders)); let focus = (*main_split.active).unwrap_or(*main_split.split_id); + + // if unsave_buffers.is_ok() { + // let unsave_buffers = unsave_buffers.unwrap(); + + // for (path, doc) in main_split.open_docs.iter() { + // for (path_buf, content) in &unsave_buffers { + // let path_buf = PathBuf::from(path_buf); + // if path == &path_buf { + // let doc = main_split.open_docs.get_mut(&path_buf).unwrap(); + // let new_rope = Rope::from(content); + // doc.init_content(new_rope); + + // // main_split.open_docs.insert(path_buf, Arc::new(doc)); + // } + // } + // println!( + // "Current new lapceTabData: {:?} {:?}", + // path, + // doc.buffer().text() + // ); + // } + // } else { + // log::warn!( + // "Error during unsaved buffer fetching : {:?}", + // unsave_buffers.unwrap_err() + // ); + // } + let mut tab = Self { id: tab_id, multiple_tab: false, @@ -1898,6 +1962,7 @@ pub fn document_save( exit_widget_id: Option, ) { let doc = self.open_docs.get(path).unwrap(); + println!("DOCUMENT SAVE:\n {:?}", doc.buffer().text()); let rev = doc.rev(); let buffer_id = doc.id(); let event_sink = ctx.get_external_handle(); @@ -2575,6 +2640,7 @@ pub fn new( event_sink: ExtEventSink, workspace: Arc, db: Arc, + unsaved_buffers: im::HashMap, ) -> Self { let split_id = Arc::new(WidgetId::next()); @@ -2646,6 +2712,7 @@ pub fn new( tab_id, config, event_sink, + unsaved_buffers, ); main_split_data.split_id = Arc::new(split_data.widget_id); for (path, locations) in positions.into_iter() { @@ -3245,6 +3312,7 @@ pub fn set_editor_tab( } } +/// The actual Editor tab structure, holding the windows. #[derive(Clone, Debug)] pub struct LapceEditorTabData { pub widget_id: WidgetId, diff --git a/lapce-data/src/db.rs b/lapce-data/src/db.rs index dbbeaf5d..bc04bbcf 100644 --- a/lapce-data/src/db.rs +++ b/lapce-data/src/db.rs @@ -54,6 +54,7 @@ pub fn to_data( tab_id: WidgetId, config: &Config, event_sink: ExtEventSink, + unsaved_buffers: im::HashMap, ) -> SplitContent { match &self { SplitContentInfo::EditorTab(tab_info) => { @@ -64,6 +65,7 @@ pub fn to_data( tab_id, config, event_sink, + unsaved_buffers, ); SplitContent::EditorTab(tab_data.widget_id) } @@ -75,6 +77,7 @@ pub fn to_data( tab_id, config, event_sink, + unsaved_buffers, ); SplitContent::Split(split_data.widget_id) } @@ -98,6 +101,7 @@ pub fn to_data( tab_id: WidgetId, config: &Config, event_sink: ExtEventSink, + unsaved_buffers: im::HashMap, ) -> LapceEditorTabData { let editor_tab_id = WidgetId::next(); let editor_tab_data = LapceEditorTabData { @@ -115,6 +119,7 @@ pub fn to_data( tab_id, config, event_sink.clone(), + unsaved_buffers.clone(), ) }) .collect(), @@ -148,6 +153,7 @@ pub fn to_data( tab_id: WidgetId, config: &Config, event_sink: ExtEventSink, + unsaved_buffers: im::HashMap, ) -> EditorTabChild { match &self { EditorTabChildInfo::Editor(editor_info) => { @@ -158,6 +164,7 @@ pub fn to_data( tab_id, config, event_sink, + unsaved_buffers, ); EditorTabChild::Editor( editor_data.view_id, @@ -187,6 +194,7 @@ pub fn to_data( tab_id: WidgetId, config: &Config, event_sink: ExtEventSink, + unsaved_buffers: im::HashMap, ) -> SplitData { let split_id = WidgetId::next(); let split_data = SplitData { @@ -204,6 +212,7 @@ pub fn to_data( tab_id, config, event_sink.clone(), + unsaved_buffers.clone(), ) }) .collect(), @@ -264,6 +273,7 @@ pub fn to_data( tab_id: WidgetId, config: &Config, event_sink: ExtEventSink, + unsaved_buffers: im::HashMap, ) -> LapceEditorData { let editor_data = LapceEditorData::new( None, @@ -291,12 +301,24 @@ pub fn to_data( )); if !data.open_docs.contains_key(path) { - let doc = Arc::new(Document::new( + let mut doc = Document::new( BufferContent::File(path.clone()), tab_id, event_sink, data.proxy.clone(), - )); + ); + let string_path = path.to_str().unwrap().to_string(); + if let Some(val) = unsaved_buffers.get(&string_path) { + println!( + "CURRENT SAVED BUFFER FOR PATH {}:\n {}", + string_path, val + ); + let new_rope = Rope::from(val); + + doc.buffer_mut().init_content(new_rope); + println!("AFTER VAL: {}", doc.buffer_mut().text().to_string()); + }; + let doc = Arc::new(doc); data.open_docs.insert(path.clone(), doc); } } else if let BufferContent::Scratch(id, _) = &self.content { @@ -428,6 +450,39 @@ pub fn get_workspace_info( Ok(info) } + pub fn get_unsaved_buffers(&self) -> Result> { + let sled_db = self.get_db()?; + let mut buffers = im::HashMap::new(); + let mut unsaved_paths = Vec::new(); + + for val in sled_db.iter().keys() { + let val = val.unwrap(); + let s = String::from_utf8((&val).to_vec()) + .expect("invalid utf-8 sequence retrieving unsaved buffer"); + + if s.contains("unsaved_buffer") { + unsaved_paths.push(s.clone()) + } + } + + for path in &unsaved_paths { + let res = sled_db.get(path)?; + + let res = match res { + Some(val) => val, + None => return Ok(buffers), + }; + + let s1 = String::from_utf8(res.to_vec())?; + let path_stripped = + String::from(path.strip_prefix("unsaved_buffer:").unwrap()); + + buffers.insert(path_stripped, s1); + } + + Ok(buffers) + } + pub fn get_buffer_info( &self, workspace: &LapceWorkspace, @@ -518,7 +573,26 @@ pub fn save_workspace(&self, data: &LapceTabData) -> Result<()> { let workspace = (*data.workspace).clone(); let workspace_info = data.workspace_info(); + // Buffer for auto save on quit + let main_split = &data.main_split; + self.insert_workspace(&workspace, &workspace_info)?; + self.insert_unsaved_buffer(main_split)?; + + Ok(()) + } + + fn insert_unsaved_buffer(&self, main_split: &LapceMainSplitData) -> Result<()> { + let sled_db = self.get_db()?; + + for (path, doc) in &main_split.open_docs { + let path_str = path.to_str().unwrap(); + let buf_text = doc.buffer().text().to_string(); + sled_db + .insert(format!("unsaved_buffer:{}", path_str), buf_text.as_str())?; + } + sled_db.flush()?; + Ok(()) } diff --git a/lapce-ui/src/app.rs b/lapce-ui/src/app.rs index 9a088579..5b3780a7 100644 --- a/lapce-ui/src/app.rs +++ b/lapce-ui/src/app.rs @@ -180,6 +180,7 @@ fn macos_window_desc(desc: WindowDesc) -> WindowDesc { }) } +/// The delegate handler for Top-Level Druid events (terminate, new window, etc.) struct LapceAppDelegate {} impl LapceAppDelegate { @@ -203,6 +204,7 @@ fn event( data: &mut LapceData, _env: &Env, ) -> Option { + //FIXME: no event::aplicationWillTerminate is sent. if let Event::ApplicationWillTerminate = event { let _ = data.db.save_app(data); return None; @@ -217,8 +219,20 @@ fn window_removed( _env: &Env, _ctx: &mut druid::DelegateCtx, ) { + println!("Removing window!"); if let Some(window) = data.windows.remove(&id) { + // let tmp = window.tabs.get(&window.active_id).unwrap(); + // let tmp = tmp.main_split.active_editor().unwrap(); + // println!("Buffer value: {:?}", tmp.content); for (_, tab) in window.tabs.iter() { + let split = &tab.main_split; + for (path, open_doc) in &split.open_docs { + println!( + "PATH: {:?}\nContent: {:?}", + path, + open_doc.buffer().text() + ); + } let _ = data.db.save_workspace(tab); } data.db.save_last_window(&window);