rust - Passing additional data to a notify-rs watcher callback - Stack Overflow

I am trying to build a cli tool to transpile a file into another in Rust.I'd like for this tool t

I am trying to build a cli tool to transpile a file into another in Rust.

I'd like for this tool to wait for a change in the input file to automatically trasnspile it again to the output file.

Ideally I would write something like this

loop {
    if hasChanged(input_file) {
        transpile(input_file, output_file, settings);
    } 
}

Where the hasChanged function is blocking to avoid a busy loop

But the only library that I found that watches if a file has changed is notify, that uses a callback for dealing with file events.

(Taken from the library page)

fn event_fn(res: Result<notify::Event>) {
    match res {
        Ok(event) => println!("event: {:?}", event),
        Err(e) => println!("watch error: {:?}", e),
    }
}

mut watcher1 = notify::recommended_watcher(event_fn)?;

The problem arises from the fact that inside the callback I cannot access the settings that i have parsed from the cli arguments, nor the input_file (a simple String) or the output_file (a Box<dyn Write> use to abstract an actual file or stdout).

Also, since all I'm doing is waiting for the file to change, after the callback setup my main function just ends, and I don't want the program to just terminate there.

Is the only solution to do all the work (parsing arguments and opening files) inside the callback?

Is there a way to pass the arguments (especially the Box<dyn Write>) to the callback in any other way?

Or there is another library that fits my use case better?

This is my first project in rust so I'm not familiar with its threading rules and lifetimes. Thanks.

I am trying to build a cli tool to transpile a file into another in Rust.

I'd like for this tool to wait for a change in the input file to automatically trasnspile it again to the output file.

Ideally I would write something like this

loop {
    if hasChanged(input_file) {
        transpile(input_file, output_file, settings);
    } 
}

Where the hasChanged function is blocking to avoid a busy loop

But the only library that I found that watches if a file has changed is notify, that uses a callback for dealing with file events.

(Taken from the library page)

fn event_fn(res: Result<notify::Event>) {
    match res {
        Ok(event) => println!("event: {:?}", event),
        Err(e) => println!("watch error: {:?}", e),
    }
}

mut watcher1 = notify::recommended_watcher(event_fn)?;

The problem arises from the fact that inside the callback I cannot access the settings that i have parsed from the cli arguments, nor the input_file (a simple String) or the output_file (a Box<dyn Write> use to abstract an actual file or stdout).

Also, since all I'm doing is waiting for the file to change, after the callback setup my main function just ends, and I don't want the program to just terminate there.

Is the only solution to do all the work (parsing arguments and opening files) inside the callback?

Is there a way to pass the arguments (especially the Box<dyn Write>) to the callback in any other way?

Or there is another library that fits my use case better?

This is my first project in rust so I'm not familiar with its threading rules and lifetimes. Thanks.

Share Improve this question asked Jan 31 at 9:26 LeonardLeonard 3863 silver badges12 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

The answer is on the docs page of notify that you linked:

From the docs:

use notify::{recommended_watcher, Event, RecursiveMode, Result, Watcher};
use std::sync::mpsc;

fn main() -> Result<()> {
    let (tx, rx) = mpsc::channel::<Result<Event>>();

    // Use recommended_watcher() to automatically select the best implementation
    // for your platform. The `EventHandler` passed to this constructor can be a
    // closure, a `std::sync::mpsc::Sender`, a `crossbeam_channel::Sender`, or
    // another type the trait is implemented for.
    let mut watcher = notify::recommended_watcher(tx)?;

    // Add a path to be watched. All files and directories at that path and
    // below will be monitored for changes.
    watcher.watch(Path::new("."), RecursiveMode::Recursive)?;
    // Block forever, printing out events as they come in
    for res in rx {
        match res {
            Ok(event) => println!("event: {:?}", event),
            Err(e) => println!("watch error: {:?}", e),
        }
    }

    Ok(())
}

This example uses an multi-producer-single-consumer channel to feed events from the callback into your main loop, while avoiding a busy loop.

From within the match res statement, you should have access to any variables you created earlier in your main function, which should include your config and input/output files.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745272116a4619810.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信