From 6efe2704e6e12669d7813cbaf75e1312b5977a2b Mon Sep 17 00:00:00 2001 From: Sugs Date: Sat, 24 Nov 2018 19:28:01 -0500 Subject: [PATCH] https://github.com/xi-editor/xi-editor/issues/922 Tailing a file with notify feature. --- rust/core-lib/src/editor.rs | 8 ++++++ rust/core-lib/src/event_context.rs | 6 ++++ rust/core-lib/src/file.rs | 44 +++++++++++++++++------------- rust/core-lib/src/tabs.rs | 3 +- 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/rust/core-lib/src/editor.rs b/rust/core-lib/src/editor.rs index 5f58f9d70..c2e8c3776 100644 --- a/rust/core-lib/src/editor.rs +++ b/rust/core-lib/src/editor.rs @@ -179,6 +179,14 @@ impl Editor { self.set_pristine(); } + pub fn tail_append(&mut self, tail: Rope) { + let buf_end = self.text.len(); + let mut builder = DeltaBuilder::new(buf_end); + builder.replace(buf_end..buf_end, tail); + self.add_delta(builder.build()); + self.set_pristine(); + } + // each outstanding plugin edit represents a rev_in_flight. pub fn increment_revs_in_flight(&mut self) { self.revs_in_flight += 1; diff --git a/rust/core-lib/src/event_context.rs b/rust/core-lib/src/event_context.rs index c632a75b0..c13331148 100644 --- a/rust/core-lib/src/event_context.rs +++ b/rust/core-lib/src/event_context.rs @@ -427,6 +427,12 @@ impl<'a> EventContext<'a> { self.render(); } + pub(crate) fn reload_tail(&mut self, text: Rope) { + self.with_editor(|ed, _, _, _| ed.tail_append(text)); + self.after_edit("core"); + self.render(); + } + pub(crate) fn plugin_info(&mut self) -> PluginBufferInfo { let ed = self.editor.borrow(); let nb_lines = ed.get_buffer().measure::() + 1; diff --git a/rust/core-lib/src/file.rs b/rust/core-lib/src/file.rs index 6d61ae004..d9dd3b87c 100644 --- a/rust/core-lib/src/file.rs +++ b/rust/core-lib/src/file.rs @@ -128,29 +128,22 @@ impl FileManager { let _ = File::create(path).map_err(|e| FileError::Io(e, path.to_owned()))?; } - //sj_todo following details need to come from RPC - let is_tail_mode_on = true; - let is_at_bottom_of_file = true; - let current_position = self.get_current_position_in_tail(&id); + if cfg!(feature = "notify") { - if is_tail_mode_on && is_at_bottom_of_file { + let current_position = self.get_current_position_in_tail(&id); + info!("current_position {:?}", current_position); let (rope, info) = try_tailing_file(path, current_position)?; self.open_files.insert(path.to_owned(), id); if self.file_info.insert(id, info).is_none() { - #[cfg(feature = "notify")] - self.watcher.watch(path, false, OPEN_FILE_EVENT_TOKEN); + self.watcher.watch(path, false, OPEN_FILE_EVENT_TOKEN); } Ok(rope) } else { let (rope, info) = try_load_file(path)?; - self.open_files.insert(path.to_owned(), id); - if self.file_info.insert(id, info).is_none() { - #[cfg(feature = "notify")] - self.watcher.watch(path, false, OPEN_FILE_EVENT_TOKEN); - } + self.file_info.insert(id, info); Ok(rope) } } @@ -216,25 +209,38 @@ impl FileManager { self.file_info.get_mut(&id).unwrap().mod_time = get_mod_time(path); #[cfg(feature = "notify")] self.watcher.watch(&path,false,OPEN_FILE_EVENT_TOKEN); + + #[cfg(feature = "notify")] + self.update_current_position_in_tail(path, &id); } Ok(()) } + + pub fn update_current_position_in_tail(&mut self, path: &Path, id: &BufferId) -> Result<(), FileError> { + + let existing_file_info = self.file_info.get_mut(&id).unwrap(); + + let mut f = File::open(path).map_err(|e| FileError::Io(e, path.to_owned()))?; + let end_position = f.seek(SeekFrom::End(0)).map_err(|e| FileError::Io(e, path.to_owned()))?; + + existing_file_info.tail_details.current_position_in_tail = end_position; + info!("Saving with end_position {:?}", end_position); + Ok(()) + } } -/// When tailing a file instead of reading file from beginning, we need to get changes from the end. +/// When tailing a file, instead of reading file from beginning, we need to get changes from the end. /// This method does that. -fn try_tailing_file

(path: P, current_postion: u64) -> Result<(Rope, FileInfo), FileError> +fn try_tailing_file

(path: P, current_position: u64) -> Result<(Rope, FileInfo), FileError> where P: AsRef { let mut f = File::open(path.as_ref()).map_err(|e| FileError::Io(e, path.as_ref().to_owned()))?; let end_position = f.seek(SeekFrom::End(0)).map_err(|e| FileError::Io(e, path.as_ref().to_owned()))?; - let diff = end_position - current_postion; - - //sj_todo do we need to check if end_position > current_position? - + let diff = end_position - current_position; + info!("end_position {:?} current_position {:?}", end_position, current_position); let mut buf = vec![0; diff as usize]; - let pos = f.seek(SeekFrom::Current(-(buf.len() as i64))).unwrap(); + f.seek(SeekFrom::Current(-(buf.len() as i64))).unwrap(); f.read_exact(&mut buf).unwrap(); let new_current_position = end_position; diff --git a/rust/core-lib/src/tabs.rs b/rust/core-lib/src/tabs.rs index 8a1cbb721..93fd654b3 100644 --- a/rust/core-lib/src/tabs.rs +++ b/rust/core-lib/src/tabs.rs @@ -660,6 +660,7 @@ impl CoreState { #[cfg(feature = "notify")] fn handle_open_file_fs_event(&mut self, event: DebouncedEvent) { use notify::DebouncedEvent::*; + info!("Event type is {:?}", event); let path = match event { NoticeWrite(ref path) | Create(ref path) | Write(ref path) | Chmod(ref path) => path, other => { @@ -689,7 +690,7 @@ impl CoreState { .find(|v| v.borrow().get_buffer_id() == buffer_id) .map(|v| v.borrow().get_view_id()) .unwrap(); - self.make_context(view_id).unwrap().reload(text); + self.make_context(view_id).unwrap().reload_tail(text); } } }