1+ #![ allow( unused) ]
12use actix_web:: web;
3+ use notify:: event:: RemoveKind ;
4+ use notify_debouncer_full:: DebouncedEvent ;
5+ use notify_debouncer_full:: { DebounceEventResult , new_debouncer, notify:: * } ;
26use pulldown_cmark:: Options ;
37use std:: fs;
48use std:: path:: Path ;
9+ use tokio:: time:: Duration ;
510mod args;
611use actix_web:: App ;
712use actix_web:: HttpServer ;
@@ -13,7 +18,7 @@ use args::MdwatchArgs;
1318use askama:: Template ;
1419use clap:: Parser ;
1520
16- use notify:: { Event , RecursiveMode , Result , Watcher } ;
21+ use notify:: { Event , RecursiveMode , Result , Watcher , event :: ModifyKind } ;
1722use rust_embed:: Embed ;
1823use tokio:: sync:: mpsc;
1924
@@ -63,41 +68,47 @@ async fn ws_handler(
6368) -> actix_web:: Result < impl Responder > {
6469 let ( response, mut session, mut _msg_stream) = actix_ws:: handle ( & req, body) ?;
6570 let file_path = file. as_str ( ) . to_string ( ) ;
66- let ( watch_tx, mut notify_rx) = mpsc:: unbounded_channel :: < Result < Event > > ( ) ;
67-
68- let mut watcher = notify:: recommended_watcher ( move |res| {
69- let _ = watch_tx. send ( res) ;
70- } )
71+ let ( watch_tx, mut notify_rx) = mpsc:: unbounded_channel :: < DebouncedEvent > ( ) ;
72+
73+ let mut debouncer = new_debouncer (
74+ Duration :: from_secs ( 2 ) ,
75+ None ,
76+ move |result : DebounceEventResult | match result {
77+ Ok ( events) => events. into_iter ( ) . for_each ( |event| {
78+ let _ = watch_tx. send ( event) ;
79+ } ) ,
80+ Err ( errors) => errors
81+ . iter ( )
82+ . for_each ( |error| eprintln ! ( "watch error: {error:?}" ) ) ,
83+ } ,
84+ )
7185 . map_err ( actix_web:: error:: ErrorInternalServerError ) ?;
7286
73- watcher
74- . watch ( Path :: new ( & file_path) , RecursiveMode :: NonRecursive )
87+ debouncer
88+ . watch ( & file_path, RecursiveMode :: NonRecursive )
7589 . map_err ( actix_web:: error:: ErrorInternalServerError ) ?;
7690
7791 actix_web:: rt:: spawn ( async move {
7892 // Keep the watcher alive in this async task to keep the msg_stream alive
79- let _watcher = watcher;
80- while let Some ( res) = notify_rx. recv ( ) . await {
81- match res {
82- Ok ( event) => {
83- if event. kind . is_remove ( ) {
84- eprintln ! ( "File removed: {}" , file_path) ;
85- break ;
86- }
87- if event. kind . is_modify ( ) {
88- let latest_markdown = match get_markdown ( & file_path) {
89- Ok ( md) => md,
90- Err ( e) => {
91- eprintln ! ( "Error reading markdown file: {e}" ) ;
92- continue ;
93- }
94- } ;
95- if session. text ( latest_markdown) . await . is_err ( ) {
96- break ;
97- }
93+ let _watcher = debouncer;
94+
95+ while let Some ( event) = notify_rx. recv ( ) . await {
96+ if matches ! ( event. kind, EventKind :: Remove ( RemoveKind :: File ) ) {
97+ eprintln ! ( "File removed: {}" , file_path) ;
98+ break ;
99+ }
100+ if matches ! ( event. kind, EventKind :: Modify ( ModifyKind :: Data ( _) ) ) {
101+ println ! ( "File modified" ) ;
102+ let latest_markdown = match get_markdown ( & file_path) {
103+ Ok ( md) => md,
104+ Err ( e) => {
105+ eprintln ! ( "Error reading markdown file: {e}" ) ;
106+ continue ;
98107 }
108+ } ;
109+ if session. text ( latest_markdown) . await . is_err ( ) {
110+ break ;
99111 }
100- Err ( e) => eprintln ! ( "watch error: {e:?}" ) ,
101112 }
102113 }
103114
0 commit comments