First pieces of .desktop file parser
This commit is contained in:
parent
f328a2ad89
commit
5ff941fc5f
@ -37,7 +37,6 @@ public:
|
||||
|
||||
this ()
|
||||
{
|
||||
writeln ("HELLO THERE!");
|
||||
}
|
||||
|
||||
~this ()
|
||||
|
@ -17,4 +17,116 @@
|
||||
* along with this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module ag.handler.desktopparser;
|
||||
module ag.handler.desktopparser;
|
||||
|
||||
import std.path : baseName;
|
||||
import std.uni : toLower;
|
||||
import std.string : format;
|
||||
import std.algorithm : startsWith;
|
||||
import glib.KeyFile;
|
||||
import appstream.Component;
|
||||
|
||||
import ag.result;
|
||||
|
||||
|
||||
immutable DESKTOP_GROUP = "Desktop Entry";
|
||||
|
||||
private string getLocaleFromKey (string key)
|
||||
{
|
||||
return "C";
|
||||
}
|
||||
|
||||
private string getValue (KeyFile kf, string key)
|
||||
{
|
||||
string val;
|
||||
try {
|
||||
val = kf.getString (DESKTOP_GROUP, key);
|
||||
} catch {
|
||||
val = null;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
bool parseDesktopFile (GeneratorResult res, string fname, string data, bool ignore_nodisplay = false)
|
||||
{
|
||||
auto df = new KeyFile ();
|
||||
try {
|
||||
df.loadFromData (data, -1, GKeyFileFlags.NONE);
|
||||
} catch (Exception e) {
|
||||
// there was an error
|
||||
res.addHint ("desktop-file-read-error", e.msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// check if we should ignore this .desktop file
|
||||
auto dtype = df.getString (DESKTOP_GROUP, "Type");
|
||||
if (dtype.toLower () != "application") {
|
||||
// ignore this file, it isn't describing an application
|
||||
return false;
|
||||
}
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
auto nodisplay = df.getString (DESKTOP_GROUP, "NoDisplay");
|
||||
if ((!ignore_nodisplay) && (nodisplay.toLower () == "true")) {
|
||||
// we ignore this .desktop file, shouldn't be displayed
|
||||
return false;
|
||||
}
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
auto asignore = df.getString (DESKTOP_GROUP, "X-AppStream-Ignore");
|
||||
if (asignore.toLower () == "true") {
|
||||
// this .desktop file should be excluded from AppStream metadata
|
||||
return false;
|
||||
}
|
||||
} catch {
|
||||
// we don't care if non-essential tags are missing.
|
||||
// if they are not there, the file should be processed.
|
||||
}
|
||||
|
||||
/* check this is a valid desktop file */
|
||||
if (!df.hasGroup (DESKTOP_GROUP)) {
|
||||
res.addHint ("desktop-file-error", format ("Desktop file '%s' is not a valid desktop file.", fname));
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure we have a valid component to work on
|
||||
auto cpt = res.getComponent (fname);
|
||||
if (cpt is null) {
|
||||
auto fname_base = baseName (fname);
|
||||
cpt = new Component ();
|
||||
cpt.setId (fname_base);
|
||||
cpt.setKind (ComponentKind.DESKTOP);
|
||||
res.addComponent (cpt);
|
||||
}
|
||||
|
||||
size_t dummy;
|
||||
auto keys = df.getKeys (DESKTOP_GROUP, dummy);
|
||||
foreach (string key; keys) {
|
||||
if (key.startsWith ("Name")) {
|
||||
auto locale = getLocaleFromKey (key);
|
||||
cpt.setName (getValue (df, key), locale);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
auto data = """
|
||||
[Desktop Entry]
|
||||
Name=FooBar
|
||||
Name[de_DE]=FooBär
|
||||
Summary=A foo-ish bar.
|
||||
""";
|
||||
|
||||
auto res = new GeneratorResult ();
|
||||
auto ret = parseDesktopFile (res, "foobar.desktop", data, false);
|
||||
assert (ret == true);
|
||||
}
|
||||
|
@ -27,11 +27,13 @@ class GeneratorHint
|
||||
{
|
||||
|
||||
private:
|
||||
string tag;
|
||||
|
||||
public:
|
||||
|
||||
this ()
|
||||
this (string tag)
|
||||
{
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,16 +21,19 @@ module ag.result;
|
||||
|
||||
import std.stdio;
|
||||
import std.string;
|
||||
import ag.hint;
|
||||
import std.array : empty;
|
||||
import appstream.Component;
|
||||
|
||||
import ag.hint;
|
||||
|
||||
|
||||
class GeneratorResult
|
||||
{
|
||||
|
||||
private:
|
||||
Component cpts[];
|
||||
GeneratorHint hints[];
|
||||
Component[string] cpts;
|
||||
string[Component] cptGID;
|
||||
GeneratorHint[] hints;
|
||||
|
||||
public:
|
||||
|
||||
@ -42,4 +45,27 @@ public:
|
||||
{
|
||||
return cpts.length == 0;
|
||||
}
|
||||
|
||||
Component getComponent (string id)
|
||||
{
|
||||
auto ptr = (id in cpts);
|
||||
if (ptr is null)
|
||||
return null;
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
void addComponent (Component cpt)
|
||||
{
|
||||
string cid = cpt.getId ();
|
||||
if (cid.empty)
|
||||
throw new Exception ("Can not add component without ID to results set.");
|
||||
|
||||
cpts[cid] = cpt;
|
||||
}
|
||||
|
||||
void addHint (string tag, string msg)
|
||||
{
|
||||
auto hint = new GeneratorHint (tag);
|
||||
hints ~= hint;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user