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