Cargo.lock 🔗
@@ -4183,6 +4183,7 @@ dependencies = [
"serde",
"serde_json",
"settings",
+ "shlex",
"sysinfo",
"task",
"tasks_ui",
Julia Ryan , Cole Miller , and Conrad Irwin created
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>
Cargo.lock | 1
crates/dap_adapters/src/codelldb.rs | 4 ++
crates/dap_adapters/src/gdb.rs | 4 +++
crates/dap_adapters/src/go.rs | 3 +
crates/dap_adapters/src/javascript.rs | 3 ++
crates/dap_adapters/src/php.rs | 1
crates/dap_adapters/src/python.rs | 3 ++
crates/dap_adapters/src/ruby.rs | 8 -----
crates/debugger_ui/Cargo.toml | 1
crates/debugger_ui/src/new_session_modal.rs | 27 +++++++++++++++++++---
crates/task/src/debug_format.rs | 11 +++++++++
11 files changed, 53 insertions(+), 13 deletions(-)
@@ -4183,6 +4183,7 @@ dependencies = [
"serde",
"serde_json",
"settings",
+ "shlex",
"sysinfo",
"task",
"tasks_ui",
@@ -42,7 +42,9 @@ impl CodeLldbDebugAdapter {
if !launch.args.is_empty() {
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 {
map.insert("stopOnEntry".into(), stop_on_entry.into());
}
@@ -35,6 +35,10 @@ impl GdbDebugAdapter {
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 {
map.insert(
"stopAtBeginningOfMainSubprogram".into(),
@@ -19,7 +19,8 @@ impl GoDebugAdapter {
dap::DebugRequest::Launch(launch_config) => json!({
"program": launch_config.program,
"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() {
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 {
map.insert("stopOnEntry".into(), stop_on_entry.into());
@@ -29,6 +29,7 @@ impl PhpDebugAdapter {
"program": launch_config.program,
"cwd": launch_config.cwd,
"args": launch_config.args,
+ "env": launch_config.env_json(),
"stopOnEntry": config.stop_on_entry.unwrap_or_default(),
}),
request: config.request.to_dap(),
@@ -32,6 +32,9 @@ impl PythonDebugAdapter {
DebugRequest::Launch(launch) => {
map.insert("program".into(), launch.program.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 {
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 (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");
};
@@ -71,12 +71,6 @@ impl DebugAdapter for RubyDebugAdapter {
format!("--port={}", port),
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() {
arguments.push("--command".to_string())
}
@@ -51,6 +51,7 @@ rpc.workspace = true
serde.workspace = true
serde_json.workspace = true
settings.workspace = true
+shlex.workspace = true
sysinfo.workspace = true
task.workspace = true
tasks_ui.workspace = true
@@ -1,3 +1,4 @@
+use collections::FxHashMap;
use std::{
borrow::Cow,
ops::Not,
@@ -595,7 +596,7 @@ impl CustomMode {
let program = cx.new(|cx| Editor::single_line(window, 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 {
this.set_text(past_program, window, cx);
@@ -617,11 +618,29 @@ impl CustomMode {
pub(super) fn debug_request(&self, cx: &App) -> task::LaunchRequest {
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 {
- program: self.program.read(cx).text(cx),
+ program,
cwd: path.is_empty().not().then(|| PathBuf::from(path)),
- args: Default::default(),
- env: Default::default(),
+ args,
+ env,
}
}
@@ -93,6 +93,17 @@ pub struct LaunchRequest {
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
#[derive(Deserialize, Serialize, PartialEq, Eq, JsonSchema, Clone, Debug)]
#[serde(rename_all = "lowercase", untagged)]