Parse env vars and args from debug launch editor (#30538)
Release Notes: - debugger: allow setting env vars and arguments on the launch command. --------- Co-authored-by: Cole Miller <m@cole-miller.net> Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
parent
0ad582eec4
commit
907b2f0521
11 changed files with 53 additions and 13 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -4183,6 +4183,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"settings",
|
"settings",
|
||||||
|
"shlex",
|
||||||
"sysinfo",
|
"sysinfo",
|
||||||
"task",
|
"task",
|
||||||
"tasks_ui",
|
"tasks_ui",
|
||||||
|
|
|
@ -42,7 +42,9 @@ impl CodeLldbDebugAdapter {
|
||||||
if !launch.args.is_empty() {
|
if !launch.args.is_empty() {
|
||||||
map.insert("args".into(), launch.args.clone().into());
|
map.insert("args".into(), launch.args.clone().into());
|
||||||
}
|
}
|
||||||
|
if !launch.env.is_empty() {
|
||||||
|
map.insert("env".into(), launch.env_json());
|
||||||
|
}
|
||||||
if let Some(stop_on_entry) = config.stop_on_entry {
|
if let Some(stop_on_entry) = config.stop_on_entry {
|
||||||
map.insert("stopOnEntry".into(), stop_on_entry.into());
|
map.insert("stopOnEntry".into(), stop_on_entry.into());
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,10 @@ impl GdbDebugAdapter {
|
||||||
map.insert("args".into(), launch.args.clone().into());
|
map.insert("args".into(), launch.args.clone().into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !launch.env.is_empty() {
|
||||||
|
map.insert("env".into(), launch.env_json());
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(stop_on_entry) = config.stop_on_entry {
|
if let Some(stop_on_entry) = config.stop_on_entry {
|
||||||
map.insert(
|
map.insert(
|
||||||
"stopAtBeginningOfMainSubprogram".into(),
|
"stopAtBeginningOfMainSubprogram".into(),
|
||||||
|
|
|
@ -19,7 +19,8 @@ impl GoDebugAdapter {
|
||||||
dap::DebugRequest::Launch(launch_config) => json!({
|
dap::DebugRequest::Launch(launch_config) => json!({
|
||||||
"program": launch_config.program,
|
"program": launch_config.program,
|
||||||
"cwd": launch_config.cwd,
|
"cwd": launch_config.cwd,
|
||||||
"args": launch_config.args
|
"args": launch_config.args,
|
||||||
|
"env": launch_config.env_json()
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,9 @@ impl JsDebugAdapter {
|
||||||
if !launch.args.is_empty() {
|
if !launch.args.is_empty() {
|
||||||
map.insert("args".into(), launch.args.clone().into());
|
map.insert("args".into(), launch.args.clone().into());
|
||||||
}
|
}
|
||||||
|
if !launch.env.is_empty() {
|
||||||
|
map.insert("env".into(), launch.env_json());
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(stop_on_entry) = config.stop_on_entry {
|
if let Some(stop_on_entry) = config.stop_on_entry {
|
||||||
map.insert("stopOnEntry".into(), stop_on_entry.into());
|
map.insert("stopOnEntry".into(), stop_on_entry.into());
|
||||||
|
|
|
@ -29,6 +29,7 @@ impl PhpDebugAdapter {
|
||||||
"program": launch_config.program,
|
"program": launch_config.program,
|
||||||
"cwd": launch_config.cwd,
|
"cwd": launch_config.cwd,
|
||||||
"args": launch_config.args,
|
"args": launch_config.args,
|
||||||
|
"env": launch_config.env_json(),
|
||||||
"stopOnEntry": config.stop_on_entry.unwrap_or_default(),
|
"stopOnEntry": config.stop_on_entry.unwrap_or_default(),
|
||||||
}),
|
}),
|
||||||
request: config.request.to_dap(),
|
request: config.request.to_dap(),
|
||||||
|
|
|
@ -32,6 +32,9 @@ impl PythonDebugAdapter {
|
||||||
DebugRequest::Launch(launch) => {
|
DebugRequest::Launch(launch) => {
|
||||||
map.insert("program".into(), launch.program.clone().into());
|
map.insert("program".into(), launch.program.clone().into());
|
||||||
map.insert("args".into(), launch.args.clone().into());
|
map.insert("args".into(), launch.args.clone().into());
|
||||||
|
if !launch.env.is_empty() {
|
||||||
|
map.insert("env".into(), launch.env_json());
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(stop_on_entry) = config.stop_on_entry {
|
if let Some(stop_on_entry) = config.stop_on_entry {
|
||||||
map.insert("stopOnEntry".into(), stop_on_entry.into());
|
map.insert("stopOnEntry".into(), stop_on_entry.into());
|
||||||
|
|
|
@ -62,7 +62,7 @@ impl DebugAdapter for RubyDebugAdapter {
|
||||||
let tcp_connection = definition.tcp_connection.clone().unwrap_or_default();
|
let tcp_connection = definition.tcp_connection.clone().unwrap_or_default();
|
||||||
let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?;
|
let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?;
|
||||||
|
|
||||||
let DebugRequest::Launch(mut launch) = definition.request.clone() else {
|
let DebugRequest::Launch(launch) = definition.request.clone() else {
|
||||||
anyhow::bail!("rdbg does not yet support attaching");
|
anyhow::bail!("rdbg does not yet support attaching");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -71,12 +71,6 @@ impl DebugAdapter for RubyDebugAdapter {
|
||||||
format!("--port={}", port),
|
format!("--port={}", port),
|
||||||
format!("--host={}", host),
|
format!("--host={}", host),
|
||||||
];
|
];
|
||||||
if launch.args.is_empty() {
|
|
||||||
let program = launch.program.clone();
|
|
||||||
let mut split = program.split(" ");
|
|
||||||
launch.program = split.next().unwrap().to_string();
|
|
||||||
launch.args = split.map(|s| s.to_string()).collect();
|
|
||||||
}
|
|
||||||
if delegate.which(launch.program.as_ref()).is_some() {
|
if delegate.which(launch.program.as_ref()).is_some() {
|
||||||
arguments.push("--command".to_string())
|
arguments.push("--command".to_string())
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ rpc.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
settings.workspace = true
|
settings.workspace = true
|
||||||
|
shlex.workspace = true
|
||||||
sysinfo.workspace = true
|
sysinfo.workspace = true
|
||||||
task.workspace = true
|
task.workspace = true
|
||||||
tasks_ui.workspace = true
|
tasks_ui.workspace = true
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use collections::FxHashMap;
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
ops::Not,
|
ops::Not,
|
||||||
|
@ -595,7 +596,7 @@ impl CustomMode {
|
||||||
|
|
||||||
let program = cx.new(|cx| Editor::single_line(window, cx));
|
let program = cx.new(|cx| Editor::single_line(window, cx));
|
||||||
program.update(cx, |this, cx| {
|
program.update(cx, |this, cx| {
|
||||||
this.set_placeholder_text("Program path", cx);
|
this.set_placeholder_text("Run", cx);
|
||||||
|
|
||||||
if let Some(past_program) = past_program {
|
if let Some(past_program) = past_program {
|
||||||
this.set_text(past_program, window, cx);
|
this.set_text(past_program, window, cx);
|
||||||
|
@ -617,11 +618,29 @@ impl CustomMode {
|
||||||
|
|
||||||
pub(super) fn debug_request(&self, cx: &App) -> task::LaunchRequest {
|
pub(super) fn debug_request(&self, cx: &App) -> task::LaunchRequest {
|
||||||
let path = self.cwd.read(cx).text(cx);
|
let path = self.cwd.read(cx).text(cx);
|
||||||
|
let command = self.program.read(cx).text(cx);
|
||||||
|
let mut args = shlex::split(&command).into_iter().flatten().peekable();
|
||||||
|
let mut env = FxHashMap::default();
|
||||||
|
while args.peek().is_some_and(|arg| arg.contains('=')) {
|
||||||
|
let arg = args.next().unwrap();
|
||||||
|
let (lhs, rhs) = arg.split_once('=').unwrap();
|
||||||
|
env.insert(lhs.to_string(), rhs.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let program = if let Some(program) = args.next() {
|
||||||
|
program
|
||||||
|
} else {
|
||||||
|
env = FxHashMap::default();
|
||||||
|
command
|
||||||
|
};
|
||||||
|
|
||||||
|
let args = args.collect::<Vec<_>>();
|
||||||
|
|
||||||
task::LaunchRequest {
|
task::LaunchRequest {
|
||||||
program: self.program.read(cx).text(cx),
|
program,
|
||||||
cwd: path.is_empty().not().then(|| PathBuf::from(path)),
|
cwd: path.is_empty().not().then(|| PathBuf::from(path)),
|
||||||
args: Default::default(),
|
args,
|
||||||
env: Default::default(),
|
env,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,17 @@ pub struct LaunchRequest {
|
||||||
pub env: FxHashMap<String, String>,
|
pub env: FxHashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl LaunchRequest {
|
||||||
|
pub fn env_json(&self) -> serde_json::Value {
|
||||||
|
serde_json::Value::Object(
|
||||||
|
self.env
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| (k.clone(), v.to_owned().into()))
|
||||||
|
.collect::<serde_json::Map<String, serde_json::Value>>(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents the type that will determine which request to call on the debug adapter
|
/// Represents the type that will determine which request to call on the debug adapter
|
||||||
#[derive(Deserialize, Serialize, PartialEq, Eq, JsonSchema, Clone, Debug)]
|
#[derive(Deserialize, Serialize, PartialEq, Eq, JsonSchema, Clone, Debug)]
|
||||||
#[serde(rename_all = "lowercase", untagged)]
|
#[serde(rename_all = "lowercase", untagged)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue