mirror of
https://github.com/helix-editor/helix.git
synced 2025-01-19 21:47:07 +04:00
Add stack pointer display when stopped
This commit is contained in:
parent
738e8a4dd3
commit
6458edecfd
@ -36,6 +36,8 @@ pub struct Client {
|
|||||||
|
|
||||||
//
|
//
|
||||||
pub breakpoints: HashMap<PathBuf, Vec<SourceBreakpoint>>,
|
pub breakpoints: HashMap<PathBuf, Vec<SourceBreakpoint>>,
|
||||||
|
// TODO: multiple threads support
|
||||||
|
pub stack_pointer: Option<StackFrame>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
@ -56,6 +58,7 @@ pub fn streams(
|
|||||||
awaited_events: Arc::new(Mutex::new(HashMap::default())),
|
awaited_events: Arc::new(Mutex::new(HashMap::default())),
|
||||||
//
|
//
|
||||||
breakpoints: HashMap::new(),
|
breakpoints: HashMap::new(),
|
||||||
|
stack_pointer: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
tokio::spawn(Self::recv(Arc::clone(&client.awaited_events), server_rx));
|
tokio::spawn(Self::recv(Arc::clone(&client.awaited_events), server_rx));
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
};
|
};
|
||||||
use insert::*;
|
use insert::*;
|
||||||
use movement::Movement;
|
use movement::Movement;
|
||||||
|
use tokio::sync::{mpsc::Receiver, Mutex};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
compositor::{self, Component, Compositor},
|
compositor::{self, Component, Compositor},
|
||||||
@ -32,8 +33,8 @@
|
|||||||
|
|
||||||
use crate::job::{self, Job, Jobs};
|
use crate::job::{self, Job, Jobs};
|
||||||
use futures_util::FutureExt;
|
use futures_util::FutureExt;
|
||||||
use std::num::NonZeroUsize;
|
|
||||||
use std::{collections::HashMap, fmt, future::Future};
|
use std::{collections::HashMap, fmt, future::Future};
|
||||||
|
use std::{num::NonZeroUsize, sync::Arc};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
@ -4267,11 +4268,34 @@ fn dap_start(cx: &mut Context) {
|
|||||||
let request = debugger.launch(to_value(args).unwrap());
|
let request = debugger.launch(to_value(args).unwrap());
|
||||||
let _ = block_on(request).unwrap();
|
let _ = block_on(request).unwrap();
|
||||||
|
|
||||||
// TODO: either await "initialized" or buffer commands until event is received
|
let stopped = block_on(debugger.listen_for_event("stopped".to_owned()));
|
||||||
|
let debugger = Arc::new(Mutex::new(debugger));
|
||||||
|
tokio::spawn(dap_listen_stopped(stopped, Arc::clone(&debugger)));
|
||||||
|
|
||||||
|
// TODO: either await "initialized" or buffer commands until event is received
|
||||||
cx.editor.debugger = Some(debugger);
|
cx.editor.debugger = Some(debugger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn dap_listen_stopped(
|
||||||
|
mut stopped: Receiver<helix_dap::Event>,
|
||||||
|
debugger: Arc<Mutex<helix_dap::Client>>,
|
||||||
|
) {
|
||||||
|
loop {
|
||||||
|
stopped.recv().await;
|
||||||
|
|
||||||
|
let mut dbg = debugger.lock().await;
|
||||||
|
let main = dbg
|
||||||
|
.threads()
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
|
.and_then(|threads| threads.get(0).and_then(|x| Some(x.clone())));
|
||||||
|
if let Some(main) = main {
|
||||||
|
let (a, _) = dbg.stack_trace(main.id).await.unwrap();
|
||||||
|
dbg.stack_pointer = a.get(0).and_then(|x| Some(x.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn dap_toggle_breakpoint(cx: &mut Context) {
|
fn dap_toggle_breakpoint(cx: &mut Context) {
|
||||||
use helix_lsp::block_on;
|
use helix_lsp::block_on;
|
||||||
|
|
||||||
@ -4297,6 +4321,7 @@ fn dap_toggle_breakpoint(cx: &mut Context) {
|
|||||||
// we shouldn't really allow editing while debug is running though
|
// we shouldn't really allow editing while debug is running though
|
||||||
|
|
||||||
if let Some(debugger) = &mut cx.editor.debugger {
|
if let Some(debugger) = &mut cx.editor.debugger {
|
||||||
|
let mut debugger = block_on(debugger.lock());
|
||||||
let breakpoints = debugger.breakpoints.entry(path.clone()).or_default();
|
let breakpoints = debugger.breakpoints.entry(path.clone()).or_default();
|
||||||
if let Some(pos) = breakpoints.iter().position(|b| b.line == breakpoint.line) {
|
if let Some(pos) = breakpoints.iter().position(|b| b.line == breakpoint.line) {
|
||||||
breakpoints.remove(pos);
|
breakpoints.remove(pos);
|
||||||
@ -4315,6 +4340,7 @@ fn dap_run(cx: &mut Context) {
|
|||||||
use helix_lsp::block_on;
|
use helix_lsp::block_on;
|
||||||
|
|
||||||
if let Some(debugger) = &mut cx.editor.debugger {
|
if let Some(debugger) = &mut cx.editor.debugger {
|
||||||
|
let mut debugger = block_on(debugger.lock());
|
||||||
let request = debugger.configuration_done();
|
let request = debugger.configuration_done();
|
||||||
let _ = block_on(request).unwrap();
|
let _ = block_on(request).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
unicode::width::UnicodeWidthStr,
|
unicode::width::UnicodeWidthStr,
|
||||||
LineEnding, Position, Range, Selection,
|
LineEnding, Position, Range, Selection,
|
||||||
};
|
};
|
||||||
|
use helix_dap::{SourceBreakpoint, StackFrame};
|
||||||
use helix_view::{
|
use helix_view::{
|
||||||
document::Mode,
|
document::Mode,
|
||||||
editor::LineNumber,
|
editor::LineNumber,
|
||||||
@ -24,7 +25,8 @@
|
|||||||
keyboard::{KeyCode, KeyModifiers},
|
keyboard::{KeyCode, KeyModifiers},
|
||||||
Document, Editor, Theme, View,
|
Document, Editor, Theme, View,
|
||||||
};
|
};
|
||||||
use std::borrow::Cow;
|
use std::{borrow::Cow, sync::Arc};
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
use crossterm::event::{Event, MouseButton, MouseEvent, MouseEventKind};
|
use crossterm::event::{Event, MouseButton, MouseEvent, MouseEventKind};
|
||||||
use tui::buffer::Buffer as Surface;
|
use tui::buffer::Buffer as Surface;
|
||||||
@ -71,7 +73,7 @@ pub fn render_view(
|
|||||||
is_focused: bool,
|
is_focused: bool,
|
||||||
loader: &syntax::Loader,
|
loader: &syntax::Loader,
|
||||||
config: &helix_view::editor::Config,
|
config: &helix_view::editor::Config,
|
||||||
debugger: Option<&helix_dap::Client>,
|
debugger: Option<Arc<Mutex<helix_dap::Client>>>,
|
||||||
) {
|
) {
|
||||||
let inner = view.inner_area();
|
let inner = view.inner_area();
|
||||||
let area = view.area;
|
let area = view.area;
|
||||||
@ -412,8 +414,9 @@ pub fn render_gutter(
|
|||||||
theme: &Theme,
|
theme: &Theme,
|
||||||
is_focused: bool,
|
is_focused: bool,
|
||||||
config: &helix_view::editor::Config,
|
config: &helix_view::editor::Config,
|
||||||
debugger: Option<&helix_dap::Client>,
|
debugger: Option<Arc<Mutex<helix_dap::Client>>>,
|
||||||
) {
|
) {
|
||||||
|
use helix_lsp::block_on;
|
||||||
let text = doc.text().slice(..);
|
let text = doc.text().slice(..);
|
||||||
let last_line = view.last_line(doc);
|
let last_line = view.last_line(doc);
|
||||||
|
|
||||||
@ -442,9 +445,15 @@ pub fn render_gutter(
|
|||||||
.map(|range| range.cursor_line(text))
|
.map(|range| range.cursor_line(text))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let breakpoints = doc
|
let mut breakpoints: Option<Vec<SourceBreakpoint>> = None;
|
||||||
.path()
|
let mut stack_pointer: Option<StackFrame> = None;
|
||||||
.and_then(|path| debugger.and_then(|debugger| debugger.breakpoints.get(path)));
|
if let Some(debugger) = debugger {
|
||||||
|
if let Some(path) = doc.path() {
|
||||||
|
let dbg = block_on(debugger.lock());
|
||||||
|
breakpoints = dbg.breakpoints.get(path).and_then(|bps| Some(bps.clone()));
|
||||||
|
stack_pointer = dbg.stack_pointer.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i, line) in (view.offset.row..(last_line + 1)).enumerate() {
|
for (i, line) in (view.offset.row..(last_line + 1)).enumerate() {
|
||||||
use helix_core::diagnostic::Severity;
|
use helix_core::diagnostic::Severity;
|
||||||
@ -465,12 +474,23 @@ pub fn render_gutter(
|
|||||||
|
|
||||||
let selected = cursors.contains(&line);
|
let selected = cursors.contains(&line);
|
||||||
|
|
||||||
if let Some(_breakpoint) = breakpoints.and_then(|breakpoints| {
|
if let Some(bps) = breakpoints.as_ref() {
|
||||||
breakpoints
|
if let Some(_) = bps.iter().find(|breakpoint| breakpoint.line == line) {
|
||||||
.iter()
|
surface.set_stringn(viewport.x, viewport.y + i as u16, "▲", 1, warning);
|
||||||
.find(|breakpoint| breakpoint.line == line)
|
}
|
||||||
}) {
|
}
|
||||||
surface.set_stringn(viewport.x, viewport.y + i as u16, "▲", 1, warning);
|
|
||||||
|
if let Some(sp) = stack_pointer.as_ref() {
|
||||||
|
if let Some(src) = sp.source.as_ref() {
|
||||||
|
if doc
|
||||||
|
.path()
|
||||||
|
.and_then(|path| Some(src.path == Some(path.clone())))
|
||||||
|
.unwrap_or(false)
|
||||||
|
&& sp.line == line
|
||||||
|
{
|
||||||
|
surface.set_stringn(viewport.x, viewport.y + i as u16, "⇒", 1, warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let text = if line == last_line && !draw_last {
|
let text = if line == last_line && !draw_last {
|
||||||
@ -1023,7 +1043,10 @@ fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
|||||||
for (view, is_focused) in cx.editor.tree.views() {
|
for (view, is_focused) in cx.editor.tree.views() {
|
||||||
let doc = cx.editor.document(view.doc).unwrap();
|
let doc = cx.editor.document(view.doc).unwrap();
|
||||||
let loader = &cx.editor.syn_loader;
|
let loader = &cx.editor.syn_loader;
|
||||||
let debugger = cx.editor.debugger.as_ref();
|
let mut dbg: Option<Arc<Mutex<helix_dap::Client>>> = None;
|
||||||
|
if let Some(debugger) = &cx.editor.debugger {
|
||||||
|
dbg = Some(Arc::clone(&debugger));
|
||||||
|
}
|
||||||
self.render_view(
|
self.render_view(
|
||||||
doc,
|
doc,
|
||||||
view,
|
view,
|
||||||
@ -1033,7 +1056,7 @@ fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
|||||||
is_focused,
|
is_focused,
|
||||||
loader,
|
loader,
|
||||||
&cx.editor.config,
|
&cx.editor.config,
|
||||||
debugger,
|
dbg,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
use futures_util::future;
|
use futures_util::future;
|
||||||
use futures_util::stream::select_all::SelectAll;
|
use futures_util::stream::select_all::SelectAll;
|
||||||
|
use tokio::sync::Mutex;
|
||||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
@ -74,7 +75,7 @@ pub struct Editor {
|
|||||||
pub theme: Theme,
|
pub theme: Theme,
|
||||||
pub language_servers: helix_lsp::Registry,
|
pub language_servers: helix_lsp::Registry,
|
||||||
|
|
||||||
pub debugger: Option<helix_dap::Client>,
|
pub debugger: Option<Arc<Mutex<helix_dap::Client>>>,
|
||||||
pub debuggers: SelectAll<UnboundedReceiverStream<helix_dap::Payload>>,
|
pub debuggers: SelectAll<UnboundedReceiverStream<helix_dap::Payload>>,
|
||||||
|
|
||||||
pub clipboard_provider: Box<dyn ClipboardProvider>,
|
pub clipboard_provider: Box<dyn ClipboardProvider>,
|
||||||
|
Loading…
Reference in New Issue
Block a user