From e4f18947de99e90b1f34328bfb0df2b8d0bbb0cc Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 18 Dec 2021 10:38:54 -0700 Subject: [PATCH] Insert a time heading when creating a journal entry --- Cargo.lock | 2 +- crates/editor/src/editor.rs | 2 +- crates/journal/Cargo.toml | 2 +- crates/journal/src/journal.rs | 54 ++++++++++++++++++++----------- crates/workspace/src/pane.rs | 6 ++-- crates/workspace/src/workspace.rs | 43 +++++++++++++++--------- 6 files changed, 70 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 09e08a510b..0b5450b8f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2501,9 +2501,9 @@ dependencies = [ name = "journal" version = "0.1.0" dependencies = [ - "anyhow", "chrono", "dirs 4.0.0", + "editor", "gpui", "log", "util", diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 539736aca2..968856493d 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1251,7 +1251,7 @@ impl Editor { } } - fn insert(&mut self, text: &str, cx: &mut ViewContext) { + pub fn insert(&mut self, text: &str, cx: &mut ViewContext) { self.start_transaction(cx); let old_selections = self.selections::(cx).collect::>(); let mut new_selections = Vec::new(); diff --git a/crates/journal/Cargo.toml b/crates/journal/Cargo.toml index 64786f34ae..b2c470f4c5 100644 --- a/crates/journal/Cargo.toml +++ b/crates/journal/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" path = "src/journal.rs" [dependencies] +editor = { path = "../editor" } gpui = { path = "../gpui" } util = { path = "../util" } workspace = { path = "../workspace" } -anyhow = "1.0" chrono = "0.4" dirs = "4.0" log = "0.4" \ No newline at end of file diff --git a/crates/journal/src/journal.rs b/crates/journal/src/journal.rs index a62fc0c562..11895426d3 100644 --- a/crates/journal/src/journal.rs +++ b/crates/journal/src/journal.rs @@ -1,8 +1,7 @@ -use std::{fs::OpenOptions, sync::Arc}; - -use anyhow::anyhow; -use chrono::{Datelike, Local}; +use chrono::{Datelike, Local, Timelike}; +use editor::{Autoscroll, Editor}; use gpui::{action, keymap::Binding, MutableAppContext}; +use std::{fs::OpenOptions, sync::Arc}; use util::TryFutureExt as _; use workspace::AppState; @@ -14,27 +13,37 @@ pub fn init(app_state: Arc, cx: &mut MutableAppContext) { } pub fn new_journal_entry(app_state: Arc, cx: &mut MutableAppContext) { - let paths = cx.background().spawn(async move { - let now = Local::now(); - let home_dir = dirs::home_dir().ok_or_else(|| anyhow!("can't determine home directory"))?; - let journal_dir = home_dir.join("journal"); - let month_dir = journal_dir - .join(now.year().to_string()) - .join(now.month().to_string()); - let entry_path = month_dir.join(format!("{}.md", now.day())); + let now = Local::now(); + let home_dir = match dirs::home_dir() { + Some(home_dir) => home_dir, + None => { + log::error!("can't determine home directory"); + return; + } + }; - std::fs::create_dir_all(dbg!(month_dir))?; + let journal_dir = home_dir.join("journal"); + let month_dir = journal_dir + .join(now.year().to_string()) + .join(now.month().to_string()); + let entry_path = month_dir.join(format!("{}.md", now.day())); + let now = now.time(); + let (pm, hour) = now.hour12(); + let am_or_pm = if pm { "PM" } else { "AM" }; + let entry_heading = format!("# {}:{} {}\n\n", hour, now.minute(), am_or_pm); + + let create_entry = cx.background().spawn(async move { + std::fs::create_dir_all(month_dir)?; OpenOptions::new() .create(true) .write(true) - .open(dbg!(&entry_path))?; - - Ok::<_, anyhow::Error>((journal_dir, entry_path)) + .open(&entry_path)?; + Ok::<_, std::io::Error>((journal_dir, entry_path)) }); cx.spawn(|mut cx| { async move { - let (journal_dir, entry_path) = paths.await?; + let (journal_dir, entry_path) = create_entry.await?; let workspace = cx .update(|cx| workspace::open_paths(&[journal_dir], &app_state, cx)) .await; @@ -46,7 +55,16 @@ pub fn new_journal_entry(app_state: Arc, cx: &mut MutableAppContext) { .await; if let Some(Some(Ok(item))) = opened.first() { - log::info!("opened an item!"); + if let Some(editor) = item.to_any().downcast::() { + editor.update(&mut cx, |editor, cx| { + let len = editor.buffer().read(cx).len(); + editor.select_ranges([len..len], Some(Autoscroll::Center), cx); + if len > 0 { + editor.insert("\n\n", cx); + } + editor.insert(&entry_heading, cx); + }); + } } Ok(()) diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index a13602016a..5a3411c926 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -107,15 +107,15 @@ impl Pane { &mut self, project_path: ProjectPath, cx: &mut ViewContext, - ) -> bool { + ) -> Option> { if let Some(index) = self.items.iter().position(|item| { item.project_path(cx.as_ref()) .map_or(false, |item_path| item_path == project_path) }) { self.activate_item(index, cx); - true + self.items.get(index).map(|handle| handle.boxed_clone()) } else { - false + None } } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 44d5d288b0..bd074f89f2 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -498,7 +498,7 @@ impl Workspace { &mut self, abs_paths: &[PathBuf], cx: &mut ViewContext, - ) -> Task, Arc>>>> { + ) -> Task, Arc>>>> { let entries = abs_paths .iter() .cloned() @@ -625,10 +625,12 @@ impl Workspace { &mut self, project_path: ProjectPath, cx: &mut ViewContext, - ) -> Option, Arc>>> { + ) -> Option, Arc>>> { let pane = self.active_pane().clone(); - if self.activate_or_open_existing_entry(project_path.clone(), &pane, cx) { - return None; + if let Some(existing_item) = + self.activate_or_open_existing_entry(project_path.clone(), &pane, cx) + { + return Some(cx.foreground().spawn(async move { Ok(existing_item) })); } let worktree = match self @@ -687,10 +689,13 @@ impl Workspace { // By the time loading finishes, the entry could have been already added // to the pane. If it was, we activate it, otherwise we'll store the // item and add a new view for it. - if !this.activate_or_open_existing_entry(project_path, &pane, cx) { - this.add_item(item.boxed_clone(), cx); + if let Some(existing) = + this.activate_or_open_existing_entry(project_path, &pane, cx) + { + Ok(existing) + } else { + Ok(this.add_item(item.boxed_clone(), cx)) } - Ok(item) }) })) } @@ -700,11 +705,13 @@ impl Workspace { project_path: ProjectPath, pane: &ViewHandle, cx: &mut ViewContext, - ) -> bool { + ) -> Option> { // If the pane contains a view for this file, then activate // that item view. - if pane.update(cx, |pane, cx| pane.activate_entry(project_path.clone(), cx)) { - return true; + if let Some(existing_item_view) = + pane.update(cx, |pane, cx| pane.activate_entry(project_path.clone(), cx)) + { + return Some(existing_item_view); } // Otherwise, if this file is already open somewhere in the workspace, @@ -727,10 +734,10 @@ impl Workspace { } }); if let Some(view) = view_for_existing_item { - pane.add_item_view(view, cx.as_mut()); - true + pane.add_item_view(view.boxed_clone(), cx.as_mut()); + Some(view) } else { - false + None } } @@ -875,13 +882,19 @@ impl Workspace { pane } - pub fn add_item(&mut self, item_handle: T, cx: &mut ViewContext) + pub fn add_item( + &mut self, + item_handle: T, + cx: &mut ViewContext, + ) -> Box where T: ItemHandle, { let view = item_handle.add_view(cx.window_id(), self.settings.clone(), cx); self.items.push(item_handle.downgrade()); - self.active_pane().add_item_view(view, cx.as_mut()); + self.active_pane() + .add_item_view(view.boxed_clone(), cx.as_mut()); + view } fn activate_pane(&mut self, pane: ViewHandle, cx: &mut ViewContext) {