rabbitmq-server/deps/rabbitmq_cli/lib/rabbitmq/cli/auto_complete.ex

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

121 lines
3.0 KiB
Elixir
Raw Normal View History

## This Source Code Form is subject to the terms of the Mozilla Public
## License, v. 2.0. If a copy of the MPL was not distributed with this
## file, You can obtain one at https://mozilla.org/MPL/2.0/.
2016-07-29 00:46:37 +08:00
##
## Copyright (c) 2007-2025 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
2016-07-29 00:46:37 +08:00
defmodule RabbitMQ.CLI.AutoComplete do
2018-07-23 13:06:18 +08:00
alias RabbitMQ.CLI.Core.{CommandModules, Parser}
2016-07-29 00:46:37 +08:00
# Use the same jaro distance limit as in Elixir's "did you mean?"
@jaro_distance_limit 0.77
2019-01-31 03:20:29 +08:00
@spec complete(String.t(), [String.t()]) :: [String.t()]
def complete(_, []) do
[]
end
2019-01-31 03:20:29 +08:00
def complete(script_name, args) do
case Parser.parse_global(args) do
{_, %{script_name: _args_script_name}, _} ->
2019-01-31 03:20:29 +08:00
complete(args)
_ ->
complete(["--script-name", script_name | args])
2016-07-29 00:46:37 +08:00
end
end
def suggest_command(_cmd_name, empty) when empty == %{} do
nil
end
2022-10-03 01:54:11 +08:00
def suggest_command(typed, module_map) do
suggestion =
module_map
|> Map.keys()
|> Enum.map(fn existing ->
{existing, String.jaro_distance(existing, typed)}
end)
|> Enum.max_by(fn {_, distance} -> distance end)
case suggestion do
{cmd, distance} when distance >= @jaro_distance_limit ->
{:suggest, cmd}
2022-10-03 01:54:11 +08:00
_ ->
nil
end
end
defp complete(tokens) do
{command, command_name, _, _, _} = Parser.parse(tokens)
last_token = List.last(tokens)
2019-01-31 03:20:29 +08:00
case {command, command_name} do
## No command provided
2019-01-31 03:20:29 +08:00
{_, ""} ->
complete_default_opts(last_token)
## Command is not found/incomplete
{:no_command, command_name} ->
2019-01-31 03:20:29 +08:00
complete_command_name(command_name)
{{:suggest, _}, command_name} ->
2019-01-31 03:20:29 +08:00
complete_command_name(command_name)
## Command is found
{command, _} ->
complete_command_opts(command, last_token)
end
2019-01-31 03:20:29 +08:00
|> Enum.sort()
end
defp complete_default_opts(opt) do
2019-01-31 03:20:29 +08:00
Parser.default_switches()
|> Keyword.keys()
|> Enum.map(fn sw -> "--" <> to_string(sw) end)
2016-07-29 00:46:37 +08:00
|> select_starts_with(opt)
|> format_options
2016-07-29 00:46:37 +08:00
end
defp complete_command_name(command_name) do
2019-01-31 03:20:29 +08:00
module_map = CommandModules.module_map()
case module_map[command_name] do
nil ->
module_map
2019-01-31 03:20:29 +08:00
|> Map.keys()
|> select_starts_with(command_name)
2019-01-31 03:20:29 +08:00
_ ->
command_name
2016-07-29 00:46:37 +08:00
end
end
2019-01-31 03:20:29 +08:00
defp complete_command_opts(command, <<"-", _::binary>> = opt) do
switches =
2024-12-05 00:07:34 +08:00
command.switches()
2019-01-31 03:20:29 +08:00
|> Keyword.keys()
|> Enum.map(fn sw -> "--" <> to_string(sw) end)
2016-07-29 00:46:37 +08:00
# aliases = command.aliases
# |> Keyword.keys
# |> Enum.map(fn(al) -> "-" <> to_string(al) end)
select_starts_with(switches, opt)
|> format_options
2016-07-29 00:46:37 +08:00
end
2019-01-31 03:20:29 +08:00
defp complete_command_opts(_, _) do
2016-07-29 00:46:37 +08:00
[]
end
defp select_starts_with(list, prefix) do
2019-01-31 03:20:29 +08:00
Enum.filter(list, fn el -> String.starts_with?(el, prefix) end)
2016-07-29 00:46:37 +08:00
end
defp format_options(options) do
options
2019-01-31 03:20:29 +08:00
|> Enum.map(fn opt -> String.replace(opt, "_", "-") end)
end
2017-01-10 22:42:40 +08:00
end