format::desktop_entry: Add desktop entry file parsing
This commit is contained in:
parent
4f1b87181d
commit
0362ae4515
189
format/desktop_entry/desktop_entry.ha
Normal file
189
format/desktop_entry/desktop_entry.ha
Normal file
@ -0,0 +1,189 @@
|
||||
use locale;
|
||||
use strings;
|
||||
|
||||
// The information from a desktop entry file.
|
||||
export type file = struct {
|
||||
typ: str,
|
||||
version: str,
|
||||
name: locale::string,
|
||||
generic_name: locale::string,
|
||||
no_display: bool,
|
||||
comment: locale::string,
|
||||
icon: locale::string,
|
||||
hidden: bool,
|
||||
only_show_in: []str,
|
||||
not_show_in: []str,
|
||||
dbus_activatable: bool,
|
||||
try_exec: str,
|
||||
exec: str,
|
||||
path: str,
|
||||
terminal: bool,
|
||||
actions: []str,
|
||||
mime_type: []str,
|
||||
categories: []str,
|
||||
implements: []str,
|
||||
keywords: locale::strings,
|
||||
startup_notify: bool,
|
||||
startup_wm_class: str,
|
||||
url: str,
|
||||
prefers_non_default_gpu: bool,
|
||||
single_main_window: bool,
|
||||
};
|
||||
|
||||
// Parses a desktop entry file. Use [[file_finish]] to get rid of it.
|
||||
export fn parse(input: io::handle) (file | error) = {
|
||||
let state = parse_state { ... };
|
||||
let scanne = scan(input);
|
||||
defer finish(&scanne);
|
||||
|
||||
for (let entr => next_entry(&scanne)) {
|
||||
match(parse_handle_entry(entr)) {
|
||||
case let err: error =>
|
||||
file_finish(&state.file);
|
||||
return err;
|
||||
case void => void;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// Frees resources associated with a [[file]].
|
||||
export fn file_finish(file: &file) void = {
|
||||
free(file.typ);
|
||||
free(file.version);
|
||||
locale_string_finish(file.name);
|
||||
locale_string_finish(file.generic_name);
|
||||
locale_string_finish(file.comment);
|
||||
locale_string_finish(file.icon);
|
||||
strings::freeall(file.only_show_in);
|
||||
strings::freeall(file.not_show_in);
|
||||
free(file.try_exec);
|
||||
free(file.exec);
|
||||
free(file.path);
|
||||
strings::freeall(file.actions);
|
||||
strings::freeall(file.mime_type);
|
||||
strings::freeall(file.categories);
|
||||
strings::freeall(file.implements);
|
||||
locale_strings_finish(file.keywords);
|
||||
free(file.startup_wm_class);
|
||||
free(file.url);
|
||||
};
|
||||
|
||||
type parse_state = struct {
|
||||
file: file,
|
||||
};
|
||||
|
||||
fn parse_handle_entry(this: *parse_state, entr: entry) (void | error) = {
|
||||
if (entr.group != "Desktop Entry") return void;
|
||||
|
||||
if (entr.key == "Type") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.typ = parse_string(entr.value)?;
|
||||
} else if (entr.key == "Version") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.version = parse_string(entr.value)?;
|
||||
} else if (entr.key == "Name") {
|
||||
parse_set_locale_string(
|
||||
*this.name, entr.locale,
|
||||
parse_localestring(entr.value)?)?;
|
||||
} else if (entr.key == "GenericName") {
|
||||
parse_set_locale_string(
|
||||
*this.generic_name, entr.locale,
|
||||
parse_localestring(entr.value)?)?;
|
||||
} else if (entr.key == "NoDisplay") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.no_display = parse_boolean(entr.value)?;
|
||||
} else if (entr.key == "Comment") {
|
||||
parse_set_locale_string(
|
||||
*this.comment, entr.locale,
|
||||
parse_localestring(entr.value)?)?;
|
||||
} else if (entr.key == "Icon") {
|
||||
parse_set_locale_string(
|
||||
*this.icon, entr.locale,
|
||||
parse_iconstring(entr.value)?)?;
|
||||
} else if (entr.key == "Hidden") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.hidden = parse_boolean(entr.value)?;
|
||||
} else if (entr.key == "OnlyShowIn") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.only_show_in = parse_strings(entr.value)?;
|
||||
} else if (entr.key == "NotShowIn") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.not_show_in = parse_strings(entr.value)?;
|
||||
} else if (entr.key == "DBusActivatable") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.dbus_activatable = parse_bool(entr.value)?;
|
||||
} else if (entr.key == "TryExec") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.try_exec = parse_string(entr.value)?;
|
||||
} else if (entr.key == "Path") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.path = parse_string(entr.value)?;
|
||||
} else if (entr.key == "Terminal") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.terminal = parse_boolean(entr.value)?;
|
||||
} else if (entr.key == "Actions") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.actions = parse_strings(entr.value)?;
|
||||
} else if (entr.key == "MimeType") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.mime_type = parse_strings(entr.value)?;
|
||||
} else if (entr.key == "Categories") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.categories = parse_strings(entr.value)?;
|
||||
} else if (entr.key == "Implements") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.implements = parse_strings(entr.value)?;
|
||||
} else if (entr.key == "Keywords") {
|
||||
parse_set_locale_strings(
|
||||
*this.keywords, entr.locale,
|
||||
parse_localestring(entr.value)?)?;
|
||||
} else if (entr.key == "StartupWMClass") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.startup_wm_class = parse_string(entr.value)?;
|
||||
} else if (entr.key == "URL") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.url = parse_string(entr.value)?;
|
||||
} else if (entr.key == "PrefersNonDefaultGPU") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.prefers_non_default_gpu = parse_bool(entr.value)?;
|
||||
} else if (entr.key == "SingleMainWindow") {
|
||||
if parse_is_localized(entr) return void;
|
||||
this.single_main_window = parse_bool(entr.value)?;
|
||||
};
|
||||
};
|
||||
|
||||
fn parse_is_localized(entr: entry) bool = {
|
||||
return !locale::equal(entr.locale, locale::c);
|
||||
};
|
||||
|
||||
fn parse_set_locale_string(dest *locale::string, local: locale::locale, value: str) void = {
|
||||
for (let existing &.. *dest) {
|
||||
if (locale::equal(existing.0, locale)) {
|
||||
existing.1 = value;
|
||||
return;
|
||||
};
|
||||
};
|
||||
append(*dest, (locale::dup(local), strings::dup(value)));
|
||||
};
|
||||
|
||||
fn parse_set_locale_strings(dest *locale::strings, local: locale::locale, value: []str) void = {
|
||||
for (let existing &.. *dest) {
|
||||
if (locale::equal(existing.0, locale)) {
|
||||
existing.1 = value;
|
||||
return;
|
||||
};
|
||||
};
|
||||
append(*dest, (locale::dup(local), strings::dupall(value)));
|
||||
};
|
||||
|
||||
fn locale_string_finish(string: locale::string) void = {
|
||||
for (let pair .. string) {
|
||||
locale::finish(pair.0);
|
||||
free(pair.1);
|
||||
};
|
||||
free(string);
|
||||
};
|
||||
|
||||
fn locale_strings_finish(strings: locale::strings) void = {
|
||||
for (string .. strings) locale_string_finish(string);
|
||||
};
|
Loading…
Reference in New Issue
Block a user