From fd0f0b11e77cc638f655f8de58b20ee00af2a6d2 Mon Sep 17 00:00:00 2001 From: Shafkath Shuhan Date: Mon, 30 Jan 2023 12:48:53 -0500 Subject: [PATCH] inline workspace commands --- helix-term/src/commands/typed.rs | 104 +++++++++++++++++++++++++-- helix-view/src/document.rs | 2 +- helix-view/src/editor.rs | 119 +------------------------------ 3 files changed, 103 insertions(+), 122 deletions(-) diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index a72d58327ef37..83dca04e6e8e5 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -1862,8 +1862,37 @@ fn save_workspace( saved_files.append(&mut new_files); UndoIndex(saved_files) }; - - cx.editor.save_workspace() + log::debug!("Saving undo index: {:?}", index); + + index + .serialize(&mut index_file) + .context("failed to save index")?; + + // Save the histories of open buffers. + for doc in cx.editor.documents_mut().filter(|doc| doc.path().is_some()) { + let path = doc.path().unwrap().clone(); + let last_saved_revision = doc.get_last_saved_revision(); + let history = doc.history.get_mut(); + let mtime = std::fs::metadata(path.clone())? + .modified()? + .duration_since(std::time::UNIX_EPOCH)? + .as_secs(); + + let mut file = workspace.get_mut(&index.find_id(&path).unwrap().to_string())?; + history + .serialize( + &mut file, + &mut std::fs::File::open(&path)?, + last_saved_revision, + mtime, + ) + .context(format!( + "failed to save history for {}", + path.to_string_lossy() + ))?; + log::debug!("Saved history for: {}", path.to_string_lossy()); + } + Ok(()) } fn open_workspace( @@ -1871,11 +1900,78 @@ fn open_workspace( _args: &[Cow], event: PromptEvent, ) -> anyhow::Result<()> { + use helix_view::workspace::undo::UndoIndex; + use helix_view::workspace::Workspace; + if event != PromptEvent::Validate { return Ok(()); } - cx.editor.open_workspace() + let mut workspace = Workspace::new()?; + let index = UndoIndex::deserialize(&mut workspace.get(".index")?) + .context("failed to load index")? + .0; + let scrolloff = cx.editor.config().scrolloff; + log::debug!("Loaded undo index: {:?}", index); + + // Open the documents in the index and load their histories. + for (id, path) in index { + if !path.exists() { + continue; + } + + // Close open buffers for the doc. + let doc_id = cx + .editor + .documents() + .find_map(|doc| (doc.path() == Some(&path)).then_some(doc.id())); + if let Some(id) = doc_id { + buffer_close_by_ids_impl(cx, &[id], false)?; + } + + let mut file = workspace.get(&id.to_string())?; + let last_mtime = std::fs::metadata(path.clone())? + .modified()? + .duration_since(std::time::UNIX_EPOCH)? + .as_secs(); + let id = cx.editor.open(path.as_path(), Action::Load)?; + let doc = doc_mut!(cx.editor, &id); + let (last_saved_revision, history) = match helix_core::history::History::deserialize( + &mut file, + &mut std::fs::File::open(&path)?, + last_mtime, + ) { + Ok(res) => res, + Err(e) => { + cx.editor.set_error(format!( + "failed to load undo file for {} because {e}", + path.to_string_lossy() + )); + continue; + } + }; + + // Jump to saved revision if the doc wasn't saved. + if history.current_revision() != last_saved_revision { + let view_id = doc + .selections() + .keys() + .next() + .copied() + .expect("No view_id available"); + let view = view_mut!(cx.editor, view_id); + apply_transaction( + &history.changes_since(last_saved_revision).unwrap(), + doc, + &view, + ); + view.ensure_cursor_in_view(&doc, scrolloff); + } + doc.history.set(history); + doc.set_last_saved_revision(last_saved_revision); + log::debug!("Loaded history for: {}", path.to_string_lossy()); + } + Ok(()) } pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[ @@ -2403,7 +2499,7 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[ TypableCommand { name: "open-workspace", aliases: &["ow"], - doc: "Open document undo history", + doc: "Open document undo history, overriding open buffers.", fun: open_workspace, completer: None, }, diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index 6b33ea6aa3086..b0b10a4b7d3c4 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -1005,7 +1005,7 @@ impl Document { } /// Get the document's latest saved revision. - pub fn get_last_saved_revision(&mut self) -> usize { + pub fn get_last_saved_revision(&self) -> usize { self.last_saved_revision } diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 4383fd3e1d6a7..1029c14f33130 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -1,5 +1,5 @@ use crate::{ - align_view, apply_transaction, + align_view, clipboard::{get_clipboard_provider, ClipboardProvider}, document::{DocumentSavedEventFuture, DocumentSavedEventResult, Mode}, graphics::{CursorKind, Rect}, @@ -7,7 +7,6 @@ use crate::{ input::KeyEvent, theme::{self, Theme}, tree::{self, Tree}, - workspace::{undo::UndoIndex, Workspace}, Align, Document, DocumentId, View, ViewId, }; use helix_vcs::DiffProviderRegistry; @@ -20,7 +19,6 @@ use tokio_stream::wrappers::UnboundedReceiverStream; use std::{ borrow::Cow, collections::{BTreeMap, HashMap}, - fs::File, io::stdin, num::NonZeroUsize, path::{Path, PathBuf}, @@ -36,7 +34,7 @@ use tokio::{ time::{sleep, Duration, Instant, Sleep}, }; -use anyhow::{anyhow, bail, Context, Error}; +use anyhow::{anyhow, bail, Error}; pub use helix_core::diagnostic::Severity; pub use helix_core::register::Registers; @@ -915,119 +913,6 @@ impl Editor { } } - // TODO: Async? - pub fn save_workspace(&mut self) -> anyhow::Result<()> { - let mut workspace = Workspace::new()?; - let mut index_file = workspace.get_mut("index.undo")?; - let index = { - let mut current_index = - UndoIndex::deserialize(&mut index_file).unwrap_or(UndoIndex::default()); - let new_files = self.documents().filter_map(|doc| { - doc.path().filter(|path| { - !current_index - .0 - .iter() - .any(|(_, indexed_path)| indexed_path == *path) - }) - }); - let mut last_id = current_index.0.last().map(|(id, _)| *id).unwrap_or(0); - current_index.0.append( - &mut new_files - .map(|path| { - let current_id = last_id; - last_id += 1; - (current_id, path.clone()) - }) - .collect(), - ); - current_index - }; - log::debug!("Saving undo index: {:?}", index); - - index - .serialize(&mut index_file) - .context("failed to serialize index")?; - for doc in self.documents_mut().filter(|doc| doc.path().is_some()) { - let history = doc.history.take(); - let last_saved_revision = doc.get_last_saved_revision(); - let path = doc.path().unwrap(); - let mtime = std::fs::metadata(path.clone())? - .modified()? - .duration_since(std::time::UNIX_EPOCH)? - .as_secs(); - let id = index.find_id(path).unwrap(); - let mut undo_file = workspace.get_mut(&id.to_string())?; - - history - .serialize( - &mut undo_file, - &mut File::open(path)?, - last_saved_revision, - mtime, - ) - .context(format!( - "failed to save history for {}", - path.to_string_lossy() - ))?; - doc.history.set(history); - } - Ok(()) - } - - pub fn open_workspace(&mut self) -> anyhow::Result<()> { - let mut workspace = Workspace::new()?; - let index = UndoIndex::deserialize(&mut workspace.get("index.undo")?) - .context("failed to load index")?; - - let scrolloff = self.config().scrolloff; - for (id, path) in index.0 { - if !path.exists() { - continue; - } - let current_view_id = view!(&self).id; - - let mut undo_file = workspace.get(&id.to_string())?; - let last_mtime = std::fs::metadata(path.clone())? - .modified()? - .duration_since(std::time::UNIX_EPOCH)? - .as_secs(); - let id = self.open(path.as_path(), Action::Load)?; - let doc = doc_mut!(self, &id); - let (last_saved_revision, history) = helix_core::history::History::deserialize( - &mut undo_file, - &mut File::open(path)?, - last_mtime, - ) - .context("failed to load history")?; - - if history.current_revision() != last_saved_revision { - let selections = doc.selections(); - let view_id = if selections.contains_key(¤t_view_id) { - // use current if possible - current_view_id - } else { - // Hack: we take the first available view_id - selections - .keys() - .next() - .copied() - .expect("No view_id available") - }; - let view = view_mut!(self, view_id); - apply_transaction( - &history.changes_since(last_saved_revision).unwrap(), - doc, - &view, - ); - view.ensure_cursor_in_view(&doc, scrolloff); - } - doc.history.set(history); - doc.set_last_saved_revision(last_saved_revision); - } - - Ok(()) - } - /// Current editing mode for the [`Editor`]. pub fn mode(&self) -> Mode { self.mode