1 module sbylib.engine.util;
2 
3 import std;
4 import sbylib.engine;
5 
6 string[] importPath() {
7     return Dub.getImportPath() ~ findPhobosPath() ~ ".";
8 }
9 
10 auto dependentLibraries() {
11     const data = Dub.describe();
12 
13     string[] dependentPackageList(string root) {
14         void func(string root, ref string[] current) {
15             foreach (dependency; data.findPackage(root).dependencies
16                     .filter!(n => current.canFind(n) is false)) {
17                 current ~= dependency;
18                 func(dependency, current);
19             }
20         }
21         string[] result;
22         func(root, result);
23         return result;
24     }
25 
26     struct Result {
27         string[] librarySearchPathList;
28         string[] libraryPathList;
29     }
30 
31     Result result;
32 
33     foreach (p; dependentPackageList(data.rootPackageName)
34         .map!(n => data.findPackage(n))
35         .filter!(p => p.targetFileName.endsWith(".a"))) {
36 
37         result.librarySearchPathList ~= buildPath(p.path, p.targetPath);
38         result.libraryPathList ~= p.targetFileName;
39     }
40 
41     result.librarySearchPathList = result.librarySearchPathList.sort.uniq.array;
42     result.libraryPathList = result.libraryPathList.sort.uniq.array;
43     return result;
44 }
45 
46 string fontPath(string filename) {
47     import std.path : buildPath;
48     return fontDir.buildPath(filename);
49 }
50 
51 string fontDir() {
52     import std.path : buildPath;
53     return rootDir.buildPath("font");
54 }
55 
56 string resourcePath(string filename) {
57     import std.path : buildPath;
58     return resourceDir.buildPath(filename);
59 }
60 
61 string resourceDir() {
62     import std.path : buildPath;
63     return rootDir.buildPath("resource");
64 }
65 
66 string rootDir() {
67     import std.algorithm : filter;
68     import std.conv : to;
69     import std.file : dirEntries, SpanMode;
70     import std.path : dirName, buildNormalizedPath;
71     import std..string : endsWith;
72     
73     string file = __FILE_FULL_PATH__.dirName;
74 
75     while (file.dirEntries(SpanMode.shallow).filter!(path => path.to!string.endsWith(".dub")).empty) {
76         assert(file.dirName != file);
77         file = file.dirName;
78     }
79 
80     return file.buildNormalizedPath();
81 }
82 
83 string cacheDir() {
84     auto dir = ".cache";
85     if (dir.exists == false)
86         mkdirRecurse(dir);
87 
88     return dir;
89 }
90 
91 private string[] findPhobosPath() {
92     import std.file : write;
93 
94     const cacheFile = cacheDir.buildPath("phobospath");
95     if (cacheFile.exists)
96         return readText(cacheFile).chomp.split("\n");
97 
98     auto file = cacheDir.buildPath("tmp.d");
99     file.write(q{
100 /+dub.sdl:
101 dependency "dmd" version="~master"
102 +/
103 void main()
104 {
105     import dmd.frontend;
106     import std.stdio;
107     findImportPaths().writeln;
108 }
109 });
110     
111     auto result = execute(["dub", file]).output
112     .split("\n")
113     .filter!(line => line.startsWith("["))
114     .map!(line => line.to!(string[]))
115     .join;
116 
117     foreach (r; result) enforce(r.exists, format!"'%s' does not exist."(r));
118     cacheFile.write(result.join("\n"));
119 
120     return result;
121 }
122 
123 string color(int frontcolorCode, int backcolormode)(string str) {
124     return format!"\x1b[%dm\x1b[%dm%s\x1b[39m\x1b[49m"(frontcolorCode, backcolormode, str);
125 }
126 
127 alias red     = color!(37,41); 
128 alias green   = color!(37,42); 
129 alias yellow  = color!(30,43); 
130 alias blue    = color!(37,44); 
131 alias magenda = color!(30,45); 
132 alias cyan    = color!(30,46); 
133 alias gray    = color!(30,47);