diff options
Diffstat (limited to 'helix-term/src/commands.rs')
-rw-r--r-- | helix-term/src/commands.rs | 123 |
1 files changed, 119 insertions, 4 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 26f599bd..acaba6d6 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1,3 +1,7 @@ +pub(crate) mod dap; + +pub use dap::*; + use helix_core::{ comment, coords_at_pos, find_first_non_whitespace_char, find_root, graphemes, indent, indent::IndentStyle, @@ -33,7 +37,7 @@ use crate::{ use crate::job::{self, Job, Jobs}; use futures_util::{FutureExt, StreamExt}; use std::num::NonZeroUsize; -use std::{fmt, future::Future}; +use std::{collections::HashMap, fmt, future::Future}; use std::{ borrow::Cow, @@ -102,13 +106,13 @@ impl<'a> Context<'a> { } } -enum Align { +pub enum Align { Top, Center, Bottom, } -fn align_view(doc: &Document, view: &mut View, align: Align) { +pub fn align_view(doc: &Document, view: &mut View, align: Align) { let pos = doc .selection(view.id) .primary() @@ -318,6 +322,19 @@ impl Command { surround_delete, "Surround delete", select_textobject_around, "Select around object", select_textobject_inner, "Select inside object", + dap_launch, "Launch debug target", + dap_toggle_breakpoint, "Toggle breakpoint", + dap_continue, "Continue program execution", + dap_pause, "Pause program execution", + dap_step_in, "Step in", + dap_step_out, "Step out", + dap_next, "Step to next", + dap_variables, "List variables", + dap_terminate, "End debug session", + dap_edit_condition, "Edit condition of the breakpoint on the current line", + dap_edit_log, "Edit log message of the breakpoint on the current line", + dap_switch_thread, "Switch current thread", + dap_switch_stack_frame, "Switch stack frame", shell_pipe, "Pipe selections through shell command", shell_pipe_to, "Pipe selections into shell command, ignoring command output", shell_insert_output, "Insert output of shell command before each selection", @@ -1477,8 +1494,8 @@ fn append_mode(cx: &mut Context) { mod cmd { use super::*; - use std::collections::HashMap; + use helix_dap::SourceBreakpoint; use helix_view::editor::Action; use ui::completers::{self, Completer}; @@ -2082,6 +2099,80 @@ mod cmd { Ok(()) } + fn debug_eval( + cx: &mut compositor::Context, + args: &[&str], + _event: PromptEvent, + ) -> anyhow::Result<()> { + use helix_lsp::block_on; + if let Some(debugger) = cx.editor.debugger.as_mut() { + let (frame, thread_id) = match (debugger.active_frame, debugger.thread_id) { + (Some(frame), Some(thread_id)) => (frame, thread_id), + _ => { + bail!("Cannot find current stack frame to access variables") + } + }; + + // TODO: support no frame_id + + let frame_id = debugger.stack_frames[&thread_id][frame].id; + let response = block_on(debugger.eval(args.join(" "), Some(frame_id)))?; + cx.editor.set_status(response.result); + } + Ok(()) + } + + pub fn get_breakpoint_at_current_line( + editor: &mut Editor, + ) -> Option<(usize, SourceBreakpoint)> { + let (view, doc) = current!(editor); + let text = doc.text().slice(..); + + let pos = doc.selection(view.id).primary().cursor(text); + let line = text.char_to_line(pos) + 1; // 1-indexing in DAP, 0-indexing in Helix + let path = match doc.path() { + Some(path) => path.to_path_buf(), + None => return None, + }; + let vec = vec![]; + let breakpoints = editor.breakpoints.get(&path).unwrap_or(&vec); + let i = breakpoints.iter().position(|b| b.line == line); + i.map(|i| (i, breakpoints.get(i).unwrap().clone())) + } + + fn debug_start( + cx: &mut compositor::Context, + args: &[&str], + _event: PromptEvent, + ) -> anyhow::Result<()> { + let mut args = args.to_owned(); + let name = match args.len() { + 0 => None, + _ => Some(args.remove(0)), + }; + dap_start_impl(&mut cx.editor, name, None, Some(args)); + Ok(()) + } + + fn debug_remote( + cx: &mut compositor::Context, + args: &[&str], + _event: PromptEvent, + ) -> anyhow::Result<()> { + let mut args = args.to_owned(); + let address = match args.len() { + 0 => None, + _ => Some(args.remove(0).parse()?), + }; + let name = match args.len() { + 0 => None, + _ => Some(args.remove(0)), + }; + dap_start_impl(&mut cx.editor, name, address, Some(args)); + + Ok(()) + } + pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[ TypableCommand { name: "quit", @@ -2322,6 +2413,27 @@ mod cmd { completer: None, }, TypableCommand { + name: "debug-start", + alias: Some("dbg"), + doc: "Start a debug session from a given template with given parameters.", + fun: debug_start, + completer: None, + }, + TypableCommand { + name: "debug-remote", + alias: Some("dbg-tcp"), + doc: "Connect to a debug adapter by TCP address and start a debugging session from a given template with given parameters.", + fun: debug_remote, + completer: None, + }, + TypableCommand { + name: "debug-eval", + alias: None, + doc: "Evaluate expression in current debug context.", + fun: debug_eval, + completer: None, + }, + TypableCommand { name: "vsplit", alias: Some("vs"), doc: "Open the file in a vertical split.", @@ -2409,6 +2521,7 @@ fn command_mode(cx: &mut Context) { .set_error(format!("no such command: '{}'", parts[0])); }; }, + None, ); prompt.doc_fn = Box::new(|input: &str| { let part = input.split(' ').next().unwrap_or_default(); @@ -4579,6 +4692,7 @@ fn shell_keep_pipe(cx: &mut Context) { let index = index.unwrap_or_else(|| ranges.len() - 1); doc.set_selection(view.id, Selection::new(ranges, index)); }, + None, ); cx.push_layer(Box::new(prompt)); @@ -4678,6 +4792,7 @@ fn shell(cx: &mut Context, prompt: Cow<'static, str>, behavior: ShellBehavior) { doc.append_changes_to_history(view.id); } }, + None, ); cx.push_layer(Box::new(prompt)); |