Skip to content

Commit

Permalink
Replace std.xml with GMarkup-based parser
Browse files Browse the repository at this point in the history
This is quite ugly, but using GMarkup avoids us introducing another
hard-to-maintain dependency for a tiny task.

(It would either be a better D XML parsing library or undeaD to
resurrect the removed standard-library module, both options are pretty
unattractive. GMarkup will not go away anytime soon)

Resolves: #2151
  • Loading branch information
ximion committed Apr 20, 2023
1 parent 6fc5d46 commit b027797
Showing 1 changed file with 55 additions and 18 deletions.
73 changes: 55 additions & 18 deletions source/gx/tilix/prefeditor/prefdialog.d
Original file line number Diff line number Diff line change
Expand Up @@ -947,40 +947,77 @@ private:
* pre GTK 3.20
*/
void loadLocalizedShortcutLabels() {
//Clear associative arrays since clear method isn't compatible with LDC
labels = null;
prefixes = null;
import glib.SimpleXML : SimpleXML;
import glib.c.types : GMarkupParser, GMarkupParseContext, GMarkupParseFlags;
import std.string : fromStringz;
import std.array : empty;

string ui = getResource(SHORTCUT_UI_RESOURCE);
if (ui.length == 0) {
errorf("Could not load '%s' resource",SHORTCUT_UI_RESOURCE);
return;
}

import std.xml: DocumentParser, ElementParser, Element, XMLException;
struct ParseHelper {
string currentId = "";
bool addNextText = false;
string[string] labels;
}

try {
DocumentParser parser = new DocumentParser(ui);
parser.onStartTag["object"] = (ElementParser xml) {
if (xml.tag.attr["class"] == "GtkShortcutsShortcut") {
string id = xml.tag.attr["id"];
xml.onEndTag["property"] = (in Element e) {
if (e.tag.attr["name"] == "title") {
labels[id] = C_(SHORTCUT_LOCALIZATION_CONTEXT, e.text);
}
};
xml.parse();
GMarkupParser parseConfig;
parseConfig.startElement = function void(GMarkupParseContext* context,
const(char)* elementNameC,
char** attributeNames,
char** attributeValues,
void* userData,
GError** err) {
auto helper = cast(ParseHelper*)userData;
const elementName = elementNameC.fromStringz;
if (elementName == "object") {
string[string] attrs;
for (uint i = 0; attributeNames[i] != null; i++)
attrs[attributeNames[i].fromStringz.to!string] = attributeValues[i].fromStringz.to!string;

if (attrs.get("class", "") == "GtkShortcutsShortcut")
helper.currentId = attrs["id"];

} else if (elementName == "property" && !helper.currentId.empty) {
for (uint i = 0; attributeNames[i] != null; i++) {
if (attributeNames[i].fromStringz == "name" && attributeValues[i].fromStringz == "title") {
helper.addNextText = true;
break;
}
}
};
parser.parse();
}
};
parseConfig.text = function void(GMarkupParseContext* context,
const(char)* text,
size_t textLen,
void* userData,
GError** err) {
auto helper = cast(ParseHelper*)userData;
if (!helper.addNextText)
return;

helper.labels[helper.currentId] = C_(SHORTCUT_LOCALIZATION_CONTEXT, text.fromStringz.to!string);
helper.currentId = null;
helper.addNextText = false;
};

try {
ParseHelper helper;
auto parser = new SimpleXML(&parseConfig, GMarkupParseFlags.PREFIX_ERROR_POSITION, &helper, null);
parser.parse(ui, ui.length);
labels = helper.labels;

// While you could use sections to get prefixes, not all sections are there
// and it's not inutituve from a localization perspective. Just add them manually
prefixes[ACTION_PREFIX_WIN] = C_(SHORTCUT_LOCALIZATION_CONTEXT, "Window");
prefixes[ACTION_PREFIX_APP] = C_(SHORTCUT_LOCALIZATION_CONTEXT, "Application");
prefixes[ACTION_PREFIX_TERMINAL] = C_(SHORTCUT_LOCALIZATION_CONTEXT, "Terminal");
prefixes[ACTION_PREFIX_SESSION] = C_(SHORTCUT_LOCALIZATION_CONTEXT, "Session");
prefixes[ACTION_PREFIX_NAUTILUS] = C_(SHORTCUT_LOCALIZATION_CONTEXT, "Nautilus");
} catch (XMLException e) {
} catch (Exception e) {
error("Failed to parse shortcuts.ui", e);
}
}
Expand Down

0 comments on commit b027797

Please sign in to comment.