Optimize the file watcher

This commit is contained in:
mo8it
2024-09-18 01:43:48 +02:00
parent e56ae6d651
commit 89c40ba256
6 changed files with 91 additions and 108 deletions
+53 -38
View File
@@ -1,7 +1,10 @@
use notify_debouncer_mini::{DebounceEventResult, DebouncedEventKind};
use std::sync::mpsc::Sender;
use notify::{
event::{MetadataKind, ModifyKind},
Event, EventKind,
};
use std::sync::{atomic::Ordering::Relaxed, mpsc::Sender};
use super::WatchEvent;
use super::{WatchEvent, EXERCISE_RUNNING};
pub struct NotifyEventHandler {
pub sender: Sender<WatchEvent>,
@@ -9,44 +12,56 @@ pub struct NotifyEventHandler {
pub exercise_names: &'static [&'static [u8]],
}
impl notify_debouncer_mini::DebounceEventHandler for NotifyEventHandler {
fn handle_event(&mut self, input_event: DebounceEventResult) {
let output_event = match input_event {
Ok(input_event) => {
let Some(exercise_ind) = input_event
.iter()
.filter_map(|input_event| {
if input_event.kind != DebouncedEventKind::Any {
return None;
}
impl notify::EventHandler for NotifyEventHandler {
fn handle_event(&mut self, input_event: notify::Result<Event>) {
if EXERCISE_RUNNING.load(Relaxed) {
return;
}
let file_name = input_event.path.file_name()?.to_str()?.as_bytes();
if file_name.len() < 4 {
return None;
}
let (file_name_without_ext, ext) = file_name.split_at(file_name.len() - 3);
if ext != b".rs" {
return None;
}
self.exercise_names
.iter()
.position(|exercise_name| *exercise_name == file_name_without_ext)
})
.min()
else {
return;
};
WatchEvent::FileChange { exercise_ind }
let input_event = match input_event {
Ok(v) => v,
Err(e) => {
// An error occurs when the receiver is dropped.
// After dropping the receiver, the debouncer guard should also be dropped.
let _ = self.sender.send(WatchEvent::NotifyErr(e));
return;
}
Err(e) => WatchEvent::NotifyErr(e),
};
// An error occurs when the receiver is dropped.
// After dropping the receiver, the debouncer guard should also be dropped.
let _ = self.sender.send(output_event);
match input_event.kind {
EventKind::Any => (),
EventKind::Modify(modify_kind) => match modify_kind {
ModifyKind::Any | ModifyKind::Data(_) => (),
ModifyKind::Metadata(metadata_kind) => match metadata_kind {
MetadataKind::Any | MetadataKind::WriteTime => (),
MetadataKind::AccessTime
| MetadataKind::Permissions
| MetadataKind::Ownership
| MetadataKind::Extended
| MetadataKind::Other => return,
},
ModifyKind::Name(_) | ModifyKind::Other => return,
},
EventKind::Access(_)
| EventKind::Create(_)
| EventKind::Remove(_)
| EventKind::Other => return,
}
let _ = input_event
.paths
.into_iter()
.filter_map(|path| {
let file_name = path.file_name()?.to_str()?.as_bytes();
let [file_name_without_ext @ .., b'.', b'r', b's'] = file_name else {
return None;
};
self.exercise_names
.iter()
.position(|exercise_name| *exercise_name == file_name_without_ext)
})
.try_for_each(|exercise_ind| self.sender.send(WatchEvent::FileChange { exercise_ind }));
}
}
+1 -4
View File
@@ -18,10 +18,7 @@ use crate::{
term::progress_bar,
};
use super::{
terminal_event::{terminal_event_handler, InputPauseGuard},
WatchEvent,
};
use super::{terminal_event::terminal_event_handler, InputPauseGuard, WatchEvent};
#[derive(PartialEq, Eq)]
enum DoneStatus {
+3 -27
View File
@@ -1,31 +1,7 @@
use crossterm::event::{self, Event, KeyCode, KeyEventKind};
use std::sync::{
atomic::{AtomicBool, Ordering::Relaxed},
mpsc::Sender,
};
use std::sync::{atomic::Ordering::Relaxed, mpsc::Sender};
use super::WatchEvent;
static INPUT_PAUSED: AtomicBool = AtomicBool::new(false);
// Private unit type to force using the constructor function.
#[must_use = "When the guard is dropped, the input is unpaused"]
pub struct InputPauseGuard(());
impl InputPauseGuard {
#[inline]
pub fn scoped_pause() -> Self {
INPUT_PAUSED.store(true, Relaxed);
Self(())
}
}
impl Drop for InputPauseGuard {
#[inline]
fn drop(&mut self) {
INPUT_PAUSED.store(false, Relaxed);
}
}
use super::{WatchEvent, EXERCISE_RUNNING};
pub enum InputEvent {
Run,
@@ -44,7 +20,7 @@ pub fn terminal_event_handler(sender: Sender<WatchEvent>, manual_run: bool) {
KeyEventKind::Press => (),
}
if INPUT_PAUSED.load(Relaxed) {
if EXERCISE_RUNNING.load(Relaxed) {
continue;
}