From 71cb0cd0afeeabfa2b378847105cc9035ba6b058 Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Thu, 5 Nov 2020 10:30:27 +0000 Subject: [PATCH] cleanup when tab is closed --- core/src/buffer.rs | 2 -- core/src/command.rs | 1 + core/src/editor.rs | 22 ++++++++++++++++++++++ core/src/lsp.rs | 40 ++++++++++++++++++++++++++++++++++------ core/src/plugin.rs | 36 +++++++++++++++++++++++++++++------- core/src/state.rs | 5 +++++ core/src/window.rs | 20 +++++++++++++++++++- 7 files changed, 110 insertions(+), 16 deletions(-) diff --git a/core/src/buffer.rs b/core/src/buffer.rs index 5b0516b0..f7f08ae1 100644 --- a/core/src/buffer.rs +++ b/core/src/buffer.rs @@ -77,8 +77,6 @@ pub struct Buffer { highlight_names: Vec, pub highlights: Vec<(usize, usize, Highlight)>, pub line_highlights: HashMap>, - // pub highlight_version: String, - // event_sink: ExtEventSink, undos: Vec>, current_undo: usize, pub path: String, diff --git a/core/src/command.rs b/core/src/command.rs index 95559f60..dd7d743f 100644 --- a/core/src/command.rs +++ b/core/src/command.rs @@ -165,6 +165,7 @@ pub enum LapceUICommand { NewTab, NextTab, PreviousTab, + CloseBuffers(Vec), RequestPaintRect(Rect), ApplyEdits(u64, Vec), UpdateHighlights(BufferId, u64, Vec<(usize, usize, Highlight)>), diff --git a/core/src/editor.rs b/core/src/editor.rs index b0d1c6c0..63c80b55 100644 --- a/core/src/editor.rs +++ b/core/src/editor.rs @@ -756,6 +756,22 @@ pub struct EditorSplitState { pub diagnostics: HashMap>, } +impl Drop for EditorSplitState { + fn drop(&mut self) { + LAPCE_APP_STATE + .ui_sink + .lock() + .as_ref() + .unwrap() + .submit_command( + LAPCE_UI_COMMAND, + LapceUICommand::CloseBuffers(self.buffers.keys().cloned().collect()), + Target::Window(self.window_id), + ); + println!("now drop editor split state"); + } +} + impl EditorSplitState { pub fn new(window_id: WindowId, tab_id: WidgetId) -> EditorSplitState { let editor_split_id = WidgetId::next(); @@ -2154,6 +2170,12 @@ pub struct EditorView { header: WidgetPod>>, } +impl Drop for EditorView { + fn drop(&mut self) { + println!("now drop editor view"); + } +} + impl EditorView { pub fn new( window_id: WindowId, diff --git a/core/src/lsp.rs b/core/src/lsp.rs index 6950548e..669ecb0a 100644 --- a/core/src/lsp.rs +++ b/core/src/lsp.rs @@ -15,7 +15,7 @@ io::BufWriter, io::Write, process::Command, - process::{self, Stdio}, + process::{self, Child, Stdio}, sync::mpsc::{channel, Receiver}, sync::Arc, thread, @@ -48,12 +48,23 @@ pub enum LspHeader { ContentLength(usize), } +pub enum LspProcess { + Child(Child), + SshSession(SshSession), +} + pub struct LspCatalog { window_id: WindowId, tab_id: WidgetId, clients: HashMap>>, } +impl Drop for LspCatalog { + fn drop(&mut self) { + println!("now drop lsp catalog"); + } +} + impl LspCatalog { pub fn new(window_id: WindowId, tab_id: WidgetId) -> LspCatalog { LspCatalog { @@ -63,6 +74,19 @@ pub fn new(window_id: WindowId, tab_id: WidgetId) -> LspCatalog { } } + pub fn stop(&self) { + for (_, client) in self.clients.iter() { + match &mut client.lock().process { + LspProcess::Child(child) => { + child.kill(); + } + LspProcess::SshSession(ssh_session) => { + ssh_session.session.disconnect(None, "closing down", None); + } + } + } + } + pub fn start_server( &mut self, exec_path: &str, @@ -203,6 +227,7 @@ pub struct LspClient { next_id: u64, pending: HashMap, options: Option, + process: LspProcess, pub server_capabilities: Option, pub opened_documents: HashMap, pub is_initialized: bool, @@ -222,12 +247,14 @@ pub fn new( .expect("Error Occurred"); let writer = Box::new(BufWriter::new(process.stdin.take().unwrap())); + let stdout = process.stdout.take().unwrap(); let lsp_client = Arc::new(Mutex::new(LspClient { window_id, tab_id, writer, next_id: 0, + process: LspProcess::Child(process), pending: HashMap::new(), server_capabilities: None, opened_documents: HashMap::new(), @@ -236,16 +263,16 @@ pub fn new( })); let local_lsp_client = lsp_client.clone(); - let mut stdout = process.stdout; thread::spawn(move || { - let mut reader = Box::new(BufReader::new(stdout.take().unwrap())); + let mut reader = Box::new(BufReader::new(stdout)); loop { match read_message(&mut reader) { Ok(message_str) => { local_lsp_client.lock().handle_message(message_str.as_ref()); } Err(err) => { - // eprintln!("Error occurred {:?}", err); + eprintln!("lsp read Error occurred {:?}", err); + return; } }; } @@ -266,6 +293,7 @@ pub fn new_ssh( ssh_session.channel_exec(&mut channel, exec_path)?; println!("lsp {}", exec_path); let writer = Box::new(ssh_session.get_stream(&channel)); + let reader = ssh_session.get_stream(&channel); let lsp_client = Arc::new(Mutex::new(LspClient { window_id, tab_id, @@ -273,6 +301,7 @@ pub fn new_ssh( next_id: 0, pending: HashMap::new(), server_capabilities: None, + process: LspProcess::SshSession(ssh_session), opened_documents: HashMap::new(), is_initialized: false, options, @@ -281,8 +310,7 @@ pub fn new_ssh( let local_lsp_client = lsp_client.clone(); // let reader = ssh_session.get_async_stream(channel.stream(0))?; thread::spawn(move || { - let mut reader = - Box::new(BufReader::new(ssh_session.get_stream(&channel))); + let mut reader = Box::new(BufReader::new(reader)); loop { match read_message(&mut reader) { Ok(message_str) => { diff --git a/core/src/plugin.rs b/core/src/plugin.rs index 31c0d52e..d298d59b 100644 --- a/core/src/plugin.rs +++ b/core/src/plugin.rs @@ -33,6 +33,11 @@ #[derive(Eq, PartialEq, Hash, Clone, Debug, Serialize, Deserialize)] pub struct PluginId(pub usize); +pub enum PluginProcess { + Child(Child), + SshSession(SshSession), +} + pub struct PluginCatalog { window_id: WindowId, tab_id: WidgetId, @@ -42,6 +47,12 @@ pub struct PluginCatalog { running: Vec, } +impl Drop for PluginCatalog { + fn drop(&mut self) { + println!("now drop plugin catalog"); + } +} + pub struct PluginHandler { window_id: WindowId, tab_id: WidgetId, @@ -59,7 +70,7 @@ pub struct Plugin { peer: RpcPeer, id: PluginId, name: String, - // process: Child, + process: PluginProcess, } impl Drop for Plugin { @@ -160,6 +171,19 @@ pub fn load_from_paths(&mut self, paths: &[PathBuf]) -> Result<()> { Ok(()) } + pub fn stop(&mut self) { + for plugin in self.running.iter_mut() { + match &mut plugin.process { + PluginProcess::Child(child) => { + child.kill(); + } + PluginProcess::SshSession(ssh) => { + ssh.session.disconnect(None, "closing down", None); + } + } + } + } + pub fn start_all(&mut self) -> Result<()> { let state = LAPCE_APP_STATE.get_tab_state(&self.window_id, &self.tab_id); let workspace_type = state.workspace.lock().kind.clone(); @@ -299,9 +323,10 @@ fn start_plugin_ssh( let mut looper = RpcLoop::new(ssh_session.get_stream(&channel)); let peer: RpcPeer = Box::new(looper.get_raw_peer()); let name = plugin_desc.name.clone(); + let read_stream = ssh_session.get_stream(&channel); let plugin = Plugin { peer, - //process: child, + process: PluginProcess::SshSession(ssh_session), name, id, }; @@ -313,10 +338,7 @@ fn start_plugin_ssh( // let reader = ssh_session.get_async_stream(channel.stream(0))?; let mut handler = PluginHandler { window_id, tab_id }; - if let Err(e) = looper.mainloop( - || BufReader::new(ssh_session.get_stream(&channel)), - &mut handler, - ) { + if let Err(e) = looper.mainloop(|| BufReader::new(read_stream), &mut handler) { println!("plugin main loop failed {} {:?}", e, plugin_desc.dir); } println!("plugin main loop exit {:?}", plugin_desc.dir); @@ -355,7 +377,7 @@ fn start_plugin_process( let name = plugin_desc.name.clone(); let plugin = Plugin { peer, - //process: child, + process: PluginProcess::Child(child), name, id, }; diff --git a/core/src/state.rs b/core/src/state.rs index 6c04569a..51c2be30 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -333,6 +333,11 @@ pub fn new(window_id: WindowId) -> LapceTabState { state } + pub fn stop(&self) { + self.plugins.lock().stop(); + self.lsp.lock().stop(); + } + pub fn start_plugin(&self) { let mut plugins = self.plugins.lock(); plugins.reload_from_paths(&[PathBuf::from_str("./lsp").unwrap()]); diff --git a/core/src/window.rs b/core/src/window.rs index 6d18e468..ba078ef9 100644 --- a/core/src/window.rs +++ b/core/src/window.rs @@ -45,6 +45,19 @@ pub fn new(window_id: WindowId, tab_id: WidgetId) -> LapceTab { } } +impl Drop for LapceTab { + fn drop(&mut self) { + println!("now drop tab"); + let state = LAPCE_APP_STATE.get_tab_state(&self.window_id, &self.tab_id); + state.stop(); + LAPCE_APP_STATE + .get_window_state(&self.window_id) + .states + .lock() + .remove(&self.tab_id); + } +} + impl Widget for LapceTab { fn event( &mut self, @@ -184,6 +197,11 @@ fn event( _ if cmd.is(LAPCE_UI_COMMAND) => { let command = cmd.get_unchecked(LAPCE_UI_COMMAND); match command { + LapceUICommand::CloseBuffers(buffer_ids) => { + for buffer_id in buffer_ids { + Arc::make_mut(&mut data.buffers).remove(buffer_id); + } + } LapceUICommand::NewTab => { let state = LapceTabState::new(self.window_id.clone()); for (_, editor) in @@ -229,7 +247,7 @@ fn event( }; let new_active = self.tabs[new_index].widget().tab_id; self.tabs.remove(index); - window_state.states.lock().remove(&active); + //window_state.states.lock().remove(&active); *active = new_active; ctx.request_layout(); }