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