diff --git a/source/configy/Exceptions.d b/source/configy/Exceptions.d index 402ee69..65d658f 100644 --- a/source/configy/Exceptions.d +++ b/source/configy/Exceptions.d @@ -18,8 +18,9 @@ import dyaml.exception; import dyaml.node; -import std.algorithm : map; +import std.algorithm : filter, map; import std.format; +import std.string : soundexer; /******************************************************************************* @@ -306,13 +307,32 @@ const scope @safe { const useColors = spec.spec == 'S'; - const fmt = "Key is not a valid member of this section. There are %s valid keys: %-(%s, %)"; - if (useColors) - formattedWrite(sink, fmt, this.fieldNames.length.paint(Yellow), - this.fieldNames.map!(f => f.paint(Green))); + // Try to find a close match, as the error is likely a typo + // This is especially important when the config file has a large + // number of fields, where the message is otherwise near-useless. + const origSound = soundexer(this.key); + auto matches = this.fieldNames.filter!(f => f.soundexer == origSound); + const hasMatch = !matches.save.empty; + + if (hasMatch) + { + const fmt = "Key is not a valid member of this section. Did you mean: %-(%s, %)"; + if (useColors) + formattedWrite(sink, fmt, matches.map!(f => f.paint(Green))); + else + formattedWrite(sink, fmt, matches); + } else - formattedWrite(sink, fmt, this.fieldNames.length, this.fieldNames); + { + // No match, just print everything + const fmt = "Key is not a valid member of this section. There are %s valid keys: %-(%s, %)"; + if (useColors) + formattedWrite(sink, fmt, this.fieldNames.length.paint(Yellow), + this.fieldNames.map!(f => f.paint(Green))); + else + formattedWrite(sink, fmt, this.fieldNames.length, this.fieldNames); + } } } diff --git a/source/configy/Test.d b/source/configy/Test.d index cf28a8f..b723184 100644 --- a/source/configy/Test.d +++ b/source/configy/Test.d @@ -207,6 +207,8 @@ static struct Config { string value; + string valhu; + string halvue; } try @@ -216,7 +218,7 @@ } catch (ConfigException exc) { - assert(exc.toString() == "/dev/null(0:0): valeu: Key is not a valid member of this section. There are 1 valid keys: value"); + assert(exc.toString() == "/dev/null(0:0): valeu: Key is not a valid member of this section. Did you mean: value, valhu"); } }