Skip to content

Commit

Permalink
fix: watcher doesn't work on vs-code/sublime/nano (#69)
Browse files Browse the repository at this point in the history
  • Loading branch information
cristianoliveira committed Jun 12, 2023
1 parent ff60feb commit 9c7e872
Show file tree
Hide file tree
Showing 11 changed files with 386 additions and 107 deletions.
287 changes: 266 additions & 21 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "funzzy"
version = "1.0.0"
version = "1.0.1"
authors = ["Cristian Oliveira <me@cristianoliveira.com>"]
description = "Yet another fancy watcher inspired by entr."
license = "MIT"
Expand All @@ -13,4 +13,5 @@ serde_derive = "1.0" # if you're using `derive(Deserialize)`
notify = "4.0.0"
yaml-rust = "0.4.1"
glob="0.2.11"
notify-debouncer-mini = "0.3.0"
#clippy = "*"
10 changes: 10 additions & 0 deletions examples/long-task.yaml
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
- name: run long task 2
run: "bash examples/longtask.sh long 2"
change: ["src/**", "tests/integration/workdir/**"]
# Ignoring VIM backup files
ignore: ["**/*~", "**/*.sw?"]

- name: run long task 3
run: "bash examples/longtask.sh short 3"
change: ["src/**", "tests/integration/workdir/**"]
# Ignoring VIM backup files
ignore: ["**/*~", "**/*.sw?"]

- name: run long task 4
run: "bash examples/longtask.sh short 4"
change: ["src/**", "tests/integration/workdir/**"]
# Ignoring VIM backup files
ignore: ["**/*~", "**/*.sw?"]
run_on_init: true

- name: run long task 5
run: "bash examples/longtask.sh short 5"
change: ["src/**", "tests/integration/workdir/**"]
# Ignoring VIM backup files
ignore: ["**/*~", "**/*.sw?"]
run_on_init: true

- name: run long task 6
run: ["bash examples/longtask.sh list 3", "bash examples/longtask.sh list 4"]
change: ["src/**", "tests/integration/workdir/**"]
# Ignoring VIM backup files
ignore: ["**/*~", "**/*.sw?"]
run_on_init: true
2 changes: 1 addition & 1 deletion linux-install.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION="v1.0.0"
VERSION="v1.0.1"

cd /tmp

Expand Down
37 changes: 11 additions & 26 deletions src/cli/watch.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
extern crate notify;

use std::sync::mpsc::channel;

use self::notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
use std::time::Duration;

use cli::Command;
use cmd;
use rules;
use stdout;
use watcher;
use watches::Watches;

pub const DEFAULT_FILENAME: &str = ".watch.yaml";
Expand All @@ -35,14 +29,6 @@ impl Command for WatchCommand {
fn execute(&self) -> Result<(), String> {
stdout::verbose("Verbose mode enabled.", self.verbose);

let (tx, rx) = channel();
let mut watcher: RecommendedWatcher =
Watcher::new(tx, Duration::from_millis(200)).expect("Unable to create watcher");

if let Err(err) = watcher.watch(".", RecursiveMode::Recursive) {
return Err(format!("Unable to watch current directory {:?}", err));
}

if let Some(rules) = self.watches.run_on_init() {
stdout::info("Running on init commands.");

Expand All @@ -57,29 +43,28 @@ impl Command for WatchCommand {
stdout::present_results(results);
}

stdout::info("Watching...");
while let Ok(event) = rx.recv() {
stdout::verbose(&format!("Event {:?}", event), self.verbose);
if let DebouncedEvent::Create(path) = event {
let path_str = path.into_os_string().into_string().unwrap();
if let Some(rules) = self.watches.watch(&path_str) {
watcher::events(
|file_changed| {
if let Some(rules) = self.watches.watch(file_changed) {
stdout::verbose(
&format!("Triggered by change in: {}", path_str),
&format!("Triggered by change in: {}", file_changed),
self.verbose,
);

let results = rules::template(rules::commands(rules), path_str.as_str())
stdout::verbose(&format!("Rules: {:?}", rules), self.verbose);

let results = rules::template(rules::commands(rules), file_changed)
.iter()
.map(|task| {
stdout::info(&format!(" task {} \n", String::from(task)));
cmd::execute(task)
})
.collect::<Vec<Result<(), String>>>();

stdout::present_results(results);
}
}
}
},
self.verbose,
);
Ok(())
}
}
70 changes: 20 additions & 50 deletions src/cli/watch_non_block.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
extern crate notify;

use std::sync::mpsc::channel;
use std::sync::mpsc::TryRecvError;

use self::notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
use std::time::Duration;

use cli::Command;
use stdout;
use watcher;
use watches::Watches;
use workers;

Expand All @@ -34,14 +29,6 @@ impl Command for WatchNonBlockCommand {
fn execute(&self) -> Result<(), String> {
stdout::verbose("Verbose mode enabled.", self.verbose);

let (tx, rx) = channel();
let mut watcher: RecommendedWatcher =
Watcher::new(tx, Duration::from_millis(200)).expect("Unable to create watcher");

if let Err(err) = watcher.watch(".", RecursiveMode::Recursive) {
return Err(format!("Unable to watch current directory {:?}", err));
}

let worker = workers::Worker::new(self.verbose);

if let Some(rules) = self.watches.run_on_init() {
Expand All @@ -51,46 +38,29 @@ impl Command for WatchNonBlockCommand {
}
}

stdout::info("Watching...");
loop {
match rx.try_recv() {
Ok(event) => {
stdout::verbose(&format!("Event {:?}", event), self.verbose);
if let DebouncedEvent::Create(path) = event {
let path_str = path.into_os_string().into_string().unwrap();

stdout::verbose(&format!("Changed file: {}", path_str), self.verbose);

if let Some(rules) = self.watches.watch(&path_str) {
stdout::verbose(
&format!("Triggered by change in: {}", path_str),
self.verbose,
);

if let Err(err) = worker.cancel_running_tasks() {
stdout::error(&format!(
"failed to cancel current running tasks: {:?}",
err
));
}

if let Err(err) = worker.schedule(rules.clone(), path_str.as_str()) {
stdout::error(&format!("failed to initiate next run: {:?}", err));
}
}
watcher::events(
|file_changed| {
if let Some(rules) = self.watches.watch(file_changed) {
stdout::verbose(
&format!("Triggered by change in: {}", file_changed),
self.verbose,
);

if let Err(err) = worker.cancel_running_tasks() {
stdout::error(&format!(
"failed to cancel current running tasks: {:?}",
err
));
}
}

Err(err) => {
if err != TryRecvError::Empty {
stdout::error(&format!("failed to receive event: {:?}", err));
break;
if let Err(err) = worker.schedule(rules, file_changed) {
stdout::error(&format!("failed to initiate next run: {:?}", err));
}
}
}

std::thread::sleep(std::time::Duration::from_millis(200));
}
},
self.verbose,
);
stdout::info("Watching...");

Ok(())
}
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod cli;
pub mod cmd;
pub mod rules;
pub mod stdout;
pub mod watcher;
pub mod watches;
pub mod workers;
pub mod yaml;
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod cli;
mod cmd;
mod rules;
mod stdout;
mod watcher;
mod watches;
mod workers;
mod yaml;
Expand Down
50 changes: 50 additions & 0 deletions src/watcher.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
extern crate notify;
extern crate notify_debouncer_mini;
use self::notify_debouncer_mini::{new_debouncer, notify::RecursiveMode};

use std::path::Path;
use std::sync::mpsc::channel;
use std::sync::mpsc::TryRecvError;
use std::time::Duration;
use stdout;

pub fn events(handler: impl Fn(&str), verbose: bool) {
let (tx, rx) = channel();
let mut debouncer =
new_debouncer(Duration::from_millis(200), None, tx).expect("Unable to create watcher");
let watcher = debouncer.watcher();

if let Err(err) = watcher.watch(Path::new("."), RecursiveMode::Recursive) {
println!("Unable to watch current directory {:?}", err);
}

stdout::info("Watching...");
loop {
match rx.try_recv() {
Ok(debounced_evts) => {
stdout::verbose(&format!("Events {:?}", debounced_evts), verbose);
if let Ok(file_change_event) = debounced_evts {
file_change_event.iter().for_each(|event| {
if let Some(path_string) = event.path.to_str() {
handler(path_string);
} else {
stdout::error(&format!(
"failed to convert path {:?} to string",
event.path
));
}
});
}
}

Err(err) => {
if err != TryRecvError::Empty {
stdout::error(&format!("failed to receive event: {:?}", err));
break;
}
}
}

std::thread::sleep(std::time::Duration::from_millis(200));
}
}
8 changes: 7 additions & 1 deletion tests/integration/specs/ignoring-folders-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ echo "
change: '$WORKDIR/**'
ignore: [
'$WORKDIR/ignored/**',
'$WORKDIR/file-to-ignore.txt'
'$WORKDIR/output.txt',
'$WORKDIR/file-to-ignore.txt',
# Vim backup files
'$WORKDIR/file-to-ignore.txt~',
'$WORKDIR/.file-to-ignore.txt.swp',
'$WORKDIR/.file-to-ignore.txt.swx'
]
- name: run not ignored
Expand Down
24 changes: 17 additions & 7 deletions tests/integration/specs/watch-command-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,27 @@ echo "
- name: run simple command
run: echo 'test1'
change: \"$WORKDIR/**\"
" > $WORKDIR/.onwatch.yaml
touch $WORKDIR/test.txt
touch $WORKDIR/output.txt
- name: run different command
run: echo '__placeholder__' | sed s/placeholder/second_commmand/g
change: \"$WORKDIR/**\"
" > "$WORKDIR"/.onwatch.yaml

touch "$WORKDIR"/test.txt
touch "$WORKDIR"/output.txt
# $TEST_DIR/funzzy --config $WORKDIR/.onwatch.yaml &
$TEST_DIR/funzzy watch --config $WORKDIR/.onwatch.yaml >> $WORKDIR/output.txt &
"$TEST_DIR"/funzzy watch \
--config "$WORKDIR"/.onwatch.yaml >> "$WORKDIR"/output.txt &
FUNZZY_PID=$!

echo "test" >> $WORKDIR/test.txt
wait_for_file "$WORKDIR/output.txt"
sh -c "vi +%s/test/foo/g +wq $WORKDIR/test.txt -u NONE"
assert_file_contains "$WORKDIR/output.txt" "echo 'test1'"

echo "some content" > "$WORKDIR"/test.txt

touch "$WORKDIR"/test.txt
assert_file_occurrencies "$WORKDIR/output.txt" "__second_commmand__" 1

touch "$WORKDIR"/test.txt
assert_file_occurrencies "$WORKDIR/output.txt" "__second_commmand__" 2

cleanup

0 comments on commit 9c7e872

Please sign in to comment.