Add desktop file format stub
This commit is contained in:
parent
218e6253e7
commit
5c911fc08d
12
format/desktop_entry/README
Normal file
12
format/desktop_entry/README
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
The desktop_entry module implements the XDG Desktop Entry Specification as
|
||||||
|
described in (https://specifications.freedesktop.org/desktop-entry-spec/latest).
|
||||||
|
Since other specifications make use of the basic desktop entry format (but with
|
||||||
|
different group names, entry requirements, etc.), this module implements:
|
||||||
|
|
||||||
|
1. The generalized format, and
|
||||||
|
2. A second processing stage to retrieve values relevant to desktop entries and
|
||||||
|
to validate them.
|
||||||
|
|
||||||
|
This module will attempt to accept malformed files for the purposes of retaining
|
||||||
|
their underlying representation, and being able to reproduce that representation
|
||||||
|
when writing updated information to the files.
|
131
format/desktop_entry/desktop_entry.ha
Normal file
131
format/desktop_entry/desktop_entry.ha
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
// Represents a file of the generic key/value format used by desktop entries.
|
||||||
|
// Specification: §3
|
||||||
|
type file = struct {
|
||||||
|
preceeding_lines: []line;
|
||||||
|
groups: []group;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A named group of key/value entries.
|
||||||
|
// Specification: §3.2
|
||||||
|
type group = struct {
|
||||||
|
name: str;
|
||||||
|
lines: []line;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A line in the file, which can be a comment (or a blank line), an entry, or
|
||||||
|
// a localized entry.
|
||||||
|
type line = (comment | entry | localized_entry);
|
||||||
|
|
||||||
|
// A comment.
|
||||||
|
// Specification: §3.1
|
||||||
|
type comment = str;
|
||||||
|
|
||||||
|
// A key/value pair.
|
||||||
|
// Specification: §3.3
|
||||||
|
type entry = struct {
|
||||||
|
key: str;
|
||||||
|
value: value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A localized entry.
|
||||||
|
// Specification: §5
|
||||||
|
type localized_entry struct {
|
||||||
|
key: str;
|
||||||
|
value: value;
|
||||||
|
locale: locale::locale;
|
||||||
|
};
|
||||||
|
|
||||||
|
// An entry value. Values that reference memory (such as [[str]]) are borrowed
|
||||||
|
// from the [[file]]. These may be free'd or overwritten when other functions in
|
||||||
|
// this module are called, so [[value_dup]] is required to extend its lifetime.
|
||||||
|
export type value = (str, bool, f32);
|
||||||
|
|
||||||
|
// Gets a non-localized value from a file. If the group does not exist, or the
|
||||||
|
// group exists but the key isn't in it, it returns void.
|
||||||
|
export fn file_get(fil: *file, group_name: str, key: str) (value | void) {
|
||||||
|
let grou = match (file_find_group(fil, group_name)) {
|
||||||
|
case index: size => yield &file.groups[index];
|
||||||
|
case void => return void;
|
||||||
|
};
|
||||||
|
let lin = match (group_find_entry(grou, key)) {
|
||||||
|
case index: size => yield &grou.lines[index];
|
||||||
|
case void => return void;
|
||||||
|
};
|
||||||
|
match (lin) {
|
||||||
|
case entr: entry => return entr.value;
|
||||||
|
case => abort();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gets a localized value from a file. If the group does not exist, or the group
|
||||||
|
// exists but the key isnt in it, it returns void. If the key is in the group
|
||||||
|
// but is not localized to the specified locale, the non-localized value is
|
||||||
|
// returned.
|
||||||
|
export fn file_get_localized(
|
||||||
|
fil: *file,
|
||||||
|
group_name: str,
|
||||||
|
key: str,
|
||||||
|
local: locale,
|
||||||
|
) (value | void) {
|
||||||
|
let grou = match (file_find_group(fil, group_name)) {
|
||||||
|
case index: size => yield &file.groups[index];
|
||||||
|
case void => return void;
|
||||||
|
};
|
||||||
|
let lin = match (group_find_localized_entry(grou, key, local)) {
|
||||||
|
case index: size => yield &grou.lines[index];
|
||||||
|
case void => return void;
|
||||||
|
};
|
||||||
|
match (lin) {
|
||||||
|
case entr: localized_entry => return entr.value;
|
||||||
|
case entr: entry => return entr.value;
|
||||||
|
case => abort();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export fn file_add
|
||||||
|
|
||||||
|
export fn file_add_localized
|
||||||
|
|
||||||
|
export fn file_remove
|
||||||
|
|
||||||
|
export fn file_remove_localized
|
||||||
|
|
||||||
|
export fn file_encode
|
||||||
|
|
||||||
|
export fn file_finish
|
||||||
|
|
||||||
|
fn file_find_group (fil *file, group_name str): (size | void) = {
|
||||||
|
let index = 0;
|
||||||
|
for (let grou .. file.groups) {
|
||||||
|
if (strings::compare(group.name, group_name) == 0) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
index ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn group_find_entry (grou *group, key str): (size | void) {
|
||||||
|
let index = 0;
|
||||||
|
for (let lin .. grou.lines) {
|
||||||
|
match (lin) {
|
||||||
|
case entr: entry =>
|
||||||
|
if (strings::compare(entry.key, entr) == 0) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
case => void ;
|
||||||
|
}
|
||||||
|
index ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duplicates a [[value]]. Use [[value_finish]] to get rid of it.
|
||||||
|
export fn value_dup(valu: value): value = match (valu) {
|
||||||
|
case let valu: str => yield strings.dup(valu);
|
||||||
|
case => yield valu;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Frees an [[entry]] previously duplicated with [[entry_dup]].
|
||||||
|
export fn value_finish(valu: value): void = match (valu) {
|
||||||
|
case let valu: str => free(valu);
|
||||||
|
case => void;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user