editor: add Node.js debugger
This commit is contained in:
parent
0e51e5fbaf
commit
d943a51e3e
5 changed files with 44 additions and 3 deletions
|
@ -5,6 +5,7 @@ use crate::{
|
||||||
Rope, RopeSlice, Tendril,
|
Rope, RopeSlice, Tendril,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use helix_dap::DebuggerQuirks;
|
||||||
pub use helix_syntax::get_language;
|
pub use helix_syntax::get_language;
|
||||||
|
|
||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
|
@ -107,11 +108,14 @@ pub struct DebugTemplate {
|
||||||
pub struct DebugAdapterConfig {
|
pub struct DebugAdapterConfig {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub transport: String,
|
pub transport: String,
|
||||||
|
#[serde(default)]
|
||||||
pub command: String,
|
pub command: String,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub args: Vec<String>,
|
pub args: Vec<String>,
|
||||||
pub port_arg: Option<String>,
|
pub port_arg: Option<String>,
|
||||||
pub templates: Vec<DebugTemplate>,
|
pub templates: Vec<DebugTemplate>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub quirks: DebuggerQuirks,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
|
|
@ -5,6 +5,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
pub use log::{error, info};
|
pub use log::{error, info};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
net::{IpAddr, Ipv4Addr, SocketAddr},
|
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||||
|
@ -20,6 +21,13 @@ use tokio::{
|
||||||
time,
|
time,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Different workarounds for adapters' differences
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct DebuggerQuirks {
|
||||||
|
#[serde(default)]
|
||||||
|
pub absolute_paths: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
id: usize,
|
id: usize,
|
||||||
|
@ -34,6 +42,7 @@ pub struct Client {
|
||||||
/// Currently active frame for the current thread.
|
/// Currently active frame for the current thread.
|
||||||
pub active_frame: Option<usize>,
|
pub active_frame: Option<usize>,
|
||||||
pub breakpoints: Vec<Breakpoint>,
|
pub breakpoints: Vec<Breakpoint>,
|
||||||
|
pub quirks: DebuggerQuirks,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
|
@ -45,6 +54,9 @@ impl Client {
|
||||||
port_arg: Option<String>,
|
port_arg: Option<String>,
|
||||||
id: usize,
|
id: usize,
|
||||||
) -> Result<(Self, UnboundedReceiver<Payload>)> {
|
) -> Result<(Self, UnboundedReceiver<Payload>)> {
|
||||||
|
if command == "" {
|
||||||
|
return Result::Err(Error::Other(anyhow!("Command not provided")));
|
||||||
|
}
|
||||||
if transport == "tcp" && port_arg.is_some() {
|
if transport == "tcp" && port_arg.is_some() {
|
||||||
Self::tcp_process(
|
Self::tcp_process(
|
||||||
&command,
|
&command,
|
||||||
|
@ -82,6 +94,7 @@ impl Client {
|
||||||
thread_id: None,
|
thread_id: None,
|
||||||
active_frame: None,
|
active_frame: None,
|
||||||
breakpoints: vec![],
|
breakpoints: vec![],
|
||||||
|
quirks: DebuggerQuirks::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
tokio::spawn(Self::recv(server_rx, client_rx));
|
tokio::spawn(Self::recv(server_rx, client_rx));
|
||||||
|
|
|
@ -2,7 +2,7 @@ mod client;
|
||||||
mod transport;
|
mod transport;
|
||||||
mod types;
|
mod types;
|
||||||
|
|
||||||
pub use client::Client;
|
pub use client::{Client, DebuggerQuirks};
|
||||||
pub use events::Event;
|
pub use events::Event;
|
||||||
pub use transport::{Payload, Response, Transport};
|
pub use transport::{Payload, Response, Transport};
|
||||||
pub use types::*;
|
pub use types::*;
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
job::Callback,
|
job::Callback,
|
||||||
ui::{FilePicker, Prompt, PromptEvent},
|
ui::{FilePicker, Prompt, PromptEvent},
|
||||||
};
|
};
|
||||||
use helix_core::Selection;
|
use helix_core::{syntax::DebugConfigCompletion, Selection};
|
||||||
use helix_dap::{self as dap, Client};
|
use helix_dap::{self as dap, Client};
|
||||||
use helix_lsp::block_on;
|
use helix_lsp::block_on;
|
||||||
|
|
||||||
|
@ -206,6 +206,8 @@ pub fn dap_start_impl(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debugger.quirks = config.quirks;
|
||||||
|
|
||||||
let start_config = match name {
|
let start_config = match name {
|
||||||
Some(name) => config.templates.iter().find(|t| t.name == name),
|
Some(name) => config.templates.iter().find(|t| t.name == name),
|
||||||
None => config.templates.get(0),
|
None => config.templates.get(0),
|
||||||
|
@ -225,8 +227,18 @@ pub fn dap_start_impl(
|
||||||
for (k, t) in template {
|
for (k, t) in template {
|
||||||
let mut value = t;
|
let mut value = t;
|
||||||
for (i, x) in params.iter().enumerate() {
|
for (i, x) in params.iter().enumerate() {
|
||||||
|
let mut param = x.to_string();
|
||||||
|
if let Some(DebugConfigCompletion::Advanced(cfg)) = start_config.completion.get(i) {
|
||||||
|
if cfg.completion == Some("filename".to_owned())
|
||||||
|
|| cfg.completion == Some("directory".to_owned())
|
||||||
|
{
|
||||||
|
param = std::fs::canonicalize(x).ok()
|
||||||
|
.and_then(|pb| pb.into_os_string().into_string().ok())
|
||||||
|
.unwrap_or(x.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
// For param #0 replace {0} in args
|
// For param #0 replace {0} in args
|
||||||
value = value.replace(format!("{{{}}}", i).as_str(), x);
|
value = value.replace(format!("{{{}}}", i).as_str(), ¶m);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(integer) = value.parse::<usize>() {
|
if let Ok(integer) = value.parse::<usize>() {
|
||||||
|
|
|
@ -188,6 +188,18 @@ comment-token = "//"
|
||||||
|
|
||||||
indent = { tab-width = 2, unit = " " }
|
indent = { tab-width = 2, unit = " " }
|
||||||
|
|
||||||
|
[language.debugger]
|
||||||
|
name = "node-debug2"
|
||||||
|
transport = "stdio"
|
||||||
|
# args consisting of cmd (node) and path to adapter should be added to user's configuration
|
||||||
|
quirks = { absolute-paths = true }
|
||||||
|
|
||||||
|
[[language.debugger.templates]]
|
||||||
|
name = "source"
|
||||||
|
request = "launch"
|
||||||
|
completion = [ { name = "main", completion = "filename", default = "index.js" } ]
|
||||||
|
args = { program = "{0}" }
|
||||||
|
|
||||||
[[language]]
|
[[language]]
|
||||||
name = "typescript"
|
name = "typescript"
|
||||||
scope = "source.ts"
|
scope = "source.ts"
|
||||||
|
|
Loading…
Reference in a new issue