1 module dinu.loader.files; 2 3 4 import dinu; 5 6 7 __gshared: 8 9 10 auto normalizePath(string path){ 11 return path 12 .unixClean 13 .expandTilde 14 .absolutePath; 15 } 16 17 18 class FilesLoader: ChoiceLoader { 19 20 string path; 21 int depth; 22 string[] loadedDirs; 23 24 this(string path, int depth){ 25 if(depth == -1) 26 depth = 9999; 27 this.path = path; 28 this.depth = depth; 29 super(); 30 } 31 32 override void run(){ 33 loadDir(path, depth); 34 } 35 36 private void loadDir(string path, size_t depth=0){ 37 auto dirs = loadFiles(path); 38 if(depth > 0){ 39 foreach(dir; dirs){ 40 loadDir(dir, depth-1); 41 } 42 } 43 } 44 45 private string[] loadFiles(string dir){ 46 dir = dir 47 .normalizePath 48 .chomp("/") ~ "/"; 49 synchronized(this){ 50 if(loadedDirs.canFind(dir)) 51 return []; 52 loadedDirs ~= dir; 53 } 54 string[] dirs; 55 foreach(i, entry; dir.dirContent){ 56 if(!active) 57 return []; 58 string path = entry.normalizePath; 59 if(path.isSymlink) 60 continue; 61 try{ 62 if(path.isDir){ 63 dirs ~= path; 64 add(new immutable CommandDir(path)); 65 }else{ 66 auto attr = getAttributes(path); 67 if(attr & (1 + (1<<3))) 68 add(new immutable CommandExec(path)); 69 add(new immutable CommandFile(path)); 70 } 71 Thread.sleep(1.msecs); 72 }catch(Throwable t){ 73 writeln(t); 74 } 75 } 76 return dirs; 77 } 78 79 void update(dstring filterText){ 80 auto path = filterText.to!string.normalizePath; 81 if(path.chompAll("/").length != path.length-1) 82 return; 83 if(path.exists && path.isDir){ 84 task({ 85 loadDir(path); 86 }).executeInNewThread; 87 } 88 } 89 90 } 91 92 auto chompAll(string text, string delim){ 93 while(text.endsWith(delim)) 94 text = text.chomp(delim); 95 return text; 96 }