Locate app bundle based on location of CLI binary
The app bundle can also be specified via `-b` or `--bundle-path`. Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
f77239bd96
commit
07562c2ccd
3 changed files with 20 additions and 40 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -998,12 +998,10 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap 3.1.8",
|
"clap 3.1.8",
|
||||||
"cocoa",
|
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
"core-services",
|
"core-services",
|
||||||
"dirs 3.0.1",
|
"dirs 3.0.1",
|
||||||
"ipc-channel",
|
"ipc-channel",
|
||||||
"objc",
|
|
||||||
"plist",
|
"plist",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
|
@ -19,8 +19,6 @@ ipc-channel = "0.16"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
cocoa = "0.24"
|
|
||||||
core-foundation = "0.9"
|
core-foundation = "0.9"
|
||||||
core-services = "0.2"
|
core-services = "0.2"
|
||||||
objc = "0.2"
|
|
||||||
plist = "1.3"
|
plist = "1.3"
|
|
@ -8,9 +8,8 @@ use core_foundation::{
|
||||||
};
|
};
|
||||||
use core_services::{kLSLaunchDefaults, LSLaunchURLSpec, LSOpenFromURLSpec, TCFType};
|
use core_services::{kLSLaunchDefaults, LSLaunchURLSpec, LSOpenFromURLSpec, TCFType};
|
||||||
use ipc_channel::ipc::{IpcOneShotServer, IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{IpcOneShotServer, IpcReceiver, IpcSender};
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{ffi::CStr, fs, path::PathBuf, ptr};
|
use std::{ffi::OsStr, fs, path::PathBuf, ptr};
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[clap(name = "zed", global_setting(clap::AppSettings::NoAutoVersion))]
|
#[clap(name = "zed", global_setting(clap::AppSettings::NoAutoVersion))]
|
||||||
|
@ -24,6 +23,9 @@ struct Args {
|
||||||
/// Print Zed's version and the app path.
|
/// Print Zed's version and the app path.
|
||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
version: bool,
|
version: bool,
|
||||||
|
/// Custom Zed.app path
|
||||||
|
#[clap(short, long)]
|
||||||
|
bundle_path: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
@ -35,19 +37,24 @@ struct InfoPlist {
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
let app_path = locate_app()?;
|
let bundle_path = if let Some(bundle_path) = args.bundle_path {
|
||||||
|
bundle_path.canonicalize()?
|
||||||
|
} else {
|
||||||
|
locate_bundle()?
|
||||||
|
};
|
||||||
|
|
||||||
if args.version {
|
if args.version {
|
||||||
let plist_path = app_path.join("Contents/Info.plist");
|
let plist_path = bundle_path.join("Contents/Info.plist");
|
||||||
let plist = plist::from_file::<_, InfoPlist>(plist_path)?;
|
let plist = plist::from_file::<_, InfoPlist>(plist_path)?;
|
||||||
println!(
|
println!(
|
||||||
"Zed {} – {}",
|
"Zed {} – {}",
|
||||||
plist.bundle_short_version_string,
|
plist.bundle_short_version_string,
|
||||||
app_path.to_string_lossy()
|
bundle_path.to_string_lossy()
|
||||||
);
|
);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tx, rx) = launch_app(app_path)?;
|
let (tx, rx) = launch_app(bundle_path)?;
|
||||||
|
|
||||||
tx.send(CliRequest::Open {
|
tx.send(CliRequest::Open {
|
||||||
paths: args
|
paths: args
|
||||||
|
@ -70,38 +77,15 @@ fn main() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn locate_app() -> Result<PathBuf> {
|
fn locate_bundle() -> Result<PathBuf> {
|
||||||
if cfg!(debug_assertions) {
|
let cli_path = std::env::current_exe()?.canonicalize()?;
|
||||||
Ok(std::env::current_exe()?
|
let mut app_path = cli_path.clone();
|
||||||
.parent()
|
while app_path.extension() != Some(OsStr::new("app")) {
|
||||||
.unwrap()
|
if !app_path.pop() {
|
||||||
.join("bundle/osx/Zed.app"))
|
return Err(anyhow!("cannot find app bundle containing {:?}", cli_path));
|
||||||
} else {
|
|
||||||
Ok(path_to_app_with_bundle_identifier("dev.zed.Zed")
|
|
||||||
.unwrap_or_else(|| "/Applications/Zed.dev".into()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn path_to_app_with_bundle_identifier(bundle_id: &str) -> Option<PathBuf> {
|
|
||||||
use cocoa::{
|
|
||||||
base::{id, nil},
|
|
||||||
foundation::{NSString, NSURL as _},
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let workspace: id = msg_send![class!(NSWorkspace), sharedWorkspace];
|
|
||||||
let bundle_id = NSString::alloc(nil).init_str(bundle_id);
|
|
||||||
let app_url: id = msg_send![workspace, URLForApplicationWithBundleIdentifier: bundle_id];
|
|
||||||
if !app_url.is_null() {
|
|
||||||
Some(PathBuf::from(
|
|
||||||
CStr::from_ptr(app_url.path().UTF8String())
|
|
||||||
.to_string_lossy()
|
|
||||||
.to_string(),
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(app_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn launch_app(app_path: PathBuf) -> Result<(IpcSender<CliRequest>, IpcReceiver<CliResponse>)> {
|
fn launch_app(app_path: PathBuf) -> Result<(IpcSender<CliRequest>, IpcReceiver<CliResponse>)> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue