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 }