cli: Support --foreground for debugging (#11819)

Release Notes:

- Added `--foreground` to the cli to allow running zed on the current
PTY.
This commit is contained in:
Conrad Irwin 2024-05-14 16:05:40 -06:00 committed by GitHub
parent 18b6ded8f0
commit 5b2c019f83
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 70 additions and 28 deletions

View file

@ -4,8 +4,10 @@ use anyhow::{Context, Result};
use clap::Parser;
use cli::{ipc::IpcOneShotServer, CliRequest, CliResponse, IpcHandshake};
use std::{
env, fs,
env, fs, io,
path::{Path, PathBuf},
process::ExitStatus,
thread::{self, JoinHandle},
};
use util::paths::PathLikeWithPosition;
@ -14,6 +16,7 @@ struct Detect;
trait InstalledApp {
fn zed_version_string(&self) -> String;
fn launch(&self, ipc_url: String) -> anyhow::Result<()>;
fn run_foreground(&self, ipc_url: String) -> io::Result<ExitStatus>;
}
#[derive(Parser, Debug)]
@ -37,6 +40,9 @@ struct Args {
/// Print Zed's version and the app path.
#[arg(short, long)]
version: bool,
/// Run zed in the foreground (useful for debugging)
#[arg(long)]
foreground: bool,
/// Custom path to Zed.app or the zed binary
#[arg(long)]
zed: Option<PathBuf>,
@ -99,10 +105,6 @@ fn main() -> Result<()> {
IpcOneShotServer::<IpcHandshake>::new().context("Handshake before Zed spawn")?;
let url = format!("zed-cli://{server_name}");
app.launch(url)?;
let (_, handshake) = server.accept().context("Handshake after Zed spawn")?;
let (tx, rx) = (handshake.requests, handshake.responses);
let open_new_workspace = if args.new {
Some(true)
} else if args.add {
@ -111,20 +113,33 @@ fn main() -> Result<()> {
None
};
tx.send(CliRequest::Open {
paths,
wait: args.wait,
open_new_workspace,
dev_server_token: args.dev_server_token,
})?;
let sender: JoinHandle<anyhow::Result<()>> = thread::spawn(move || {
let (_, handshake) = server.accept().context("Handshake after Zed spawn")?;
let (tx, rx) = (handshake.requests, handshake.responses);
tx.send(CliRequest::Open {
paths,
wait: args.wait,
open_new_workspace,
dev_server_token: args.dev_server_token,
})?;
while let Ok(response) = rx.recv() {
match response {
CliResponse::Ping => {}
CliResponse::Stdout { message } => println!("{message}"),
CliResponse::Stderr { message } => eprintln!("{message}"),
CliResponse::Exit { status } => std::process::exit(status),
while let Ok(response) = rx.recv() {
match response {
CliResponse::Ping => {}
CliResponse::Stdout { message } => println!("{message}"),
CliResponse::Stderr { message } => eprintln!("{message}"),
CliResponse::Exit { status } => std::process::exit(status),
}
}
Ok(())
});
if args.foreground {
app.run_foreground(url)?;
} else {
app.launch(url)?;
sender.join().unwrap()?;
}
Ok(())
@ -141,7 +156,8 @@ mod linux {
unix::net::{SocketAddr, UnixDatagram},
},
path::{Path, PathBuf},
process, thread,
process::{self, ExitStatus},
thread,
time::Duration,
};
@ -208,6 +224,12 @@ mod linux {
}
Ok(())
}
fn run_foreground(&self, ipc_url: String) -> io::Result<ExitStatus> {
std::process::Command::new(self.0.clone())
.arg(ipc_url)
.status()
}
}
impl App {
@ -257,7 +279,9 @@ mod linux {
#[cfg(target_os = "windows")]
mod windows {
use crate::{Detect, InstalledApp};
use std::io;
use std::path::Path;
use std::process::ExitStatus;
struct App;
impl InstalledApp for App {
@ -267,6 +291,9 @@ mod windows {
fn launch(&self, _ipc_url: String) -> anyhow::Result<()> {
unimplemented!()
}
fn run_foreground(&self, _ipc_url: String) -> io::Result<ExitStatus> {
unimplemented!()
}
}
impl Detect {
@ -288,9 +315,9 @@ mod mac_os {
use serde::Deserialize;
use std::{
ffi::OsStr,
fs,
fs, io,
path::{Path, PathBuf},
process::Command,
process::{Command, ExitStatus},
ptr,
};
@ -442,6 +469,15 @@ mod mac_os {
Ok(())
}
fn run_foreground(&self, ipc_url: String) -> io::Result<ExitStatus> {
let path = match self {
Bundle::App { app_bundle, .. } => app_bundle.join("Contents/MacOS/zed"),
Bundle::LocalPath { executable, .. } => executable.clone(),
};
std::process::Command::new(path).arg(ipc_url).status()
}
}
impl Bundle {