Start integrating into the editor's event loop

This commit is contained in:
Blaž Hrastnik 2021-08-16 18:16:06 +09:00
parent 0300dbdeb3
commit d39baa3b4e
11 changed files with 86 additions and 27 deletions

5
Cargo.lock generated
View File

@ -324,7 +324,7 @@ dependencies = [
[[package]]
name = "helix-dap"
version = "0.3.0"
version = "0.4.0"
dependencies = [
"anyhow",
"fern",
@ -375,6 +375,7 @@ dependencies = [
"futures-util",
"fuzzy-matcher",
"helix-core",
"helix-dap",
"helix-lsp",
"helix-tui",
"helix-view",
@ -416,6 +417,7 @@ dependencies = [
"encoding_rs",
"futures-util",
"helix-core",
"helix-dap",
"helix-lsp",
"helix-tui",
"log",
@ -423,6 +425,7 @@ dependencies = [
"serde",
"slotmap",
"tokio",
"tokio-stream",
"toml",
"url",
"which",

View File

@ -1,6 +1,6 @@
[package]
name = "helix-dap"
version = "0.3.0"
version = "0.4.0"
authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
edition = "2018"
license = "MPL-2.0"

View File

@ -186,12 +186,12 @@ async fn request<R: crate::types::Request>(
&self,
arguments: R::Arguments,
) -> Result<R::Result> {
let (callback_rx, mut callback_tx) = channel(1);
let (callback_tx, mut callback_rx) = channel(1);
let arguments = Some(serde_json::to_value(arguments)?);
let req = Request {
back_ch: Some(callback_rx),
back_ch: Some(callback_tx),
seq: self.next_request_id(),
command: R::COMMAND.to_string(),
arguments,
@ -201,7 +201,7 @@ async fn request<R: crate::types::Request>(
.send(req)
.expect("Failed to send request to debugger");
let response = callback_tx.recv().await.unwrap()?;
let response = callback_rx.recv().await.unwrap()?;
let response = serde_json::from_value(response.body.unwrap_or_default())?;
Ok(response)
}
@ -209,7 +209,7 @@ async fn request<R: crate::types::Request>(
pub fn capabilities(&self) -> &DebuggerCapabilities {
self.capabilities
.as_ref()
.expect("language server not yet initialized!")
.expect("debugger not yet initialized!")
}
pub async fn initialize(&mut self, adapter_id: String) -> Result<()> {
@ -240,21 +240,19 @@ pub async fn disconnect(&mut self) -> Result<()> {
}
pub async fn launch(&mut self, args: serde_json::Value) -> Result<()> {
let mut initialized = self.listen_for_event("initialized".to_owned()).await;
// TODO: buffer these until initialized arrives
let res = self.request::<requests::Launch>(args);
let ev = initialized.recv();
join!(res, ev).0?;
let response = self.request::<requests::Launch>(args).await?;
log::error!("launch response {}", response);
Ok(())
}
pub async fn attach(&mut self, args: serde_json::Value) -> Result<()> {
let mut initialized = self.listen_for_event("initialized".to_owned()).await;
// TODO: buffer these until initialized arrives
let res = self.request::<requests::Attach>(args);
let ev = initialized.recv();
join!(res, ev).0?;
let response = self.request::<requests::Attach>(args).await?;
log::error!("attach response {}", response);
Ok(())
}

View File

@ -159,20 +159,17 @@ async fn send_string_to_server(
}
fn process_response(res: Response) -> Result<Response> {
match res.success {
true => {
info!("<- DAP success in response to {}", res.request_seq);
if res.success {
info!("<- DAP success in response to {}", res.request_seq);
Ok(res)
}
false => {
error!(
"<- DAP error {:?} ({:?}) for command #{} {}",
res.message, res.body, res.request_seq, res.command
);
Ok(res)
} else {
error!(
"<- DAP error {:?} ({:?}) for command #{} {}",
res.message, res.body, res.request_seq, res.command
);
Err(Error::Other(anyhow::format_err!("{:?}", res.body)))
}
Err(Error::Other(anyhow::format_err!("{:?}", res.body)))
}
}

View File

@ -24,4 +24,4 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0"
tokio = { version = "1.9", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot", "sync"] }
tokio-stream = "0.1.7"
tokio-stream = "0.1"

View File

@ -24,6 +24,7 @@ path = "src/main.rs"
helix-core = { version = "0.4", path = "../helix-core" }
helix-view = { version = "0.4", path = "../helix-view" }
helix-lsp = { version = "0.4", path = "../helix-lsp" }
helix-dap = { version = "0.4", path = "../helix-dap" }
anyhow = "1"
once_cell = "1.8"

View File

@ -245,6 +245,15 @@ pub fn handle_terminal_events(&mut self, event: Option<Result<Event, crossterm::
}
}
pub async fn handle_debugger_message(
&mut self,
call: (),
server_id: usize,
) {
//
}
pub async fn handle_language_server_message(
&mut self,
call: helix_lsp::Call,

View File

@ -1900,6 +1900,41 @@ fn tree_sitter_scopes(
Ok(())
}
fn debug(
cx: &mut compositor::Context,
_args: &[&str],
_event: PromptEvent,
) -> anyhow::Result<()> {
use helix_dap::Client;
use helix_lsp::block_on;
use serde_json::to_value;
let (_, doc) = current!(cx.editor);
// look up config for filetype
// if multiple available, open picker
log::error!("1");
let client = Client::tcp_process("dlv", vec!["dap"], "-l 127.0.0.1:{}", 0);
let mut client = block_on(client)?;
log::error!("2");
let request = client.initialize("go".to_owned());
let _ = block_on(request)?;
log::error!("3");
let mut args = HashMap::new();
args.insert("mode", "debug");
// args.insert("program", "path/to/program");
let request = client.launch(to_value(args)?);
let _ = block_on(request)?;
log::error!("4");
doc.debugger = Some(client);
Ok(())
}
pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
TypableCommand {
name: "quit",
@ -2138,6 +2173,13 @@ fn tree_sitter_scopes(
doc: "Display tree sitter scopes, primarily for theming and development.",
fun: tree_sitter_scopes,
completer: None,
},
TypableCommand {
name: "debug",
alias: None,
doc: "Start a debug session.",
fun: debug,
completer: None,
}
];

View File

@ -18,6 +18,7 @@ bitflags = "1.3"
anyhow = "1"
helix-core = { version = "0.4", path = "../helix-core" }
helix-lsp = { version = "0.4", path = "../helix-lsp"}
helix-dap = { version = "0.4", path = "../helix-dap"}
crossterm = { version = "0.20", optional = true }
# Conversion traits
@ -25,6 +26,7 @@ once_cell = "1.8"
url = "2"
tokio = { version = "1", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot"] }
tokio-stream = "0.1"
futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false }
slotmap = "1"

View File

@ -100,6 +100,7 @@ pub struct Document {
diagnostics: Vec<Diagnostic>,
language_server: Option<Arc<helix_lsp::Client>>,
pub debugger: Option<helix_dap::Client>,
}
use std::fmt;
@ -425,6 +426,7 @@ pub fn from(text: Rope, encoding: Option<&'static encoding_rs::Encoding>) -> Sel
history: Cell::new(History::default()),
last_saved_revision: 0,
language_server: None,
debugger: None,
line_ending: DEFAULT_LINE_ENDING,
}
}

View File

@ -7,6 +7,9 @@
};
use futures_util::future;
use futures_util::stream::select_all::SelectAll;
use tokio_stream::wrappers::UnboundedReceiverStream;
use std::{
path::{Path, PathBuf},
sync::Arc,
@ -70,6 +73,7 @@ pub struct Editor {
pub registers: Registers,
pub theme: Theme,
pub language_servers: helix_lsp::Registry,
pub debuggers: SelectAll<UnboundedReceiverStream<(usize, helix_dap::Payload)>>,
pub clipboard_provider: Box<dyn ClipboardProvider>,
pub syn_loader: Arc<syntax::Loader>,
@ -107,6 +111,7 @@ pub fn new(
selected_register: RegisterSelection::default(),
theme: themes.default(),
language_servers,
debuggers: SelectAll::new(),
syn_loader: config_loader,
theme_loader: themes,
registers: Registers::default(),