diff options
author | Evgeny Khramtsov <ekhramtsov@process-one.net> | 2019-04-29 20:57:59 +0300 |
---|---|---|
committer | Evgeny Khramtsov <ekhramtsov@process-one.net> | 2019-04-29 20:57:59 +0300 |
commit | 39bbc7cad862a71b4da9f02b86f8af6f1be55c4a (patch) | |
tree | cfa01419e3ba719ad3468d81af1720734048f41e /src/ejabberd_config.erl | |
parent | Disable offline_from_mam tests on riak since it doesn't support mam (diff) |
Provide a suggestion when unknown option is detected
Diffstat (limited to 'src/ejabberd_config.erl')
-rw-r--r-- | src/ejabberd_config.erl | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index b9b0f8ee..00120fcb 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -38,7 +38,8 @@ default_db/1, default_db/2, default_ram_db/1, default_ram_db/2, default_queue_type/1, queue_dir/0, fsm_limit_opts/1, use_cache/1, cache_size/1, cache_missed/1, cache_life_time/1, - codec_options/1, get_plain_terms_file/2, negotiation_timeout/0]). + codec_options/1, get_plain_terms_file/2, negotiation_timeout/0, + similar_option/2]). -export([start/2]). @@ -1099,7 +1100,9 @@ validate_opts(#state{opts = Opts} = State, ModOpts) -> erlang:error(invalid_option) end; _ -> - ?ERROR_MSG("Unknown option '~s'", [Opt]), + KnownOpts = dict:fetch_keys(ModOpts), + ?ERROR_MSG("Unknown option '~s', did you mean '~s'?", + [Opt, similar_option(Opt, KnownOpts)]), erlang:error(unknown_option) end end, Opts), @@ -1123,6 +1126,34 @@ is_file_readable(Path) -> false end. +-spec similar_option(atom(), [atom()]) -> atom(). +similar_option(Pattern, [_|_] = Opts) -> + String = atom_to_list(Pattern), + {Ds, _} = lists:mapfoldl( + fun(Opt, Cache) -> + {Distance, Cache1} = ld(String, atom_to_list(Opt), Cache), + {{Distance, Opt}, Cache1} + end, #{}, Opts), + element(2, lists:min(Ds)). + +%% Levenshtein distance +-spec ld(string(), string(), map()) -> {non_neg_integer(), map()}. +ld([] = S, T, Cache) -> + {length(T), maps:put({S, T}, length(T), Cache)}; +ld(S, [] = T, Cache) -> + {length(S), maps:put({S, T}, length(S), Cache)}; +ld([X|S], [X|T], Cache) -> + ld(S, T, Cache); +ld([_|ST] = S, [_|TT] = T, Cache) -> + try {maps:get({S, T}, Cache), Cache} + catch _:{badkey, _} -> + {L1, C1} = ld(S, TT, Cache), + {L2, C2} = ld(ST, T, C1), + {L3, C3} = ld(ST, TT, C2), + L = 1 + lists:min([L1, L2, L3]), + {L, maps:put({S, T}, L, C3)} + end. + get_version() -> case application:get_env(ejabberd, custom_vsn) of {ok, Vsn0} when is_list(Vsn0) -> |