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