diff options
Diffstat (limited to 'helix-term/src/application.rs')
-rw-r--r-- | helix-term/src/application.rs | 144 |
1 files changed, 141 insertions, 3 deletions
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 1fcca681..9aa98271 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -1,11 +1,18 @@ -use helix_core::{merge_toml_values, syntax}; +use helix_core::{merge_toml_values, syntax, Range, Selection}; +use helix_dap::Payload; use helix_lsp::{lsp, util::lsp_pos_to_pos, LspProgressMap}; use helix_view::{theme, Editor}; -use crate::{args::Args, compositor::Compositor, config::Config, job::Jobs, ui}; +use crate::{ + args::Args, + commands::{align_view, Align}, + compositor::Compositor, + config::Config, + job::Jobs, + ui, +}; use log::error; - use std::{ io::{stdout, Write}, sync::Arc, @@ -191,6 +198,9 @@ impl Application { last_render = Instant::now(); } } + Some(payload) = self.editor.debugger_events.next() => { + self.handle_debugger_message(payload).await; + } Some(callback) = self.jobs.futures.next() => { self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback); self.render(); @@ -252,6 +262,134 @@ impl Application { } } + pub async fn handle_debugger_message(&mut self, payload: helix_dap::Payload) { + use helix_dap::{events, Event}; + let mut debugger = match self.editor.debugger.as_mut() { + Some(debugger) => debugger, + None => return, + }; + + match payload { + Payload::Event(ev) => match ev { + Event::Stopped(events::Stopped { + thread_id, + description, + text, + reason, + all_threads_stopped, + .. + }) => { + debugger.is_running = false; + let main = debugger.threads().await.ok().and_then(|threads| { + // Workaround for debugging Go tests. Main thread has * in beginning of its name + let mut main = threads.iter().find(|t| t.name.starts_with('*')).cloned(); + if main.is_none() { + main = threads.get(0).cloned(); + } + main + }); + + if let Some(main) = main { + let (bt, _) = debugger.stack_trace(main.id).await.unwrap(); + debugger.stack_pointer = bt.get(0).cloned(); + debugger.stopped_thread = Some(main.id); + } + + let scope = match thread_id { + Some(id) => format!("Thread {}", id), + None => "Target".to_owned(), + }; + + let mut status = format!("{} stopped because of {}", scope, reason); + if let Some(desc) = description { + status.push_str(&format!(" {}", desc)); + } + if let Some(text) = text { + status.push_str(&format!(" {}", text)); + } + if all_threads_stopped.unwrap_or_default() { + status.push_str(" (all threads stopped)"); + } + + if let Some(helix_dap::StackFrame { + source: + Some(helix_dap::Source { + path: Some(ref src), + .. + }), + line, + column, + end_line, + end_column, + .. + }) = debugger.stack_pointer + { + let path = src.clone(); + self.editor + .open(path, helix_view::editor::Action::Replace) + .unwrap(); + + let (view, doc) = current!(self.editor); + + let text_end = doc.text().len_chars().saturating_sub(1); + let start = doc.text().try_line_to_char(line - 1).unwrap_or(0) + column; + if let Some(end_line) = end_line { + let end = doc.text().try_line_to_char(end_line - 1).unwrap_or(0) + + end_column.unwrap_or(0); + doc.set_selection( + view.id, + Selection::new( + helix_core::SmallVec::from_vec(vec![Range::new( + start.min(text_end), + end.min(text_end), + )]), + 0, + ), + ); + } else { + doc.set_selection(view.id, Selection::point(start.min(text_end))); + } + align_view(doc, view, Align::Center); + } + self.editor.set_status(status); + } + Event::Output(events::Output { + category, output, .. + }) => { + let prefix = match category { + Some(category) => { + if &category == "telemetry" { + return; + } + format!("Debug ({}):", category) + } + None => "Debug:".to_owned(), + }; + + self.editor.set_status(format!("{} {}", prefix, output)); + } + Event::Initialized => { + self.editor + .set_status("Debugged application started".to_owned()); + } + Event::Continued(_) => { + if let Some(debugger) = self.editor.debugger.as_mut() { + debugger.stopped_thread = None; + debugger.stack_pointer = None; + debugger.is_running = true; + } + } + ev => { + log::warn!("Unhandled event {:?}", ev); + return; // return early to skip render + } + }, + Payload::Response(_) => unreachable!(), + Payload::Request(_) => todo!(), + } + self.render(); + } + pub async fn handle_language_server_message( &mut self, call: helix_lsp::Call, |