FileWatcher.hx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package hide.tools;
  2. private typedef FileEvent = {path:String,fun:Void->Void,checkDel:Bool,element:js.html.Element};
  3. class FileWatcher {
  4. var ide : hide.Ide;
  5. var watches : Map<String,{ events : Array<FileEvent>, w : js.node.fs.FSWatcher, ignoreNext : Bool, wasChanged : Bool, changed : Bool, isDir : Bool }> = new Map();
  6. var timer : haxe.Timer;
  7. public function new() {
  8. ide = hide.Ide.inst;
  9. }
  10. public function ignoreNextChange( path : String ) {
  11. var w = getWatches(path);
  12. w.ignoreNext = true;
  13. }
  14. public function dispose() {
  15. if( timer != null ) {
  16. timer.stop();
  17. timer = null;
  18. }
  19. for( w in watches )
  20. if( w.w != null )
  21. w.w.close();
  22. watches = new Map();
  23. }
  24. public function register( path : String, updateFun, ?checkDelete : Bool, ?element : Element ) {
  25. var w = getWatches(path);
  26. w.events.push({ path : path, fun : updateFun, checkDel : checkDelete, element : element == null ? null : element[0] });
  27. if( element != null && timer == null ) {
  28. timer = new haxe.Timer(1000);
  29. timer.run = cleanEvents;
  30. }
  31. }
  32. public function unregister( path : String, updateFun : Void -> Void ) {
  33. var w = getWatches(path);
  34. for( e in w.events )
  35. if( Reflect.compareMethods(e.fun, updateFun) ) {
  36. w.events.remove(e);
  37. break;
  38. }
  39. if( w.events.length == 0 ) {
  40. watches.remove(path);
  41. if( w.w != null ) w.w.close();
  42. }
  43. }
  44. function cleanEvents() {
  45. for( w in watches )
  46. for( e in w.events.copy() )
  47. isLive(w.events, e);
  48. }
  49. function isLive( events : Array<FileEvent>, e : FileEvent ) {
  50. if( e.element == null ) return true;
  51. var elt = e.element;
  52. while( elt != null ) {
  53. if( elt.nodeName == "BODY" ) return true;
  54. elt = elt.parentElement;
  55. }
  56. events.remove(e);
  57. return false;
  58. }
  59. function getWatches( path : String ) {
  60. var w = watches.get(path);
  61. if( w == null ) {
  62. var fullPath = ide.getPath(path);
  63. w = {
  64. events : [],
  65. w : null,
  66. changed : false,
  67. isDir : try sys.FileSystem.isDirectory(fullPath) catch( e : Dynamic ) false,
  68. ignoreNext : false,
  69. wasChanged : false,
  70. };
  71. w.w = try js.node.Fs.watch(fullPath, function(k:String, file:String) {
  72. if( w.isDir && k == "change" ) return;
  73. if( k == "change" ) w.wasChanged = true;
  74. if( w.changed ) return;
  75. w.changed = true;
  76. haxe.Timer.delay(function() {
  77. if( !w.changed ) return;
  78. w.changed = false;
  79. if( w.ignoreNext ) {
  80. w.ignoreNext = false;
  81. return;
  82. }
  83. for( e in w.events.copy() )
  84. if( isLive(w.events,e) && (w.wasChanged || e.checkDel) )
  85. e.fun();
  86. w.wasChanged = false;
  87. }, 100);
  88. }) catch( e : Dynamic ) {
  89. // file does not exists, trigger a delayed event
  90. haxe.Timer.delay(function() {
  91. for( e in w.events.copy() )
  92. if( isLive(w.events,e) && e.checkDel )
  93. e.fun();
  94. }, 0);
  95. return w;
  96. }
  97. watches.set(path, w);
  98. }
  99. return w;
  100. }
  101. }