1use fs::RealFs;
2use futures::channel::mpsc;
3use gpui::Context as _;
4use remote::{
5 protocol::{read_message, write_message},
6 SshSession,
7};
8use remote_server::HeadlessProject;
9use smol::{io::AsyncWriteExt, stream::StreamExt as _, Async};
10use std::{env, io, mem, process, sync::Arc};
11
12fn main() {
13 env::set_var("RUST_BACKTRACE", "1");
14
15 let subcommand = std::env::args().nth(1);
16 match subcommand.as_deref() {
17 Some("run") => {}
18 Some("version") => {
19 println!("{}", env!("ZED_PKG_VERSION"));
20 return;
21 }
22 _ => {
23 eprintln!("usage: remote <run|version>");
24 process::exit(1);
25 }
26 }
27
28 env_logger::init();
29
30 gpui::App::headless().run(move |cx| {
31 HeadlessProject::init(cx);
32
33 let (incoming_tx, incoming_rx) = mpsc::unbounded();
34 let (outgoing_tx, mut outgoing_rx) = mpsc::unbounded();
35
36 let mut stdin = Async::new(io::stdin()).unwrap();
37 let mut stdout = Async::new(io::stdout()).unwrap();
38
39 let session = SshSession::server(incoming_rx, outgoing_tx, cx);
40 let project = cx.new_model(|cx| {
41 HeadlessProject::new(
42 session.clone(),
43 Arc::new(RealFs::new(Default::default(), None)),
44 cx,
45 )
46 });
47
48 cx.background_executor()
49 .spawn(async move {
50 let mut output_buffer = Vec::new();
51 while let Some(message) = outgoing_rx.next().await {
52 write_message(&mut stdout, &mut output_buffer, message).await?;
53 stdout.flush().await?;
54 }
55 anyhow::Ok(())
56 })
57 .detach();
58
59 cx.background_executor()
60 .spawn(async move {
61 let mut input_buffer = Vec::new();
62 loop {
63 let message = match read_message(&mut stdin, &mut input_buffer).await {
64 Ok(message) => message,
65 Err(error) => {
66 log::warn!("error reading message: {:?}", error);
67 process::exit(0);
68 }
69 };
70 incoming_tx.unbounded_send(message).ok();
71 }
72 })
73 .detach();
74
75 mem::forget(project);
76 });
77}