main.rs

 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, sync::Arc};
 8use zed::{
 9    self, assets, editor, file_finder, language, menus, rpc, settings,
10    workspace::{self, OpenParams},
11    worktree, AppState,
12};
13
14fn main() {
15    init_logger();
16
17    let app = gpui::App::new(assets::Assets).unwrap();
18
19    let (_, settings) = settings::channel(&app.font_cache()).unwrap();
20    let language_registry = Arc::new(language::LanguageRegistry::new());
21    language_registry.set_theme(&settings.borrow().theme);
22
23    let app_state = AppState {
24        language_registry: language_registry.clone(),
25        settings,
26        rpc: rpc::Client::new(language_registry),
27    };
28
29    app.run(move |cx| {
30        cx.set_menus(menus::menus(app_state.clone()));
31        zed::init(cx);
32        workspace::init(cx);
33        worktree::init(cx, app_state.rpc.clone());
34        editor::init(cx);
35        file_finder::init(cx);
36
37        if stdout_is_a_pty() {
38            cx.platform().activate(true);
39        }
40
41        let paths = collect_path_args();
42        if !paths.is_empty() {
43            cx.dispatch_global_action(
44                "workspace:open_paths",
45                OpenParams {
46                    paths,
47                    app_state: app_state.clone(),
48                },
49            );
50        }
51    });
52}
53
54fn init_logger() {
55    let level = LevelFilter::Info;
56
57    if stdout_is_a_pty() {
58        SimpleLogger::init(level, Default::default()).expect("could not initialize logger");
59    } else {
60        let log_dir_path = dirs::home_dir()
61            .expect("could not locate home directory for logging")
62            .join("Library/Logs/");
63        let log_file_path = log_dir_path.join("Zed.log");
64        fs::create_dir_all(&log_dir_path).expect("could not create log directory");
65        let log_file = OpenOptions::new()
66            .create(true)
67            .append(true)
68            .open(log_file_path)
69            .expect("could not open logfile");
70        simplelog::WriteLogger::init(level, simplelog::Config::default(), log_file)
71            .expect("could not initialize logger");
72    }
73}
74
75fn stdout_is_a_pty() -> bool {
76    unsafe { libc::isatty(libc::STDOUT_FILENO as i32) != 0 }
77}
78
79fn collect_path_args() -> Vec<PathBuf> {
80    std::env::args()
81        .skip(1)
82        .filter_map(|arg| match fs::canonicalize(arg) {
83            Ok(path) => Some(path),
84            Err(error) => {
85                log::error!("error parsing path argument: {}", error);
86                None
87            }
88        })
89        .collect::<Vec<_>>()
90}