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