1 /+
2     This file is part of Reloaded Vibes.
3     Copyright (c) 2019  0xEAB
4 
5     Distributed under the Boost Software License, Version 1.0.
6        (See accompanying file LICENSE_1_0.txt or copy at
7              https://www.boost.org/LICENSE_1_0.txt)
8  +/
9 module reloadedvibes.watcher;
10 
11 import std.algorithm : remove;
12 import std.range : isInputRange;
13 import fswatch;
14 
15 final class Watcher
16 {
17     private
18     {
19         FileWatch*[] _fws = [];
20         WatcherClient[] _cs = [];
21     }
22 
23     public this(Range)(Range directories) if (isInputRange!Range)
24     {
25         foreach (dir; directories)
26         {
27             this._fws ~= new FileWatch(dir, true);
28         }
29     }
30 
31     private
32     {
33         void registerClient(WatcherClient c) @safe pure nothrow
34         {
35             this._cs ~= c;
36         }
37 
38         void unregisterClient(WatcherClient c)
39         {
40             this._cs = this._cs.remove!(x => x == c);
41         }
42 
43         void query()
44         {
45             bool notify = false;
46 
47             foreach (fw; this._fws)
48             {
49                 if (fw.getEvents().length > 0)
50                 {
51                     notify = true;
52                 }
53             }
54 
55             if (notify)
56             {
57                 foreach (c; this._cs)
58                 {
59                     c.notify();
60                 }
61             }
62         }
63     }
64 }
65 
66 class WatcherClient
67 {
68     private
69     {
70         Watcher _w;
71         bool _notified = false;
72     }
73 
74     public
75     {
76         Watcher watcher()
77         {
78             return this._w;
79         }
80     }
81 
82     public final this(Watcher w) @safe pure nothrow
83     {
84         this._w = w;
85         this._w.registerClient(this);
86     }
87 
88     public final
89     {
90         bool query()
91         {
92             if (this._notified)
93             {
94                 this._notified = false;
95                 return true;
96             }
97 
98             this._w.query();
99 
100             if (this._notified)
101             {
102                 this._notified = false;
103                 return true;
104             }
105 
106             return false;
107         }
108 
109         void unregister()
110         {
111             this._w.unregisterClient(this);
112         }
113     }
114 
115     protected
116     {
117         void notify()
118         {
119             this.setNotified();
120         }
121 
122         void setNotified() @safe pure nothrow @nogc
123         {
124             this._notified = true;
125         }
126     }
127 }