Fix auto complete module to support new parser API

This commit is contained in:
Daniil Fedotov 2017-01-16 17:56:17 +00:00
parent e9fcb059c2
commit b7fb43fb48
4 changed files with 111 additions and 19 deletions

View File

@ -18,19 +18,25 @@ defmodule Rabbitmq.CLI.AutoComplete do
alias RabbitMQ.CLI.Core.Parser, as: Parser
alias RabbitMQ.CLI.Core.CommandModules, as: CommandModules
@spec complete(String.t) :: {:ok, [String.t]}
@spec complete(String.t) :: [String.t]
def complete(str) do
tokens = String.split(str, " ", trim: true)
case List.last(tokens) do
nil -> [];
last_token ->
{args, opts, _} = Parser.parse(tokens)
CommandModules.load(opts)
variants = case args do
[] -> complete_default_opts(last_token);
[cmd|_] -> complete_command_opts(cmd, last_token)
{command, command_name, _, _, _} = Parser.parse(tokens)
case {command, command_name} do
## No command provided
{_, ""} -> complete_default_opts(last_token);
## Command is not found/incomplete
{:no_command, command_name} ->
complete_command_name(command_name);
{{:suggest, _}, command_name} ->
complete_command_name(command_name);
## Command is found
{command, _} ->
complete_command_opts(command, last_token)
end
variants
# last_token_position = length(tokens) - 1
# Enum.map(variants,
# fn(v) ->
@ -46,21 +52,22 @@ defmodule Rabbitmq.CLI.AutoComplete do
|> Keyword.keys
|> Enum.map(fn(sw) -> "--" <> to_string(sw) end)
|> select_starts_with(opt)
|> format_options
end
def complete_command_opts(cmd, opt) do
commands = CommandModules.module_map
case commands[cmd] do
nil ->
commands
def complete_command_name(command_name) do
module_map = CommandModules.module_map
case module_map[command_name] do
nil ->
module_map
|> Map.keys
|> select_starts_with(opt)
command ->
complete_opts(command, opt)
|> select_starts_with(command_name)
_ ->
command_name
end
end
def complete_opts(command, <<"-", _ :: binary>> = opt) do
def complete_command_opts(command, <<"-", _ :: binary>> = opt) do
switches = command.switches
|> Keyword.keys
|> Enum.map(fn(sw) -> "--" <> to_string(sw) end)
@ -69,12 +76,18 @@ defmodule Rabbitmq.CLI.AutoComplete do
# |> Keyword.keys
# |> Enum.map(fn(al) -> "-" <> to_string(al) end)
select_starts_with(switches, opt)
|> format_options
end
def complete_opts(_, _) do
def complete_command_opts(_, _) do
[]
end
defp select_starts_with(list, prefix) do
Enum.filter(list, fn(el) -> String.starts_with?(el, prefix) end)
end
defp format_options(options) do
options
|> Enum.map(fn(opt) -> String.replace(opt, "_", "-") end)
end
end

View File

@ -21,7 +21,7 @@ defmodule RabbitMQ.CLI.Core.Parser do
# the English language is 5.
@levenshtein_distance_limit 5
@spec parse(String.t) :: {command :: :no_command | atom(),
@spec parse(String.t) :: {command :: :no_command | atom() | {:suggest, String.t()},
command_name :: String.t,
arguments :: [String.t],
options :: Map.t,

View File

@ -64,7 +64,11 @@ defmodule RabbitMQCtl.MixfileBase do
RabbitMQ.CLI.Seagull.Commands.SeagullCommand,
RabbitMQ.CLI.Seagull.Commands.PacificGullCommand,
RabbitMQ.CLI.Seagull.Commands.HerringGullCommand,
RabbitMQ.CLI.Seagull.Commands.HermannGullCommand]
RabbitMQ.CLI.Seagull.Commands.HermannGullCommand,
RabbitMQ.CLI.Wolf.Commands.CanisLupusCommand,
RabbitMQ.CLI.Wolf.Commands.CanisLatransCommand,
RabbitMQ.CLI.Wolf.Commands.CanisAureusCommand
]
[{:modules, mods ++ test_modules |> Enum.sort} | app]
end
defp add_modules(app, _) do

View File

@ -0,0 +1,75 @@
## The contents of this file are subject to the Mozilla Public License
## Version 1.1 (the "License"); you may not use this file except in
## compliance with the License. You may obtain a copy of the License
## at http://www.mozilla.org/MPL/
##
## Software distributed under the License is distributed on an "AS IS"
## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
## the License for the specific language governing rights and
## limitations under the License.
##
## The Original Code is RabbitMQ.
##
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2017 Pivotal Software, Inc. All rights reserved.
defmodule AutoCompleteTest do
use ExUnit.Case, async: false
@subject Rabbitmq.CLI.AutoComplete
test "Auto-completes a command" do
["canis_lupus", "canis_latrans", "canis_aureus"] = @subject.complete("canis")
["canis_lupus", "canis_latrans", "canis_aureus"] = @subject.complete("canis_")
["canis_lupus", "canis_latrans"] = @subject.complete("canis_l")
["canis_latrans"] = @subject.complete("canis_la")
["canis_aureus"] = @subject.complete("canis_a")
["canis_aureus"] = @subject.complete("--node foo --quet canis_a")
end
test "Auto-completes default options if command is not specified" do
["--vhost"] = @subject.complete("--vh")
## Prints script_name as script-name
["--script-name"] = @subject.complete("--script")
["--script-name"] = @subject.complete("--node foo --script")
end
test "Auto-completes the command options if full command is specified" do
["--colour", "--dingo", "--dog"] = @subject.complete("canis_lupus -")
["--colour", "--dingo", "--dog"] = @subject.complete("canis_lupus --")
["--dingo", "--dog"] = @subject.complete("canis_lupus --d")
end
end
defmodule RabbitMQ.CLI.Wolf.Commands.CanisLupusCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def usage(), do: ["canis_lupus"]
def validate(_,_), do: :ok
def merge_defaults(_,_), do: {[], %{}}
def banner(_,_), do: ""
def run(_,_), do: :ok
def switches(), do: [colour: :string, dingo: :boolean, dog: :boolean]
end
defmodule RabbitMQ.CLI.Wolf.Commands.CanisLatransCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def usage(), do: ["canis_latrans"]
def validate(_,_), do: :ok
def merge_defaults(_,_), do: {[], %{}}
def banner(_,_), do: ""
def run(_,_), do: :ok
end
defmodule RabbitMQ.CLI.Wolf.Commands.CanisAureusCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def usage(), do: ["canis_aureus"]
def validate(_,_), do: :ok
def merge_defaults(_,_), do: {[], %{}}
def banner(_,_), do: ""
def run(_,_), do: :ok
end