diff options
author | Evgeny Khramtsov <ekhramtsov@process-one.net> | 2019-04-30 09:36:38 +0300 |
---|---|---|
committer | Evgeny Khramtsov <ekhramtsov@process-one.net> | 2019-04-30 09:36:38 +0300 |
commit | 4af99f7b03ce44193192f75c492b9e28e99e2600 (patch) | |
tree | 993fb3d790fb069179f154ecd429ad1d7d1eecfe /src | |
parent | Provide a suggestion when unknown module is detected (diff) |
Rename ejabberd_config:similar_option/2 -> misc:best_match/2
Diffstat (limited to 'src')
-rw-r--r-- | src/ejabberd_config.erl | 32 | ||||
-rw-r--r-- | src/gen_mod.erl | 4 | ||||
-rw-r--r-- | src/misc.erl | 32 |
3 files changed, 35 insertions, 33 deletions
diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 40d157a8..f4abf8d5 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -39,7 +39,7 @@ 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, - similar_option/2, get_modules/0]). + get_modules/0]). -export([start/2]). @@ -1102,7 +1102,7 @@ validate_opts(#state{opts = Opts} = State, ModOpts) -> _ -> KnownOpts = dict:fetch_keys(ModOpts), ?ERROR_MSG("Unknown option '~s', did you mean '~s'?", - [Opt, similar_option(Opt, KnownOpts)]), + [Opt, misc:best_match(Opt, KnownOpts)]), erlang:error(unknown_option) end end, Opts), @@ -1126,34 +1126,6 @@ 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) -> diff --git a/src/gen_mod.erl b/src/gen_mod.erl index eb433de5..b972285f 100644 --- a/src/gen_mod.erl +++ b/src/gen_mod.erl @@ -585,7 +585,7 @@ validate_opts(Host, Module, Opts0) -> " did you mean '~s'?" " Available options are: ~s", [Opt, Module, - ejabberd_config:similar_option(Opt, KnownOpts), + misc:best_match(Opt, KnownOpts), misc:join_atoms(KnownOpts, <<", ">>)]), module_error(ErrTxt) end. @@ -746,7 +746,7 @@ format_module_error(Module, Fun, Arity, Opts, Class, Reason, St) -> "exists inside either ~s or ~s " "directory", [Fun, Module, - ejabberd_config:similar_option( + misc:best_match( Module, ejabberd_config:get_modules()), Module, filename:dirname(code:which(?MODULE)), diff --git a/src/misc.erl b/src/misc.erl index 73d05ff2..4f683a43 100644 --- a/src/misc.erl +++ b/src/misc.erl @@ -39,7 +39,7 @@ css_dir/0, img_dir/0, js_dir/0, msgs_dir/0, sql_dir/0, lua_dir/0, read_css/1, read_img/1, read_js/1, read_lua/1, try_url/1, intersection/2, format_val/1, cancel_timer/1, unique_timestamp/0, - is_mucsub_message/1]). + is_mucsub_message/1, best_match/2]). %% Deprecated functions -export([decode_base64/1, encode_base64/1]). @@ -425,6 +425,18 @@ cancel_timer(TRef) when is_reference(TRef) -> cancel_timer(_) -> ok. +-spec best_match(atom(), [atom()]) -> atom(). +best_match(Pattern, []) -> + Pattern; +best_match(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)). + %%%=================================================================== %%% Internal functions %%%=================================================================== @@ -485,3 +497,21 @@ get_dir(Type) -> unique_timestamp() -> {MS, S, _} = erlang:timestamp(), {MS, S, erlang:unique_integer([positive, monotonic]) rem 1000000}. + +%% 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. |