1mod assets;
2mod only_instance;
3mod open_listener;
4
5pub use assets::*;
6use gpui2::AsyncAppContext;
7pub use only_instance::*;
8pub use open_listener::*;
9
10use anyhow::{Context, Result};
11use cli::{
12 ipc::{self, IpcSender},
13 CliRequest, CliResponse, IpcHandshake,
14};
15use futures::{channel::mpsc, SinkExt, StreamExt};
16use std::{sync::Arc, thread};
17
18pub fn connect_to_cli(
19 server_name: &str,
20) -> Result<(mpsc::Receiver<CliRequest>, IpcSender<CliResponse>)> {
21 let handshake_tx = cli::ipc::IpcSender::<IpcHandshake>::connect(server_name.to_string())
22 .context("error connecting to cli")?;
23 let (request_tx, request_rx) = ipc::channel::<CliRequest>()?;
24 let (response_tx, response_rx) = ipc::channel::<CliResponse>()?;
25
26 handshake_tx
27 .send(IpcHandshake {
28 requests: request_tx,
29 responses: response_rx,
30 })
31 .context("error sending ipc handshake")?;
32
33 let (mut async_request_tx, async_request_rx) =
34 futures::channel::mpsc::channel::<CliRequest>(16);
35 thread::spawn(move || {
36 while let Ok(cli_request) = request_rx.recv() {
37 if smol::block_on(async_request_tx.send(cli_request)).is_err() {
38 break;
39 }
40 }
41 Ok::<_, anyhow::Error>(())
42 });
43
44 Ok((async_request_rx, response_tx))
45}
46
47pub struct AppState;
48
49pub async fn handle_cli_connection(
50 (mut requests, _responses): (mpsc::Receiver<CliRequest>, IpcSender<CliResponse>),
51 _app_state: Arc<AppState>,
52 mut _cx: AsyncAppContext,
53) {
54 if let Some(request) = requests.next().await {
55 match request {
56 CliRequest::Open { paths: _, wait: _ } => {
57 // let mut caret_positions = HashMap::new();
58
59 // let paths = if paths.is_empty() {
60 // todo!()
61 // workspace::last_opened_workspace_paths()
62 // .await
63 // .map(|location| location.paths().to_vec())
64 // .unwrap_or_default()
65 // } else {
66 // paths
67 // .into_iter()
68 // .filter_map(|path_with_position_string| {
69 // let path_with_position = PathLikeWithPosition::parse_str(
70 // &path_with_position_string,
71 // |path_str| {
72 // Ok::<_, std::convert::Infallible>(
73 // Path::new(path_str).to_path_buf(),
74 // )
75 // },
76 // )
77 // .expect("Infallible");
78 // let path = path_with_position.path_like;
79 // if let Some(row) = path_with_position.row {
80 // if path.is_file() {
81 // let row = row.saturating_sub(1);
82 // let col =
83 // path_with_position.column.unwrap_or(0).saturating_sub(1);
84 // caret_positions.insert(path.clone(), Point::new(row, col));
85 // }
86 // }
87 // Some(path)
88 // })
89 // .collect()
90 // };
91
92 // let mut errored = false;
93 // todo!("workspace")
94 // match cx
95 // .update(|cx| workspace::open_paths(&paths, &app_state, None, cx))
96 // .await
97 // {
98 // Ok((workspace, items)) => {
99 // let mut item_release_futures = Vec::new();
100
101 // for (item, path) in items.into_iter().zip(&paths) {
102 // match item {
103 // Some(Ok(item)) => {
104 // if let Some(point) = caret_positions.remove(path) {
105 // if let Some(active_editor) = item.downcast::<Editor>() {
106 // active_editor
107 // .downgrade()
108 // .update(&mut cx, |editor, cx| {
109 // let snapshot =
110 // editor.snapshot(cx).display_snapshot;
111 // let point = snapshot
112 // .buffer_snapshot
113 // .clip_point(point, Bias::Left);
114 // editor.change_selections(
115 // Some(Autoscroll::center()),
116 // cx,
117 // |s| s.select_ranges([point..point]),
118 // );
119 // })
120 // .log_err();
121 // }
122 // }
123
124 // let released = oneshot::channel();
125 // cx.update(|cx| {
126 // item.on_release(
127 // cx,
128 // Box::new(move |_| {
129 // let _ = released.0.send(());
130 // }),
131 // )
132 // .detach();
133 // });
134 // item_release_futures.push(released.1);
135 // }
136 // Some(Err(err)) => {
137 // responses
138 // .send(CliResponse::Stderr {
139 // message: format!("error opening {:?}: {}", path, err),
140 // })
141 // .log_err();
142 // errored = true;
143 // }
144 // None => {}
145 // }
146 // }
147
148 // if wait {
149 // let background = cx.background();
150 // let wait = async move {
151 // if paths.is_empty() {
152 // let (done_tx, done_rx) = oneshot::channel();
153 // if let Some(workspace) = workspace.upgrade(&cx) {
154 // let _subscription = cx.update(|cx| {
155 // cx.observe_release(&workspace, move |_, _| {
156 // let _ = done_tx.send(());
157 // })
158 // });
159 // drop(workspace);
160 // let _ = done_rx.await;
161 // }
162 // } else {
163 // let _ =
164 // futures::future::try_join_all(item_release_futures).await;
165 // };
166 // }
167 // .fuse();
168 // futures::pin_mut!(wait);
169
170 // loop {
171 // // Repeatedly check if CLI is still open to avoid wasting resources
172 // // waiting for files or workspaces to close.
173 // let mut timer = background.timer(Duration::from_secs(1)).fuse();
174 // futures::select_biased! {
175 // _ = wait => break,
176 // _ = timer => {
177 // if responses.send(CliResponse::Ping).is_err() {
178 // break;
179 // }
180 // }
181 // }
182 // }
183 // }
184 // }
185 // Err(error) => {
186 // errored = true;
187 // responses
188 // .send(CliResponse::Stderr {
189 // message: format!("error opening {:?}: {}", paths, error),
190 // })
191 // .log_err();
192 // }
193 // }
194
195 // responses
196 // .send(CliResponse::Exit {
197 // status: i32::from(errored),
198 // })
199 // .log_err();
200 }
201 }
202 }
203}