1// Allow binary to be called Zed for a nice application menu when running executable direcly
2#![allow(non_snake_case)]
3
4use client::{self, http, ChannelList, UserStore};
5use fs::OpenOptions;
6use gpui::AssetSource;
7use log::LevelFilter;
8use parking_lot::Mutex;
9use simplelog::SimpleLogger;
10use std::{fs, path::PathBuf, sync::Arc};
11use theme::{ThemeRegistry, DEFAULT_THEME_NAME};
12use workspace::{self, settings, AppState, OpenNew, OpenParams, OpenPaths, Settings};
13use zed::{
14 self, assets::Assets, build_window_options, build_workspace, fs::RealFs, language, menus,
15};
16
17fn main() {
18 init_logger();
19
20 let app = gpui::App::new(Assets).unwrap();
21 let embedded_fonts = Assets
22 .list("fonts")
23 .into_iter()
24 .map(|f| Arc::new(Assets.load(&f).unwrap().to_vec()))
25 .collect::<Vec<_>>();
26 app.platform().fonts().add_fonts(&embedded_fonts).unwrap();
27
28 let themes = ThemeRegistry::new(Assets, app.font_cache());
29 let theme = themes.get(DEFAULT_THEME_NAME).unwrap();
30 let settings = Settings::new("Inconsolata", &app.font_cache(), theme)
31 .unwrap()
32 .with_overrides(
33 language::PLAIN_TEXT.name(),
34 settings::Override {
35 soft_wrap: Some(settings::SoftWrap::PreferredLineLength),
36 ..Default::default()
37 },
38 )
39 .with_overrides(
40 "Markdown",
41 settings::Override {
42 soft_wrap: Some(settings::SoftWrap::PreferredLineLength),
43 ..Default::default()
44 },
45 );
46 let (settings_tx, settings) = postage::watch::channel_with(settings);
47 let languages = Arc::new(language::build_language_registry());
48 languages.set_theme(&settings.borrow().theme.editor.syntax);
49
50 app.run(move |cx| {
51 let http = http::client();
52 let client = client::Client::new(http.clone());
53 let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http.clone(), cx));
54 let mut path_openers = Vec::new();
55
56 client::init(client.clone(), cx);
57 workspace::init(cx);
58 editor::init(cx, &mut path_openers);
59 go_to_line::init(cx);
60 file_finder::init(cx);
61 chat_panel::init(cx);
62 project_panel::init(cx);
63 diagnostics::init(cx);
64
65 let app_state = Arc::new(AppState {
66 languages: languages.clone(),
67 settings_tx: Arc::new(Mutex::new(settings_tx)),
68 settings,
69 themes,
70 channel_list: cx
71 .add_model(|cx| ChannelList::new(user_store.clone(), client.clone(), cx)),
72 client,
73 user_store,
74 fs: Arc::new(RealFs),
75 path_openers: Arc::from(path_openers),
76 build_window_options: &build_window_options,
77 build_workspace: &build_workspace,
78 });
79 journal::init(app_state.clone(), cx);
80 zed::init(&app_state, cx);
81 theme_selector::init(app_state.as_ref().into(), cx);
82
83 cx.set_menus(menus::menus(&app_state.clone()));
84
85 if stdout_is_a_pty() {
86 cx.platform().activate(true);
87 }
88
89 let paths = collect_path_args();
90 if paths.is_empty() {
91 cx.dispatch_global_action(OpenNew(app_state.clone()));
92 } else {
93 cx.dispatch_global_action(OpenPaths(OpenParams { paths, app_state }));
94 }
95 });
96}
97
98fn init_logger() {
99 let level = LevelFilter::Info;
100
101 if stdout_is_a_pty() {
102 SimpleLogger::init(level, Default::default()).expect("could not initialize logger");
103 } else {
104 let log_dir_path = dirs::home_dir()
105 .expect("could not locate home directory for logging")
106 .join("Library/Logs/");
107 let log_file_path = log_dir_path.join("Zed.log");
108 fs::create_dir_all(&log_dir_path).expect("could not create log directory");
109 let log_file = OpenOptions::new()
110 .create(true)
111 .append(true)
112 .open(log_file_path)
113 .expect("could not open logfile");
114 simplelog::WriteLogger::init(level, simplelog::Config::default(), log_file)
115 .expect("could not initialize logger");
116 log_panics::init();
117 }
118}
119
120fn stdout_is_a_pty() -> bool {
121 unsafe { libc::isatty(libc::STDOUT_FILENO as i32) != 0 }
122}
123
124fn collect_path_args() -> Vec<PathBuf> {
125 std::env::args()
126 .skip(1)
127 .filter_map(|arg| match fs::canonicalize(arg) {
128 Ok(path) => Some(path),
129 Err(error) => {
130 log::error!("error parsing path argument: {}", error);
131 None
132 }
133 })
134 .collect::<Vec<_>>()
135}