diff --git a/lib/std/io/path.c3 b/lib/std/io/path.c3 index 072912889..11f70c22f 100644 --- a/lib/std/io/path.c3 +++ b/lib/std/io/path.c3 @@ -1,5 +1,6 @@ module std::io::path; import std::collections::list; +import std::os::env; const PathEnv DEFAULT_PATH_ENV = env::WIN32 ? PathEnv.WIN32 : PathEnv.POSIX; const char PREFERRED_SEPARATOR_WIN32 = '\\'; @@ -448,6 +449,54 @@ fn void Path.free(self) free(self.path_string.ptr); } + +/** + * Returns the current user's home directory. + **/ +fn String! get_home_dir() +{ + String home; + $if env::WIN32: + home = "USERPROFILE"; + $else + home = "HOME"; + $endif + return env::get_var(home); +} + +/** + * Returns the current user's config directory. + **/ +fn String! get_config_dir(Allocator* using = mem::heap()) +{ + $if env::WIN32: + String s = env::get_var("AppData")!; + return s; + $else + String s; + DString str; + $if env::DARWIN: + s = env::get_var("HOME")!; + const DIR = "/Library/Application Support"; + $else + if (try s1 = env::get_var("XDG_CONFIG_HOME")) + { + s = s1; + } + else + { + s = env::get_var("HOME")!; + } + const DIR = "/.config"; + $endif + str.init(s.len + DIR.len, using); + str.append(s); + str.append(DIR); + return str.as_str(); + $endif +} + + const bool[256] RESERVED_PATH_CHAR_POSIX = { [0] = true, ['/'] = true, diff --git a/lib/std/os/env.c3 b/lib/std/os/env.c3 index e7a864253..cf381900f 100644 --- a/lib/std/os/env.c3 +++ b/lib/std/os/env.c3 @@ -10,15 +10,33 @@ import libc; **/ fn String! get_var(String name) { - $if env::LIBC && !env::WIN32: + $switch + $case env::LIBC && !env::WIN32: @pool() { ZString val = libc::getenv(name.zstr_tcopy()); return val ? val.as_str() : SearchResult.MISSING?; }; - $else + $case env::WIN32: + @pool() + { + // https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getenvironmentvariable + WString wname = name.to_wstring(.using = mem::temp())!; + const N = 64; + DString buffer; + buffer.tinit(N); + usz n = (usz)win32::getEnvironmentVariable(wname, (Win32_LPCWSTR)buffer.as_str().ptr, (Win32_DWORD)buffer.capacity()); + if (n == 0) return SearchResult.MISSING?; + if (n > N) + { + buffer.reserve(n - N); + win32::getEnvironmentVariable(wname, (Win32_LPCWSTR)buffer.as_str().ptr, (Win32_DWORD)buffer.capacity()); + } + return buffer.as_str(); + }; + $default: return ""; - $endif + $endswitch } /** diff --git a/lib/std/os/win32/process.c3 b/lib/std/os/win32/process.c3 index f9912c057..9e98fadf0 100644 --- a/lib/std/os/win32/process.c3 +++ b/lib/std/os/win32/process.c3 @@ -83,7 +83,11 @@ extern fn Win32_BOOL getOverlappedResult( Win32_LPDWORD lpNumberOfBytesTransferred, Win32_BOOL bWait ) @extern("GetOverlappedResult"); - +extern fn Win32_DWORD getEnvironmentVariable( + Win32_LPCWSTR lpName, + Win32_LPWSTR lpBuffer, + Win32_DWORD nSize +) @extern("GetEnvironmentVariable"); struct SystemInfo {