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 version(OSX) {
95 
96         // On OSX we're using standard directories, prior we
97         // used .inochi-creator there, but that's not correct
98         // This code will ensure we still use old config if it's there.
99         // Otherwise we create config for the *correct* path
100         string fdir = buildPath(appDataDir, "."~APP_FOLDER_NAME);
101         if (!exists(fdir)) fdir = buildPath(appDataDir, APP_FOLDER_NAME);
102         appDataDir = fdir;
103         return appDataDir;
104     } else {
105 
106         // On other platforms we go for .(app name)
107         appDataDir = buildPath(appDataDir, "."~APP_FOLDER_NAME);
108         return appDataDir;
109     }
110 }
111 
112 /**
113     Gets the directory for an imgui config file.
114 */
115 string incGetAppImguiConfigFile() {
116     if (cachedImguiFileDir) return cachedImguiFileDir;
117     cachedImguiFileDir = buildPath(incGetAppConfigPath(), "imgui.ini");
118     return cachedImguiFileDir;
119 }
120 
121 /**
122     Gets directory for custom fonts
123 */
124 string incGetAppFontsPath() {
125     if (cachedFontDir) return cachedFontDir;
126     cachedFontDir = buildPath(incGetAppConfigPath(), "fonts");
127     if (!exists(cachedFontDir)) {
128         
129         // Create our font directory
130         mkdirRecurse(cachedFontDir);
131     }
132     return cachedFontDir;
133 }
134 
135 /**
136     Gets directory for custom locales
137 */
138 string incGetAppLocalePath() {
139     if (cachedLocaleDir) return cachedLocaleDir;
140 
141     cachedLocaleDir = buildPath(incGetAppConfigPath(), "i18n");
142     if (!exists(cachedLocaleDir)) {
143         
144         // Create our font directory
145         mkdirRecurse(cachedLocaleDir);
146     }
147     return cachedLocaleDir;
148 }
149 
150 /**
151     Gets special directory for locales
152 */
153 string incGetAppLocalePathExtra() {
154     
155     // AppImage locale dir is the root of the appimage
156     version(linux) {
157         auto here = environment.get("HERE");
158         if (here) {
159             return here;
160         }    
161     }
162 
163     return null;
164 }