cleanup when tab is closed

This commit is contained in:
Dongdong Zhou 2020-11-05 10:30:27 +00:00
parent b6a3c25529
commit 71cb0cd0af
7 changed files with 110 additions and 16 deletions

View File

@ -77,8 +77,6 @@ pub struct Buffer {
highlight_names: Vec<String>,
pub highlights: Vec<(usize, usize, Highlight)>,
pub line_highlights: HashMap<usize, Vec<(usize, usize, String)>>,
// pub highlight_version: String,
// event_sink: ExtEventSink,
undos: Vec<Vec<(RopeDelta, RopeDelta)>>,
current_undo: usize,
pub path: String,

View File

@ -165,6 +165,7 @@ pub enum LapceUICommand {
NewTab,
NextTab,
PreviousTab,
CloseBuffers(Vec<BufferId>),
RequestPaintRect(Rect),
ApplyEdits(u64, Vec<TextEdit>),
UpdateHighlights(BufferId, u64, Vec<(usize, usize, Highlight)>),

View File

@ -756,6 +756,22 @@ pub struct EditorSplitState {
pub diagnostics: HashMap<String, Vec<Diagnostic>>,
}
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<LapceUIState, Box<dyn Widget<LapceUIState>>>,
}
impl Drop for EditorView {
fn drop(&mut self) {
println!("now drop editor view");
}
}
impl EditorView {
pub fn new(
window_id: WindowId,

View File

@ -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<String, Arc<Mutex<LspClient>>>,
}
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<u64, Callback>,
options: Option<Value>,
process: LspProcess,
pub server_capabilities: Option<ServerCapabilities>,
pub opened_documents: HashMap<BufferId, Url>,
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) => {

View File

@ -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<Plugin>,
}
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,
};

View File

@ -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()]);

View File

@ -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<LapceUIState> 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();
}