@@ -11,6 +11,7 @@ pub struct IpcHandshake {
pub enum CliRequest {
Open {
paths: Vec<String>,
+ urls: Vec<String>,
wait: bool,
open_new_workspace: Option<bool>,
dev_server_token: Option<String>,
@@ -5,6 +5,7 @@ use clap::Parser;
use cli::{ipc::IpcOneShotServer, CliRequest, CliResponse, IpcHandshake};
use parking_lot::Mutex;
use std::{
+ convert::Infallible,
env, fs, io,
path::{Path, PathBuf},
process::ExitStatus,
@@ -37,8 +38,7 @@ struct Args {
///
/// Use `path:line:row` syntax to open a file at a specific location.
/// Non-existing paths and directories will ignore `:line:row` suffix.
- #[arg(value_parser = parse_path_with_position)]
- paths_with_position: Vec<PathLikeWithPosition<PathBuf>>,
+ paths_with_position: Vec<String>,
/// Print Zed's version and the app path.
#[arg(short, long)]
version: bool,
@@ -53,12 +53,30 @@ struct Args {
dev_server_token: Option<String>,
}
-fn parse_path_with_position(
- argument_str: &str,
-) -> Result<PathLikeWithPosition<PathBuf>, std::convert::Infallible> {
- PathLikeWithPosition::parse_str(argument_str, |_, path_str| {
+fn parse_path_with_position(argument_str: &str) -> Result<String, std::io::Error> {
+ let path_like = PathLikeWithPosition::parse_str::<Infallible>(argument_str, |_, path_str| {
Ok(Path::new(path_str).to_path_buf())
})
+ .unwrap();
+ let curdir = env::current_dir()?;
+
+ let canonicalized = path_like.map_path_like(|path| match fs::canonicalize(&path) {
+ Ok(path) => Ok(path),
+ Err(e) => {
+ if let Some(mut parent) = path.parent() {
+ if parent == Path::new("") {
+ parent = &curdir
+ }
+ match fs::canonicalize(parent) {
+ Ok(parent) => Ok(parent.join(path.file_name().unwrap())),
+ Err(_) => Err(e),
+ }
+ } else {
+ Err(e)
+ }
+ }
+ })?;
+ Ok(canonicalized.to_string(|path| path.display().to_string()))
}
fn main() -> Result<()> {
@@ -91,28 +109,6 @@ fn main() -> Result<()> {
return Ok(());
}
- let curdir = env::current_dir()?;
- let mut paths = vec![];
- for path in args.paths_with_position {
- let canonicalized = path.map_path_like(|path| match fs::canonicalize(&path) {
- Ok(path) => Ok(path),
- Err(e) => {
- if let Some(mut parent) = path.parent() {
- if parent == Path::new("") {
- parent = &curdir;
- }
- match fs::canonicalize(parent) {
- Ok(parent) => Ok(parent.join(path.file_name().unwrap())),
- Err(_) => Err(e),
- }
- } else {
- Err(e)
- }
- }
- })?;
- paths.push(canonicalized.to_string(|path| path.display().to_string()))
- }
-
let (server, server_name) =
IpcOneShotServer::<IpcHandshake>::new().context("Handshake before Zed spawn")?;
let url = format!("zed-cli://{server_name}");
@@ -126,6 +122,19 @@ fn main() -> Result<()> {
};
let exit_status = Arc::new(Mutex::new(None));
+ let mut paths = vec![];
+ let mut urls = vec![];
+ for path in args.paths_with_position.iter() {
+ if path.starts_with("zed://")
+ || path.starts_with("http://")
+ || path.starts_with("https://")
+ || path.starts_with("file://")
+ {
+ urls.push(path.to_string());
+ } else {
+ paths.push(parse_path_with_position(path)?)
+ }
+ }
let sender: JoinHandle<anyhow::Result<()>> = thread::spawn({
let exit_status = exit_status.clone();
@@ -134,6 +143,7 @@ fn main() -> Result<()> {
let (tx, rx) = (handshake.requests, handshake.responses);
tx.send(CliRequest::Open {
paths,
+ urls,
wait: args.wait,
open_new_workspace,
dev_server_token: args.dev_server_token,
@@ -4,13 +4,13 @@ Type=Application
Name=$APP_NAME
GenericName=Text Editor
Comment=A high-performance, multiplayer code editor.
-TryExec=$APP_CLI
+TryExec=$APP
StartupNotify=$DO_STARTUP_NOTIFY
Exec=$APP_CLI $APP_ARGS
Icon=$APP_ICON
Categories=Utility;TextEditor;Development;IDE;
Keywords=zed;
-MimeType=text/plain;inode/directory;
+MimeType=text/plain;inode/directory;x-scheme-handler/zed;
Actions=NewWorkspace;
[Desktop Action NewWorkspace]
@@ -22,7 +22,7 @@ use welcome::{show_welcome_view, FIRST_OPEN};
use workspace::item::ItemHandle;
use workspace::{AppState, Workspace};
-use crate::{init_headless, init_ui};
+use crate::{handle_open_request, init_headless, init_ui};
#[derive(Default, Debug)]
pub struct OpenRequest {
@@ -223,6 +223,7 @@ pub async fn handle_cli_connection(
if let Some(request) = requests.next().await {
match request {
CliRequest::Open {
+ urls,
paths,
wait,
open_new_workspace,
@@ -257,6 +258,27 @@ pub async fn handle_cli_connection(
return;
}
+ if !urls.is_empty() {
+ cx.update(|cx| {
+ match OpenRequest::parse(urls, cx) {
+ Ok(open_request) => {
+ handle_open_request(open_request, app_state.clone(), cx);
+ responses.send(CliResponse::Exit { status: 0 }).log_err();
+ }
+ Err(e) => {
+ responses
+ .send(CliResponse::Stderr {
+ message: format!("{e}"),
+ })
+ .log_err();
+ responses.send(CliResponse::Exit { status: 1 }).log_err();
+ }
+ };
+ })
+ .log_err();
+ return;
+ }
+
if let Err(e) = cx
.update(|cx| init_ui(app_state.clone(), cx))
.and_then(|r| r)