Defaults in completions, better schema

This commit is contained in:
Dmitry Sharshakov 2021-08-29 14:51:47 +03:00
parent f53d8411cb
commit b42631942b
No known key found for this signature in database
GPG key ID: 471FD32E15FD8473
7 changed files with 88 additions and 58 deletions

View file

@ -5,7 +5,6 @@ use crate::{
Rope, RopeSlice, Tendril, Rope, RopeSlice, Tendril,
}; };
use helix_dap::DebugAdapterConfig;
pub use helix_syntax::get_language; pub use helix_syntax::get_language;
use arc_swap::ArcSwap; use arc_swap::ArcSwap;
@ -69,6 +68,41 @@ pub struct LanguageServerConfiguration {
pub args: Vec<String>, pub args: Vec<String>,
} }
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")]
pub struct AdvancedCompletion {
pub name: Option<String>,
pub completion: Option<String>,
pub default: Option<String>,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case", untagged)]
pub enum DebugConfigCompletion {
Named(String),
Advanced(AdvancedCompletion),
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")]
pub struct DebugTemplate {
pub name: String,
pub request: String,
pub completion: Vec<DebugConfigCompletion>,
pub args: HashMap<String, String>,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")]
pub struct DebugAdapterConfig {
pub name: String,
pub transport: String,
pub command: String,
pub args: Vec<String>,
pub port_arg: Option<String>,
pub templates: Vec<DebugTemplate>,
}
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub struct IndentationConfiguration { pub struct IndentationConfiguration {

View file

@ -38,28 +38,24 @@ pub struct Client {
impl Client { impl Client {
// Spawn a process and communicate with it by either TCP or stdio // Spawn a process and communicate with it by either TCP or stdio
pub async fn process( pub async fn process(
cfg: DebugAdapterConfig, transport: String,
command: String,
args: Vec<String>,
port_arg: Option<String>,
id: usize, id: usize,
) -> Result<(Self, UnboundedReceiver<Payload>)> { ) -> Result<(Self, UnboundedReceiver<Payload>)> {
if cfg.transport == "tcp" && cfg.port_arg.is_some() { if transport == "tcp" && port_arg.is_some() {
Self::tcp_process( Self::tcp_process(
&cfg.command, &command,
cfg.args.iter().map(|s| s.as_str()).collect(), args.iter().map(|s| s.as_str()).collect(),
&cfg.port_arg.unwrap(), &port_arg.unwrap(),
id, id,
) )
.await .await
} else if cfg.transport == "stdio" { } else if transport == "stdio" {
Self::stdio( Self::stdio(&command, args.iter().map(|s| s.as_str()).collect(), id)
&cfg.command,
cfg.args.iter().map(|s| s.as_str()).collect(),
id,
)
} else { } else {
Result::Err(Error::Other(anyhow!( Result::Err(Error::Other(anyhow!("Incorrect transport {}", transport)))
"Incorrect transport {}",
cfg.transport
)))
} }
} }

View file

@ -1,26 +1,6 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value; use serde_json::Value;
use std::{collections::HashMap, path::PathBuf}; use std::path::PathBuf;
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")]
pub struct DebugTemplate {
pub name: String,
pub request: String,
pub completion: Vec<String>,
pub args: HashMap<String, String>,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")]
pub struct DebugAdapterConfig {
pub name: String,
pub transport: String,
pub command: String,
pub args: Vec<String>,
pub port_arg: Option<String>,
pub templates: Vec<DebugTemplate>,
}
pub trait Request { pub trait Request {
type Arguments: serde::de::DeserializeOwned + serde::Serialize; type Arguments: serde::de::DeserializeOwned + serde::Serialize;

View file

@ -4528,7 +4528,13 @@ pub fn dap_start_impl(
let result = match socket { let result = match socket {
Some(socket) => block_on(Client::tcp(socket, 0)), Some(socket) => block_on(Client::tcp(socket, 0)),
None => block_on(Client::process(config.clone(), 0)), None => block_on(Client::process(
config.transport.clone(),
config.command.clone(),
config.args.clone(),
config.port_arg.clone(),
0,
)),
}; };
let (mut debugger, events) = match result { let (mut debugger, events) = match result {

View file

@ -11,7 +11,7 @@ use helix_core::{
coords_at_pos, coords_at_pos,
graphemes::{ensure_grapheme_boundary_next, next_grapheme_boundary, prev_grapheme_boundary}, graphemes::{ensure_grapheme_boundary_next, next_grapheme_boundary, prev_grapheme_boundary},
movement::Direction, movement::Direction,
syntax::{self, HighlightEvent}, syntax::{self, DebugConfigCompletion, HighlightEvent},
unicode::segmentation::UnicodeSegmentation, unicode::segmentation::UnicodeSegmentation,
unicode::width::UnicodeWidthStr, unicode::width::UnicodeWidthStr,
LineEnding, Position, Range, Selection, LineEnding, Position, Range, Selection,
@ -710,28 +710,38 @@ impl EditorView {
} }
fn debug_parameter_prompt( fn debug_parameter_prompt(
completions: Vec<String>, completions: Vec<DebugConfigCompletion>,
config_name: String, config_name: String,
mut params: Vec<String>, mut params: Vec<String>,
) -> Prompt { ) -> Prompt {
let i = params.len(); let i = params.len();
let field_type = completions.get(i).map(|x| x.as_str()); let completion = completions.get(i).unwrap();
let field_type = if let DebugConfigCompletion::Advanced(cfg) = completion {
cfg.completion.clone().unwrap_or_else(|| "".to_owned())
} else {
"".to_owned()
};
let name = match completion {
DebugConfigCompletion::Advanced(cfg) => {
cfg.name.clone().unwrap_or_else(|| field_type.to_owned())
}
DebugConfigCompletion::Named(name) => name.clone(),
};
let default_val = match completion {
DebugConfigCompletion::Advanced(cfg) => {
cfg.default.clone().unwrap_or_else(|| "".to_owned())
}
_ => "".to_owned(),
};
let noop = |_input: &str| Vec::new(); let noop = |_input: &str| Vec::new();
let completer = match field_type { let completer = match &field_type[..] {
Some(field_type) => { "filename" => super::completers::filename,
if field_type.starts_with("filename") { "directory" => super::completers::directory,
super::completers::filename _ => noop,
} else if field_type.starts_with("directory") {
super::completers::directory
} else {
noop
}
}
None => noop,
}; };
Prompt::new( Prompt::new(
format!("{}: ", field_type.unwrap_or("arg")), format!("{}: ", name),
None, None,
completer, completer,
move |cx: &mut crate::compositor::Context, input: &str, event: PromptEvent| { move |cx: &mut crate::compositor::Context, input: &str, event: PromptEvent| {
@ -739,7 +749,11 @@ impl EditorView {
return; return;
} }
params.push(input.to_owned()); let mut value = input.to_owned();
if value.is_empty() {
value = default_val.clone();
}
params.push(value);
if params.len() < completions.len() { if params.len() < completions.len() {
let completions = completions.clone(); let completions = completions.clone();

View file

@ -22,7 +22,7 @@ use anyhow::Error;
pub use helix_core::diagnostic::Severity; pub use helix_core::diagnostic::Severity;
pub use helix_core::register::Registers; pub use helix_core::register::Registers;
use helix_core::syntax; use helix_core::syntax::{self, DebugConfigCompletion};
use helix_core::Position; use helix_core::Position;
use serde::Deserialize; use serde::Deserialize;
@ -77,7 +77,7 @@ pub struct Editor {
pub debugger: Option<helix_dap::Client>, pub debugger: Option<helix_dap::Client>,
pub debugger_events: SelectAll<UnboundedReceiverStream<helix_dap::Payload>>, pub debugger_events: SelectAll<UnboundedReceiverStream<helix_dap::Payload>>,
pub debug_config_picker: Option<Vec<String>>, pub debug_config_picker: Option<Vec<String>>,
pub debug_config_completions: Option<Vec<Vec<String>>>, pub debug_config_completions: Option<Vec<Vec<DebugConfigCompletion>>>,
pub variables: Option<Vec<String>>, pub variables: Option<Vec<String>>,
pub variables_page: usize, pub variables_page: usize,

View file

@ -173,8 +173,8 @@ args = { mode = "exec", program = "{0}" }
[[language.debugger.templates]] [[language.debugger.templates]]
name = "test" name = "test"
request = "launch" request = "launch"
completion = [ "directory: tests", "directory: cache output" ] completion = [ { name = "tests", completion = "directory", default = "." } ]
args = { mode = "test", program = "{0}", output = "{1}" } args = { mode = "test", program = "{0}" }
[[language.debugger.templates]] [[language.debugger.templates]]
name = "attach" name = "attach"