From 6b65d76014504458436e79f8ef7e1cb3e8493a8a Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Sat, 28 Oct 2023 11:37:25 -0400 Subject: [PATCH] Port journal to GPUI2 --- Cargo.lock | 19 ++++ Cargo.toml | 1 + crates/journal2/Cargo.toml | 27 +++++ crates/journal2/src/journal2.rs | 176 ++++++++++++++++++++++++++++++++ crates/zed-actions/src/lib.rs | 30 +++--- crates/zed2/Cargo.toml | 2 +- crates/zed2/src/main.rs | 2 +- 7 files changed, 240 insertions(+), 17 deletions(-) create mode 100644 crates/journal2/Cargo.toml create mode 100644 crates/journal2/src/journal2.rs diff --git a/Cargo.lock b/Cargo.lock index 450d435ac2..5e158405b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4171,6 +4171,24 @@ dependencies = [ "workspace", ] +[[package]] +name = "journal2" +version = "0.1.0" +dependencies = [ + "anyhow", + "chrono", + "dirs 4.0.0", + "editor", + "gpui2", + "log", + "schemars", + "serde", + "settings2", + "shellexpand", + "util", + "workspace", +] + [[package]] name = "jpeg-decoder" version = "0.1.22" @@ -10903,6 +10921,7 @@ dependencies = [ "indexmap 1.9.3", "install_cli", "isahc", + "journal2", "language2", "language_tools", "lazy_static", diff --git a/Cargo.toml b/Cargo.toml index 7db8e1073d..2627afb4ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,7 @@ members = [ "crates/install_cli", "crates/install_cli2", "crates/journal", + "crates/journal2", "crates/language", "crates/language2", "crates/language_selector", diff --git a/crates/journal2/Cargo.toml b/crates/journal2/Cargo.toml new file mode 100644 index 0000000000..8da2f51a62 --- /dev/null +++ b/crates/journal2/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "journal2" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +path = "src/journal2.rs" +doctest = false + +[dependencies] +editor = { path = "../editor" } +gpui2 = { path = "../gpui2" } +util = { path = "../util" } +workspace = { path = "../workspace" } +settings2 = { path = "../settings2" } + +anyhow.workspace = true +chrono = "0.4" +dirs = "4.0" +serde.workspace = true +schemars.workspace = true +log.workspace = true +shellexpand = "2.1.0" + +[dev-dependencies] +editor = { path = "../editor", features = ["test-support"] } diff --git a/crates/journal2/src/journal2.rs b/crates/journal2/src/journal2.rs new file mode 100644 index 0000000000..6268548530 --- /dev/null +++ b/crates/journal2/src/journal2.rs @@ -0,0 +1,176 @@ +use anyhow::Result; +use chrono::{Datelike, Local, NaiveTime, Timelike}; +use gpui2::AppContext; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use settings2::Settings; +use std::{ + fs::OpenOptions, + path::{Path, PathBuf}, + sync::Arc, +}; +use workspace::AppState; +// use zed::AppState; + +// todo!(); +// actions!(journal, [NewJournalEntry]); + +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +pub struct JournalSettings { + pub path: Option, + pub hour_format: Option, +} + +impl Default for JournalSettings { + fn default() -> Self { + Self { + path: Some("~".into()), + hour_format: Some(Default::default()), + } + } +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum HourFormat { + #[default] + Hour12, + Hour24, +} + +impl settings2::Settings for JournalSettings { + const KEY: Option<&'static str> = Some("journal"); + + type FileContent = Self; + + fn load( + defaults: &Self::FileContent, + user_values: &[&Self::FileContent], + _: &mut AppContext, + ) -> Result { + Self::load_via_json_merge(defaults, user_values) + } +} + +pub fn init(_: Arc, cx: &mut AppContext) { + JournalSettings::register(cx); + + // todo!() + // cx.add_global_action(move |_: &NewJournalEntry, cx| new_journal_entry(app_state.clone(), cx)); +} + +pub fn new_journal_entry(_: Arc, cx: &mut AppContext) { + let settings = JournalSettings::get_global(cx); + let journal_dir = match journal_dir(settings.path.as_ref().unwrap()) { + Some(journal_dir) => journal_dir, + None => { + log::error!("Can't determine journal directory"); + return; + } + }; + + let now = Local::now(); + let month_dir = journal_dir + .join(format!("{:02}", now.year())) + .join(format!("{:02}", now.month())); + let entry_path = month_dir.join(format!("{:02}.md", now.day())); + let now = now.time(); + let _entry_heading = heading_entry(now, &settings.hour_format); + + let _create_entry = cx.executor().spawn(async move { + std::fs::create_dir_all(month_dir)?; + OpenOptions::new() + .create(true) + .write(true) + .open(&entry_path)?; + Ok::<_, std::io::Error>((journal_dir, entry_path)) + }); + + // todo!("workspace") + // cx.spawn(|cx| async move { + // let (journal_dir, entry_path) = create_entry.await?; + // let (workspace, _) = + // cx.update(|cx| workspace::open_paths(&[journal_dir], &app_state, None, cx))?; + + // let opened = workspace + // .update(&mut cx, |workspace, cx| { + // workspace.open_paths(vec![entry_path], true, cx) + // })? + // .await; + + // if let Some(Some(Ok(item))) = opened.first() { + // if let Some(editor) = item.downcast::().map(|editor| editor.downgrade()) { + // editor.update(&mut cx, |editor, cx| { + // let len = editor.buffer().read(cx).len(cx); + // editor.change_selections(Some(Autoscroll::center()), cx, |s| { + // s.select_ranges([len..len]) + // }); + // if len > 0 { + // editor.insert("\n\n", cx); + // } + // editor.insert(&entry_heading, cx); + // editor.insert("\n\n", cx); + // })?; + // } + // } + + // anyhow::Ok(()) + // }) + // .detach_and_log_err(cx); +} + +fn journal_dir(path: &str) -> Option { + let expanded_journal_dir = shellexpand::full(path) //TODO handle this better + .ok() + .map(|dir| Path::new(&dir.to_string()).to_path_buf().join("journal")); + + return expanded_journal_dir; +} + +fn heading_entry(now: NaiveTime, hour_format: &Option) -> String { + match hour_format { + Some(HourFormat::Hour24) => { + let hour = now.hour(); + format!("# {}:{:02}", hour, now.minute()) + } + _ => { + let (pm, hour) = now.hour12(); + let am_or_pm = if pm { "PM" } else { "AM" }; + format!("# {}:{:02} {}", hour, now.minute(), am_or_pm) + } + } +} + +#[cfg(test)] +mod tests { + mod heading_entry_tests { + use super::super::*; + + #[test] + fn test_heading_entry_defaults_to_hour_12() { + let naive_time = NaiveTime::from_hms_milli_opt(15, 0, 0, 0).unwrap(); + let actual_heading_entry = heading_entry(naive_time, &None); + let expected_heading_entry = "# 3:00 PM"; + + assert_eq!(actual_heading_entry, expected_heading_entry); + } + + #[test] + fn test_heading_entry_is_hour_12() { + let naive_time = NaiveTime::from_hms_milli_opt(15, 0, 0, 0).unwrap(); + let actual_heading_entry = heading_entry(naive_time, &Some(HourFormat::Hour12)); + let expected_heading_entry = "# 3:00 PM"; + + assert_eq!(actual_heading_entry, expected_heading_entry); + } + + #[test] + fn test_heading_entry_is_hour_24() { + let naive_time = NaiveTime::from_hms_milli_opt(15, 0, 0, 0).unwrap(); + let actual_heading_entry = heading_entry(naive_time, &Some(HourFormat::Hour24)); + let expected_heading_entry = "# 15:00"; + + assert_eq!(actual_heading_entry, expected_heading_entry); + } + } +} diff --git a/crates/zed-actions/src/lib.rs b/crates/zed-actions/src/lib.rs index df6405a4b1..020601180e 100644 --- a/crates/zed-actions/src/lib.rs +++ b/crates/zed-actions/src/lib.rs @@ -7,26 +7,26 @@ actions!( zed, [ About, + DebugElements, + DecreaseBufferFontSize, Hide, HideOthers, - ShowAll, - Minimize, - Zoom, - ToggleFullScreen, - Quit, - DebugElements, - OpenLog, - OpenLicenses, - OpenTelemetryLog, - OpenKeymap, - OpenSettings, - OpenLocalSettings, - OpenDefaultSettings, - OpenDefaultKeymap, IncreaseBufferFontSize, - DecreaseBufferFontSize, + Minimize, + OpenDefaultKeymap, + OpenDefaultSettings, + OpenKeymap, + OpenLicenses, + OpenLocalSettings, + OpenLog, + OpenSettings, + OpenTelemetryLog, + Quit, ResetBufferFontSize, ResetDatabase, + ShowAll, + ToggleFullScreen, + Zoom, ] ); diff --git a/crates/zed2/Cargo.toml b/crates/zed2/Cargo.toml index 1d90536a33..a6b31871dd 100644 --- a/crates/zed2/Cargo.toml +++ b/crates/zed2/Cargo.toml @@ -43,7 +43,7 @@ fuzzy = { path = "../fuzzy" } # go_to_line = { path = "../go_to_line" } gpui2 = { path = "../gpui2" } install_cli = { path = "../install_cli" } -# journal = { path = "../journal" } +journal2 = { path = "../journal2" } language2 = { path = "../language2" } # language_selector = { path = "../language_selector" } lsp = { path = "../lsp" } diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index 44a441db0b..b9968a3ef5 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -188,7 +188,7 @@ fn main() { // workspace::init(app_state.clone(), cx); // recent_projects::init(cx); - // journal::init(app_state.clone(), cx); + // journal2::init(app_state.clone(), cx); // language_selector::init(cx); // theme_selector::init(cx); // activity_indicator::init(cx);