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     string inForcedConfigDir;
12 }
13 
14 /**
15     The name of the folder inochi creator config gets thrown in to.
16 */
17 enum APP_FOLDER_NAME = "inochi-creator";
18 
19 /**
20     Name of environment variable to force a configuration path
21 */
22 enum ENV_CONFIG_PATH = "INOCHI_CONFIG_PATH";
23 
24 /**
25     Returns the app configuration directory for the platform
26 */
27 string incGetAppConfigPath() {
28     if (cachedConfigDir) return cachedConfigDir;
29     if (inForcedConfigDir) return inForcedConfigDir;
30     string appDataDir;
31 
32     // Once this function has completed cache the result.
33     scope(success) {
34         
35         if (inForcedConfigDir) {
36             
37             // Also make sure the folder exists
38             if (!exists(inForcedConfigDir)) {
39                 mkdirRecurse(inForcedConfigDir);
40             }
41         } else {
42             cachedConfigDir = appDataDir;
43 
44             // Also make sure the folder exists
45             if (!exists(cachedConfigDir)) {
46                 mkdirRecurse(cachedConfigDir);
47             }
48         }
49     }
50 
51     // On Windows %AppData% is used.
52     // Example: C:/Users/USERNAME/AppData/Roaming/.inochi-creatorS
53     version(Windows) {
54         appDataDir = environment.get("AppData");
55     }
56 
57     // On Linux the app data dir is in $XDG_CONFIG_DIR, $HOME/.config or $HOME
58     // Example: /home/USERNAME/.inochi-creator
59     else version(linux) {
60         appDataDir = environment.get("XDG_CONFIG_HOME");
61         if (!appDataDir) appDataDir = buildPath(environment.get("HOME"), ".config");
62     }
63 
64     // On macOS things are thrown in to $HOME/Library/Application Support
65     // Example: /home/USERNAME/Library/Application Support/.inochi-creator
66     else version(OSX) {
67         appDataDir = environment.get("HOME");
68         if (appDataDir) appDataDir = buildPath(appDataDir, "Library", "Application Support");
69     }
70 
71     // On other POSIX platforms just assume $HOME exists.
72     // Example: /home/USERNAME/.inochi-creator
73     else version(posix) {
74         appDataDir = environment.get("HOME");
75     }
76 
77     // Allow packagers, etc. to specify a forced config directory.
78     inForcedConfigDir = environment.get(ENV_CONFIG_PATH);
79     if (inForcedConfigDir) return inForcedConfigDir;
80     
81 
82     if (!appDataDir) appDataDir = getcwd();
83 
84     version(linux) {
85 
86         // On linux we're using standard XDG dirs, prior we
87         // used .inochi-creator there, but that's not correct
88         // This code will ensure we still use old config if it's there.
89         // Otherwise we create config for the *correct* path
90         string fdir = buildPath(appDataDir, "."~APP_FOLDER_NAME);
91         if (!exists(fdir)) fdir = buildPath(appDataDir, APP_FOLDER_NAME);
92         appDataDir = fdir;
93         return appDataDir;
94     } else {
95 
96         // On other platforms we go for .(app name)
97         appDataDir = buildPath(appDataDir, "."~APP_FOLDER_NAME);
98         return appDataDir;
99     }
100 }
101 
102 /**
103     Gets the directory for an imgui config file.
104 */
105 string incGetAppImguiConfigFile() {
106     if (cachedImguiFileDir) return cachedImguiFileDir;
107     cachedImguiFileDir = buildPath(incGetAppConfigPath(), "imgui.ini");
108     return cachedImguiFileDir;
109 }
110 
111 /**
112     Gets directory for custom fonts
113 */
114 string incGetAppFontsPath() {
115     if (cachedFontDir) return cachedFontDir;
116     cachedFontDir = buildPath(incGetAppConfigPath(), "fonts");
117     if (!exists(cachedFontDir)) {
118         
119         // Create our font directory
120         mkdirRecurse(cachedFontDir);
121 
122         // Create our font dir and install our fonts
123         import std.file : write;
124 
125         write(buildPath(cachedFontDir, "OpenDyslexic.otf"), import("OpenDyslexic.otf"));
126         // TODO: Write a license file for OpenDyslexic?
127     }
128     return cachedFontDir;
129 }
130 
131 /**
132     Gets directory for custom fonts
133 */
134 string incGetAppLocalePath() {
135     if (cachedLocaleDir) return cachedLocaleDir;
136     cachedLocaleDir = buildPath(incGetAppConfigPath(), "i18n");
137     if (!exists(cachedLocaleDir)) {
138         
139         // Create our font directory
140         mkdirRecurse(cachedLocaleDir);
141     }
142     return cachedLocaleDir;
143 }