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.rs130
1 files changed, 109 insertions, 21 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index ded5a0e4..677943e8 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,
history::UndoKind,
@@ -45,8 +49,8 @@ use crate::{
use crate::job::{self, Job, Jobs};
use futures_util::{FutureExt, StreamExt};
+use std::{collections::HashMap, fmt, future::Future};
use std::{collections::HashSet, num::NonZeroUsize};
-use std::{fmt, future::Future};
use std::{
borrow::Cow,
@@ -115,13 +119,13 @@ impl<'a> Context<'a> {
}
}
-pub(crate) enum Align {
+pub enum Align {
Top,
Center,
Bottom,
}
-pub(crate) 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()
@@ -394,6 +398,21 @@ impl MappableCommand {
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",
@@ -1550,7 +1569,6 @@ fn search_completions(cx: &mut Context, reg: Option<char>) -> Vec<String> {
items.into_iter().cloned().collect()
}
-// TODO: use one function for search vs extend
fn search(cx: &mut Context) {
searcher(cx, Direction::Forward)
}
@@ -1558,7 +1576,7 @@ fn search(cx: &mut Context) {
fn rsearch(cx: &mut Context) {
searcher(cx, Direction::Backward)
}
-// TODO: use one function for search vs extend
+
fn searcher(cx: &mut Context, direction: Direction) {
let reg = cx.register.unwrap_or('/');
let scrolloff = cx.editor.config.scrolloff;
@@ -1783,11 +1801,11 @@ fn global_search(cx: &mut Context) {
relative_path.into()
}
},
- move |editor: &mut Editor, (line_num, path), action| {
- match editor.open(path.into(), action) {
+ move |cx, (line_num, path), action| {
+ match cx.editor.open(path.into(), action) {
Ok(_) => {}
Err(e) => {
- editor.set_error(format!(
+ cx.editor.set_error(format!(
"Failed to open file '{}': {}",
path.display(),
e
@@ -1797,7 +1815,7 @@ fn global_search(cx: &mut Context) {
}
let line_num = *line_num;
- let (view, doc) = current!(editor);
+ let (view, doc) = current!(cx.editor);
let text = doc.text();
let start = text.line_to_char(line_num);
let end = text.line_to_char((line_num + 1).min(text.len_lines()));
@@ -2000,7 +2018,6 @@ fn append_mode(cx: &mut Context) {
pub mod cmd {
use super::*;
- use std::collections::HashMap;
use helix_view::editor::Action;
use ui::completers::{self, Completer};
@@ -2680,6 +2697,58 @@ pub mod cmd {
Ok(())
}
+ fn debug_eval(
+ cx: &mut compositor::Context,
+ args: &[Cow<str>],
+ _event: PromptEvent,
+ ) -> anyhow::Result<()> {
+ 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(())
+ }
+
+ fn debug_start(
+ cx: &mut compositor::Context,
+ args: &[Cow<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(cx, name.as_deref(), None, Some(args))
+ }
+
+ fn debug_remote(
+ cx: &mut compositor::Context,
+ args: &[Cow<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(cx, name.as_deref(), address, Some(args))
+ }
+
fn tutor(
cx: &mut compositor::Context,
_args: &[Cow<str>],
@@ -3095,6 +3164,27 @@ pub 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.",
@@ -3325,8 +3415,8 @@ fn buffer_picker(cx: &mut Context) {
.map(|(_, doc)| new_meta(doc))
.collect(),
BufferMeta::format,
- |editor: &mut Editor, meta, action| {
- editor.switch(meta.id, action);
+ |cx, meta, action| {
+ cx.editor.switch(meta.id, action);
},
|editor, meta| {
let doc = &editor.documents.get(&meta.id)?;
@@ -3393,9 +3483,9 @@ fn symbol_picker(cx: &mut Context) {
let mut picker = FilePicker::new(
symbols,
|symbol| (&symbol.name).into(),
- move |editor: &mut Editor, symbol, _action| {
- push_jump(editor);
- let (view, doc) = current!(editor);
+ move |cx, symbol, _action| {
+ push_jump(cx.editor);
+ let (view, doc) = current!(cx.editor);
if let Some(range) =
lsp_range_to_range(doc.text(), symbol.location.range, offset_encoding)
@@ -3452,10 +3542,10 @@ fn workspace_symbol_picker(cx: &mut Context) {
format!("{} ({})", &symbol.name, relative_path).into()
}
},
- move |editor: &mut Editor, symbol, action| {
+ move |cx, symbol, action| {
let path = symbol.location.uri.to_file_path().unwrap();
- editor.open(path, action).expect("editor.open failed");
- let (view, doc) = current!(editor);
+ cx.editor.open(path, action).expect("editor.open failed");
+ let (view, doc) = current!(cx.editor);
if let Some(range) =
lsp_range_to_range(doc.text(), symbol.location.range, offset_encoding)
@@ -4127,9 +4217,7 @@ fn goto_impl(
let line = location.range.start.line;
format!("{}:{}", file, line).into()
},
- move |editor: &mut Editor, location, action| {
- jump_to(editor, location, offset_encoding, action)
- },
+ move |cx, location, action| jump_to(cx.editor, location, offset_encoding, action),
|_editor, location| {
let path = location.uri.to_file_path().unwrap();
let line = Some((