Skip to content

Commit

Permalink
https://github.com/xi-editor/xi-editor/issues/922
Browse files Browse the repository at this point in the history
Tailing a file with notify feature.
  • Loading branch information
sjoshid committed Nov 25, 2018
1 parent 1eb59fd commit 6efe270
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 20 deletions.
8 changes: 8 additions & 0 deletions rust/core-lib/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions rust/core-lib/src/event_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<LinesMetric>() + 1;
Expand Down
44 changes: 25 additions & 19 deletions rust/core-lib/src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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<P>(path: P, current_postion: u64) -> Result<(Rope, FileInfo), FileError>
fn try_tailing_file<P>(path: P, current_position: u64) -> Result<(Rope, FileInfo), FileError>
where P: AsRef<Path>
{
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;
Expand Down
3 changes: 2 additions & 1 deletion rust/core-lib/src/tabs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand Down Expand Up @@ -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);
}
}
}
Expand Down

0 comments on commit 6efe270

Please sign in to comment.