aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src/commands.rs
diff options
context:
space:
mode:
Diffstat (limited to 'helix-term/src/commands.rs')
-rw-r--r--helix-term/src/commands.rs125
1 files changed, 121 insertions, 4 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 95c46a4e..f3761d7d 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,21 @@ 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",
+ dap_enable_exceptions, "Enable exception breakpoints",
+ dap_disable_exceptions, "Disable exception breakpoints",
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",
@@ -1490,8 +1509,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};
@@ -2095,6 +2114,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",
@@ -2335,6 +2428,27 @@ mod cmd {
completer: None,
},
TypableCommand {
+ name: "debug-start",
+ aliases: &["dbg"],
+ doc: "Start a debug session from a given template with given parameters.",
+ fun: debug_start,
+ completer: None,
+ },
+ TypableCommand {
+ name: "debug-remote",
+ aliases: &["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",
+ aliases: &[],
+ doc: "Evaluate expression in current debug context.",
+ fun: debug_eval,
+ completer: None,
+ },
+ TypableCommand {
name: "vsplit",
aliases: &["vs"],
doc: "Open the file in a vertical split.",
@@ -2419,6 +2533,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();
@@ -4603,6 +4718,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));
@@ -4702,6 +4818,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));