123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- package hide.tools;
- typedef FileWatchEvent = {path:String,fun:Void->Void,checkDel:Bool,element:js.html.Element,?ignoreCheck:String};
- private typedef Watch = {
- path : String,
- events : Array<FileWatchEvent>,
- w : js.node.fs.FSWatcher,
- wasChanged : Bool,
- changed : Bool,
- isDir : Bool,
- version : Int
- };
- class FileWatcher {
- var ide : hide.Ide;
- var watches : Map<String, Watch> = new Map();
- var timer : haxe.Timer;
- public function new() {
- ide = hide.Ide.inst;
- }
- public function pause() {
- for( w in watches )
- if( w.w != null ) {
- var sign = getSignature(w.path);
- if( sign != null ) {
- for( f in w.events )
- f.ignoreCheck = sign;
- }
- w.w.close();
- w.w = null;
- }
- }
- public function resume() {
- for( w in watches )
- if( w.w == null && w.events.length > 0 ) {
- initWatch(w);
- var sign = getSignature(w.path);
- for( f in w.events )
- if( f.ignoreCheck != sign || w.isDir ) {
- w.changed = true;
- w.version++;
- w.wasChanged = sign != null;
- break;
- }
- if( w.changed )
- haxe.Timer.delay(onEventChanged.bind(w),0);
- }
- }
- public function ignorePrevChange( f : FileWatchEvent ) {
- f.ignoreCheck = getSignature(f.path);
- }
- function getSignature( path : String ) : String {
- var sign = js.node.Crypto.createHash(js.node.Crypto.CryptoAlgorithm.MD5);
- try {
- sign.update(js.node.Fs.readFileSync(ide.getPath(path)));
- return sign.digest("base64");
- } catch( e : Dynamic ) {
- return null;
- }
- }
- public function dispose() {
- if( timer != null ) {
- timer.stop();
- timer = null;
- }
- for( w in watches )
- if( w.w != null )
- w.w.close();
- watches = new Map();
- }
- public function register( path : String, updateFun, ?checkDelete : Bool, ?element : Element ) : FileWatchEvent {
- path = ide.getPath(path);
- var w = getWatches(path);
- var f : FileWatchEvent = { path : path, fun : updateFun, checkDel : checkDelete, element : element == null ? null : element[0] };
- w.events.push(f);
- if( element != null && timer == null ) {
- timer = new haxe.Timer(1000);
- timer.run = cleanEvents;
- }
- return f;
- }
- public function registerRaw( path : String, updateFun, ?checkDelete : Bool, ?element : js.html.Element) : FileWatchEvent {
- path = ide.getPath(path);
- var w = getWatches(path);
- var f : FileWatchEvent = { path : path, fun : updateFun, checkDel : checkDelete, element: element};
- w.events.push(f);
- if( element != null && timer == null ) {
- timer = new haxe.Timer(1000);
- timer.run = cleanEvents;
- }
- return f;
- }
- public function unregister( path : String, updateFun : Void -> Void ) {
- path = ide.getPath(path);
- var w = getWatches(path);
- for( e in w.events )
- if( Reflect.compareMethods(e.fun, updateFun) ) {
- w.events.remove(e);
- break;
- }
- if( w.events.length == 0 ) {
- watches.remove(path);
- if( w.w != null ) w.w.close();
- }
- }
- public function unregisterElement( element : Element ) {
- for( path => w in watches ) {
- for( e in w.events.copy() )
- if( e.element == element[0] )
- w.events.remove(e);
- if( w.events.length == 0 ) {
- watches.remove(path);
- if( w.w != null ) w.w.close();
- }
- }
- }
- public function getVersion( path : String ) : Int {
- var w = watches.get(ide.getPath(path));
- if( w == null )
- return 0;
- return w.version;
- }
- function cleanEvents() {
- for( w in watches )
- for( e in w.events.copy() )
- isLive(w.events, e);
- }
- function isLive( events : Array<FileWatchEvent>, e : FileWatchEvent ) {
- if( e.element == null ) return true;
- var elt = e.element;
- while( elt != null ) {
- if( elt.nodeName == "BODY" ) return true;
- elt = elt.parentElement;
- }
- events.remove(e);
- return false;
- }
- function onEventChanged( w : Watch ) {
- if( !w.changed ) return;
- w.changed = false;
- var sign = null;
- for( e in w.events.copy() )
- if( isLive(w.events,e) && (w.wasChanged || e.checkDel) ) {
- if( e.ignoreCheck != null ) {
- if( sign == null ) sign = getSignature(w.path);
- if( sign == e.ignoreCheck ) continue;
- e.ignoreCheck = null;
- }
- e.fun();
- }
- w.wasChanged = false;
- }
- function initWatch( w : Watch ) {
- w.w = js.node.Fs.watch(w.path, function(k:String, file:String) {
- if( w.isDir && k == "change" ) return;
- if( k == "change" ) w.wasChanged = true;
- if( w.changed ) return;
- w.changed = true;
- w.version++;
- haxe.Timer.delay(onEventChanged.bind(w),100);
- });
- }
- function getWatches( path : String ) {
- var w = watches.get(path);
- if( w == null ) {
- var fullPath = ide.getPath(path);
- w = {
- path : fullPath,
- events : [],
- w : null,
- changed : false,
- isDir : try sys.FileSystem.isDirectory(fullPath) catch( e : Dynamic ) false,
- wasChanged : false,
- version : 0,
- };
- try initWatch(w) catch( e : Dynamic ) {
- // file does not exists, trigger a delayed event
- haxe.Timer.delay(function() {
- for( e in w.events.copy() )
- if( isLive(w.events,e) && e.checkDel )
- e.fun();
- }, 0);
- return w;
- }
- watches.set(path, w);
- }
- return w;
- }
- }
|