diff --git a/.travis.yml b/.travis.yml index 8ed4ce7..309764a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: d matrix: allow_failures: - d: gdc-4.8.2 - - d: ldc-0.15.1 + - d: ldc-0.14.0 - d: dmd-2.065.0 include: - d: dmd-2.067.1 @@ -10,6 +10,7 @@ matrix: - d: ldc-0.15.1 - d: dmd-2.065.0 - d: gdc-4.8.2 + - d: ldc-0.14.0 script: - dub test --compiler=${DC} diff --git a/README.md b/README.md index 7373c58..f488570 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ # Desktopfile D library for working with *.desktop* files. Desktop entries in Freedesktop world are akin to shortcuts from Windows world (.lnk files). + +[![Build Status](https://travis-ci.org/MyLittleRobo/desktopfile.svg?branch=master)](https://travis-ci.org/MyLittleRobo/desktopfile) + The most of desktop environments on Linux and BSD flavors follows [Desktop Entry Specification](http://standards.freedesktop.org/desktop-entry-spec/latest/) today. The goal of **desktopfile** library is to provide implementation of this specification in D programming language. Please feel free to propose enchancements or report any related bugs to *Issues* page. diff --git a/source/desktopfile.d b/source/desktopfile.d index f4682ca..6d07b2e 100644 --- a/source/desktopfile.d +++ b/source/desktopfile.d @@ -113,10 +113,20 @@ public: */ @safe this() { super(); - _desktopEntry = addGroup("Desktop Entry"); + _desktopEntry = super.addGroup("Desktop Entry"); this["Version"] = "1.0"; } + @safe override IniLikeGroup addGroup(string groupName) { + if (!_desktopEntry) { + enforce(groupName == "Desktop Entry", "The first group must be Desktop Entry"); + _desktopEntry = super.addGroup(groupName); + return _desktopEntry; + } else { + return super.addGroup(groupName); + } + } + /** * Removes group by name. You can't remove "Desktop Entry" group with this function. */ @@ -165,7 +175,7 @@ public: return Type.Directory; } } - if (fileName().extension == ".directory") { + if (fileName().baseName() == ".directory" || fileName().extension == ".directory") { return Type.Directory; } diff --git a/source/inilike.d b/source/inilike.d index e3a253d..9ee4ea9 100644 --- a/source/inilike.d +++ b/source/inilike.d @@ -83,6 +83,11 @@ private alias KeyValueTuple = Tuple!(string, "key", string, "value"); /** * Constructs localized key name from key and locale. * Returns: localized key in form key[locale]. Automatically omits locale encoding if present. + * Example: +---------- +assert(localizedKey("Name", "ru_RU") == "Name[ru_RU]"); +---------- + * */ @safe string localizedKey(string key, string locale) pure nothrow { @@ -94,7 +99,11 @@ private alias KeyValueTuple = Tuple!(string, "key", string, "value"); } /** - * Ditto, but constructs locale name from arguments. + * ditto, but constructs locale name from arguments. + * Example: +---------- +assert(localizedKey("Name", "ru", "RU") == "Name[ru_RU]"); +---------- */ @safe string localizedKey(string key, string lang, string country, string modifier = null) pure nothrow { @@ -249,15 +258,15 @@ struct IniLikeLine GroupStart = 4 } - @safe static IniLikeLine fromComment(string comment) nothrow { + @nogc @safe static IniLikeLine fromComment(string comment) nothrow { return IniLikeLine(comment, null, Type.Comment); } - @safe static IniLikeLine fromGroupName(string groupName) nothrow { + @nogc @safe static IniLikeLine fromGroupName(string groupName) nothrow { return IniLikeLine(groupName, null, Type.GroupStart); } - @safe static IniLikeLine fromKeyValue(string key, string value) nothrow { + @nogc @safe static IniLikeLine fromKeyValue(string key, string value) nothrow { return IniLikeLine(key, value, Type.KeyValue); } @@ -479,7 +488,7 @@ private: } /** - * Reads range of strings into the range on IniLikeLines. + * Reads range of strings into the range of IniLikeLines. */ @trusted auto iniLikeRangeReader(Range)(Range byLine) if(is(ElementType!Range == string)) { @@ -580,10 +589,7 @@ public: } break; case IniLikeLine.Type.GroupStart: - { - enforce(line.groupName.length, "empty group name"); - enforce(group(line.groupName) is null, "group is defined more than once"); - + { currentGroup = addGroup(line.groupName); if (options & ReadOptions.firstGroupOnly) { @@ -628,10 +634,10 @@ public: * Throws: Exception if group with such name already exists or groupName is empty. */ @safe IniLikeGroup addGroup(string groupName) { - enforce(groupName.length, "group name is empty"); + enforce(groupName.length, "empty group name"); + enforce(group(groupName) is null, "group already exists"); auto iniLikeGroup = new IniLikeGroup(groupName, this); - enforce(group(groupName) is null, "group already exists"); _groupIndices[groupName] = _groups.length; _groups ~= iniLikeGroup; @@ -651,7 +657,7 @@ public: /** * Range of groups in order how they were defined in file. */ - @safe auto byGroup() { + @nogc @safe auto byGroup() { return _groups[].map!(g => g); //to prevent elements be accessible as lvalues } ///ditto