aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src/application.rs
diff options
context:
space:
mode:
Diffstat (limited to 'helix-term/src/application.rs')
-rw-r--r--helix-term/src/application.rs144
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,