1 module creator.core.path;
2 import std.path;
3 import std.process;
4 import std.file : getcwd, mkdirRecurse, exists;
5 
6 private {
7     string cachedConfigDir;
8     string cachedImguiFileDir;
9     string cachedFontDir;
10     string cachedLocaleDir;
11 }
12 
13 /**
14     The name of the folder inochi creator config gets thrown in to.
15 */
16 enum APP_FOLDER_NAME = ".inochi-creator";
17 
18 /**
19     Name of environment variable to force a configuration path
20 */
21 enum ENV_CONFIG_PATH = "INOCHI_CONFIG_PATH";
22 
23 /**
24     Returns the app configuration directory for the platform
25 */
26 string incGetAppConfigPath() {
27     if (cachedConfigDir) return cachedConfigDir;
28     string appDataDir;
29 
30     // Once this function has completed cache the result.
31     scope(success) {
32         cachedConfigDir = appDataDir;
33         
34         // Also make sure the folder exists
35         if (!exists(cachedConfigDir)) {
36             mkdirRecurse(cachedConfigDir);
37         }
38     }
39 
40     // On Windows %AppData% is used.
41     // Example: C:/Users/USERNAME/AppData/Roaming/.inochi-creatorS
42     version(Windows) {
43         appDataDir = environment.get("AppData");
44     }
45 
46     // On Linux the app data dir is in $XDG_CONFIG_DIR, $HOME/.config or $HOME
47     // Example: /home/USERNAME/.inochi-creator
48     else version(linux) {
49         appDataDir = environment.get("XDG_CONFIG_HOME");
50         if (!appDataDir) appDataDir = buildPath(environment.get("HOME"), ".config");
51     }
52 
53     // On macOS things are thrown in to $HOME/Library/Application Support
54     // Example: /home/USERNAME/Library/Application Support/.inochi-creator
55     else version(OSX) {
56         appDataDir = environment.get("HOME");
57         if (appDataDir) appDataDir = buildPath(appDataDir, "Library", "Application Support");
58     }
59 
60     // On other POSIX platforms just assume $HOME exists.
61     // Example: /home/USERNAME/.inochi-creator
62     else version(posix) {
63         appDataDir = environment.get("HOME");
64     }
65 
66     // Allow packagers, etc. to specify a forced config directory.
67     string inForcedConfigDir = environment.get(ENV_CONFIG_PATH);
68     if (inForcedConfigDir) {
69         return inForcedConfigDir;
70     }
71 
72     if (!appDataDir) appDataDir = getcwd();
73     appDataDir = buildPath(appDataDir, APP_FOLDER_NAME);
74     return appDataDir;
75 }
76 
77 /**
78     Gets the directory for an imgui config file.
79 */
80 string incGetAppImguiConfigFile() {
81     if (cachedImguiFileDir) return cachedImguiFileDir;
82     cachedImguiFileDir = buildPath(incGetAppConfigPath(), "imgui.ini");
83     return cachedImguiFileDir;
84 }
85 
86 /**
87     Gets directory for custom fonts
88 */
89 string incGetAppFontsPath() {
90     if (cachedFontDir) return cachedFontDir;
91     cachedFontDir = buildPath(incGetAppConfigPath(), "fonts");
92     if (!exists(cachedFontDir)) {
93         
94         // Create our font directory
95         mkdirRecurse(cachedFontDir);
96 
97         // Create our font dir and install our fonts
98         import std.file : write;
99 
100         write(buildPath(cachedFontDir, "OpenDyslexic.otf"), import("OpenDyslexic.otf"));
101         // TODO: Write a license file for OpenDyslexic?
102     }
103     return cachedFontDir;
104 }
105 
106 /**
107     Gets directory for custom fonts
108 */
109 string incGetAppLocalePath() {
110     if (cachedLocaleDir) return cachedLocaleDir;
111     cachedLocaleDir = buildPath(incGetAppConfigPath(), "i18n");
112     if (!exists(cachedLocaleDir)) {
113         
114         // Create our font directory
115         mkdirRecurse(cachedLocaleDir);
116     }
117     return cachedLocaleDir;
118 }