1// Allow binary to be called Zed for a nice application menu when running executable direcly
2#![allow(non_snake_case)]
3
4use fs::OpenOptions;
5use log::LevelFilter;
6use simplelog::SimpleLogger;
7use std::{fs, path::PathBuf};
8use zed::{
9 assets, editor, file_finder, menus, settings,
10 workspace::{self, OpenParams},
11};
12
13fn main() {
14 init_logger();
15
16 let app = gpui::App::new(assets::Assets).unwrap();
17 let (_, settings_rx) = settings::channel(&app.font_cache()).unwrap();
18 app.run(move |ctx| {
19 ctx.set_menus(menus::menus(settings_rx.clone()));
20 workspace::init(ctx);
21 editor::init(ctx);
22 file_finder::init(ctx);
23
24 if stdout_is_a_pty() {
25 ctx.platform().activate(true);
26 }
27
28 let paths = collect_path_args();
29 if !paths.is_empty() {
30 ctx.dispatch_global_action(
31 "workspace:open_paths",
32 OpenParams {
33 paths,
34 settings: settings_rx,
35 },
36 );
37 }
38 });
39}
40
41fn init_logger() {
42 let level = LevelFilter::Info;
43
44 if stdout_is_a_pty() {
45 SimpleLogger::init(level, Default::default()).expect("could not initialize logger");
46 } else {
47 let log_dir_path = dirs::home_dir()
48 .expect("could not locate home directory for logging")
49 .join("Library/Logs/");
50 let log_file_path = log_dir_path.join("Zed.log");
51 fs::create_dir_all(&log_dir_path).expect("could not create log directory");
52 let log_file = OpenOptions::new()
53 .create(true)
54 .append(true)
55 .open(log_file_path)
56 .expect("could not open logfile");
57 simplelog::WriteLogger::init(level, simplelog::Config::default(), log_file)
58 .expect("could not initialize logger");
59 }
60}
61
62fn stdout_is_a_pty() -> bool {
63 unsafe { libc::isatty(libc::STDOUT_FILENO as i32) != 0 }
64}
65
66fn collect_path_args() -> Vec<PathBuf> {
67 std::env::args()
68 .skip(1)
69 .filter_map(|arg| match fs::canonicalize(arg) {
70 Ok(path) => Some(path),
71 Err(error) => {
72 log::error!("error parsing path argument: {}", error);
73 None
74 }
75 })
76 .collect::<Vec<_>>()
77}