Add way to query the system locales
This commit is contained in:
parent
27b7252580
commit
409aab92ff
96
locale/+linux.ha
Normal file
96
locale/+linux.ha
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
use bufio;
|
||||||
|
use errors;
|
||||||
|
use io;
|
||||||
|
use os;
|
||||||
|
use strings;
|
||||||
|
|
||||||
|
def locale_conf_path = "/etc/locale.conf";
|
||||||
|
|
||||||
|
// Returns the locale to use for character classification and case conversion.
|
||||||
|
// The memory is statically allocated and must not be free'd. It may be
|
||||||
|
// overwritten later, so use [[locale_dup]] to extend its lifetime.
|
||||||
|
export fn get_ctype() locale = get_locale("LC_CTYPE");
|
||||||
|
|
||||||
|
// Returns the locale to use for collation order.
|
||||||
|
// The memory is statically allocated and must not be free'd. It may be
|
||||||
|
// overwritten later, so use [[locale_dup]] to extend its lifetime.
|
||||||
|
export fn get_collate() locale = get_locale("LC_COLLATE");
|
||||||
|
|
||||||
|
// Returns the locale to use for monetary formatting.
|
||||||
|
// The memory is statically allocated and must not be free'd. It may be
|
||||||
|
// overwritten later, so use [[locale_dup]] to extend its lifetime.
|
||||||
|
export fn get_monetary() locale = get_locale("LC_MONETARY");
|
||||||
|
|
||||||
|
// Returns the locale to use for numeric, non-monetary formatting.
|
||||||
|
// The memory is statically allocated and must not be free'd. It may be
|
||||||
|
// overwritten later, so use [[locale_dup]] to extend its lifetime.
|
||||||
|
export fn get_numeric() locale = get_locale("LC_NUMERIC");
|
||||||
|
|
||||||
|
// Returns the locale to use for date and time formats.
|
||||||
|
// The memory is statically allocated and must not be free'd. It may be
|
||||||
|
// overwritten later, so use [[locale_dup]] to extend its lifetime.
|
||||||
|
export fn get_time() locale = get_locale("LC_TIME");
|
||||||
|
|
||||||
|
// Returns the locale to use for formats of informative and diagnostic messages
|
||||||
|
// and interactive responses.
|
||||||
|
// The memory is statically allocated and must not be free'd. It may be
|
||||||
|
// overwritten later, so use [[locale_dup]] to extend its lifetime.
|
||||||
|
export fn get_messages() locale = get_locale("LC_MESSAGES");
|
||||||
|
|
||||||
|
// Returns the locale to use for linguistic translations.
|
||||||
|
// The memory is statically allocated and must not be free'd. It may be
|
||||||
|
// overwritten later, so use [[locale_dup]] to extend its lifetime.
|
||||||
|
export fn get_lang() locale = get_locale("LC_LANG");
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
fn get_language() []locale;
|
||||||
|
|
||||||
|
fn get_locale(var: str) locale =
|
||||||
|
match (get_env_locale(var)) {
|
||||||
|
case let local: locale => yield local;
|
||||||
|
case =>
|
||||||
|
yield match (get_locale_conf_entry(var)) {
|
||||||
|
case let local: locale => yield local;
|
||||||
|
case =>
|
||||||
|
yield c;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
fn get_env_locale(var: str) (locale | errors::invalid) =
|
||||||
|
match (os::getenv(var)) {
|
||||||
|
case let env: str => return parse_locale(env);
|
||||||
|
case => return errors::invalid;
|
||||||
|
};
|
||||||
|
|
||||||
|
let locale_conf: []str = [];
|
||||||
|
|
||||||
|
@fini fn locale_conf() void = strings::freeall(locale_conf);
|
||||||
|
|
||||||
|
fn get_locale_conf_entry(var: str) (locale | errors::invalid) = {
|
||||||
|
get_locale_conf();
|
||||||
|
for (let entry .. locale_conf) {
|
||||||
|
let (key, value) = strings::cut(entry, "=");
|
||||||
|
if (key == var) return parse_locale(value);
|
||||||
|
};
|
||||||
|
return errors::invalid;
|
||||||
|
};
|
||||||
|
|
||||||
|
fn get_locale_conf() []str = {
|
||||||
|
if (len(locale_conf) != 0) return locale_conf;
|
||||||
|
|
||||||
|
let file = match (os::open(locale_conf_path)) {
|
||||||
|
case let file: io::file => yield file;
|
||||||
|
case => return locale_conf;
|
||||||
|
};
|
||||||
|
defer io::close(file)!; // when the hell does closing a file fail????
|
||||||
|
|
||||||
|
let scanner = bufio::newscanner(file);
|
||||||
|
defer bufio::finish(&scanner);
|
||||||
|
|
||||||
|
for (true) {
|
||||||
|
match (bufio::scan_line(&scanner)) {
|
||||||
|
case let line: const str => append(locale_conf, line);
|
||||||
|
case => return locale_conf;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
40
locale/-linux.ha
Normal file
40
locale/-linux.ha
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
use errors;
|
||||||
|
|
||||||
|
// Returns the locale to use for character classification and case conversion.
|
||||||
|
// The memory is statically allocated and must not be free'd. It may be
|
||||||
|
// overwritten later, so use [[locale_dup]] to extend its lifetime.
|
||||||
|
export fn get_ctype() locale = c;
|
||||||
|
|
||||||
|
// Returns the locale to use for collation order.
|
||||||
|
// The memory is statically allocated and must not be free'd. It may be
|
||||||
|
// overwritten later, so use [[locale_dup]] to extend its lifetime.
|
||||||
|
export fn get_collate() locale = c;
|
||||||
|
|
||||||
|
// Returns the locale to use for monetary formatting.
|
||||||
|
// The memory is statically allocated and must not be free'd. It may be
|
||||||
|
// overwritten later, so use [[locale_dup]] to extend its lifetime.
|
||||||
|
export fn get_monetary() locale = c;
|
||||||
|
|
||||||
|
// Returns the locale to use for numeric, non-monetary formatting.
|
||||||
|
// The memory is statically allocated and must not be free'd. It may be
|
||||||
|
// overwritten later, so use [[locale_dup]] to extend its lifetime.
|
||||||
|
export fn get_numeric() locale = c;
|
||||||
|
|
||||||
|
// Returns the locale to use for date and time formats.
|
||||||
|
// The memory is statically allocated and must not be free'd. It may be
|
||||||
|
// overwritten later, so use [[locale_dup]] to extend its lifetime.
|
||||||
|
export fn get_time() locale = c;
|
||||||
|
|
||||||
|
// Returns the locale to use for formats of informative and diagnostic messages
|
||||||
|
// and interactive responses.
|
||||||
|
// The memory is statically allocated and must not be free'd. It may be
|
||||||
|
// overwritten later, so use [[locale_dup]] to extend its lifetime.
|
||||||
|
export fn get_messages() locale = c;
|
||||||
|
|
||||||
|
// Returns the locale to use for linguistic translations.
|
||||||
|
// The memory is statically allocated and must not be free'd. It may be
|
||||||
|
// overwritten later, so use [[locale_dup]] to extend its lifetime.
|
||||||
|
export fn get_lang() locale = c;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
export fn get_language() []locale;
|
@ -10,13 +10,20 @@ export type locale = struct {
|
|||||||
modifier: str,
|
modifier: str,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The default locale. Stands for computer, the C language, etc.
|
||||||
|
export def c = locale {
|
||||||
|
lang = "C",
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
// Parses a [[locale]] name of the form:
|
// Parses a [[locale]] name of the form:
|
||||||
//
|
//
|
||||||
// lang_COUNTRY.ENCODING@MODIFIER
|
// lang_COUNTRY.ENCODING@MODIFIER
|
||||||
//
|
//
|
||||||
// Where _COUNTRY, .ENCODING, and @MODIFIER may be omitted. The function
|
// Where _COUNTRY, .ENCODING, and @MODIFIER may be omitted. The function
|
||||||
// returns a [[locale]], or [[errors::invalid]] if the input cannot be parsed.
|
// returns a [[locale]], or [[errors::invalid]] if the input cannot be parsed.
|
||||||
// All memory is borrowed from the input.
|
// All memory is borrowed from the input, so [[locale_finish]] should not be
|
||||||
|
// used to free it.
|
||||||
export fn parse_locale(in: str) (locale | errors::invalid) = {
|
export fn parse_locale(in: str) (locale | errors::invalid) = {
|
||||||
let (in, modifier) = strings::rcut(in, "@");
|
let (in, modifier) = strings::rcut(in, "@");
|
||||||
if (strings::compare(in, "") == 0) return void: errors::invalid;
|
if (strings::compare(in, "") == 0) return void: errors::invalid;
|
||||||
@ -55,7 +62,23 @@ export fn format_locale(local: locale) str = {
|
|||||||
|
|
||||||
// Checks if two [[locale]]s are equal.
|
// Checks if two [[locale]]s are equal.
|
||||||
export fn locale_equal(a: locale, b: locale) bool =
|
export fn locale_equal(a: locale, b: locale) bool =
|
||||||
strings::compare(a.lang, b.lang ) == 0 &&
|
a.lang == b.lang &&
|
||||||
strings::compare(a.country, b.country ) == 0 &&
|
a.country == b.country &&
|
||||||
strings::compare(a.encoding, b.encoding) == 0 &&
|
a.encoding == b.encoding &&
|
||||||
strings::compare(a.modifier, b.modifier) == 0;
|
a.modifier == b.modifier;
|
||||||
|
|
||||||
|
// Duplicates a [[locale]] structure. Use [[locale_finish]] to get rid of it.
|
||||||
|
export fn locale_dup(local: locale) locale = locale {
|
||||||
|
lang = strings::dup(local.lang),
|
||||||
|
country = strings::dup(local.country),
|
||||||
|
encoding = strings::dup(local.encoding),
|
||||||
|
modifier = strings::dup(local.modifier),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Frees memory associated with a [[locale]] structure.
|
||||||
|
export fn locale_finish(local: locale) void = {
|
||||||
|
free(local.lang);
|
||||||
|
free(local.country);
|
||||||
|
free(local.encoding);
|
||||||
|
free(local.modifier);
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user