Packages
fnord
0.6.4
0.9.40
0.9.39
0.9.38
0.9.37
0.9.36
0.9.35
0.9.34
0.9.33
0.9.32
0.9.31
0.9.30
0.9.29
0.9.28
0.9.27
0.9.26
0.9.25
0.9.24
0.9.23
0.9.22
0.9.21
0.9.20
0.9.19
0.9.18
0.9.17
0.9.16
0.9.15
0.9.14
0.9.13
0.9.12
0.9.11
0.9.10
0.9.9
0.9.8
0.9.7
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.99
0.8.98
0.8.97
0.8.96
0.8.95
0.8.94
0.8.93
0.8.92
0.8.91
0.8.90
0.8.89
0.8.88
0.8.87
0.8.86
0.8.85
0.8.84
0.8.83
0.8.82
0.8.81
0.8.80
0.8.79
0.8.78
0.8.77
0.8.76
0.8.75
0.8.74
0.8.73
0.8.72
0.8.71
0.8.70
0.8.69
0.8.68
0.8.67
0.8.66
0.8.65
0.8.64
0.8.63
0.8.62
0.8.61
0.8.60
0.8.59
0.8.58
0.8.57
0.8.56
0.8.55
0.8.54
0.8.53
0.8.52
0.8.51
0.8.50
0.8.49
0.8.48
0.8.47
0.8.46
0.8.45
0.8.44
0.8.43
0.8.42
0.8.41
0.8.40
0.8.39
0.8.38
0.8.37
0.8.36
0.8.35
0.8.34
0.8.33
0.8.32
0.8.31
0.8.30
0.8.29
0.8.27
0.8.26
0.8.25
0.8.24
0.8.23
0.8.22
0.8.21
0.8.20
0.8.19
0.8.18
0.8.17
0.8.16
0.8.15
0.8.14
0.8.13
0.8.12
0.8.11
0.8.1
0.8.0
0.7.24
0.7.23
0.7.22
0.7.21
0.7.20
0.7.19
0.7.18
0.7.17
0.7.16
0.7.15
0.7.14
0.7.13
0.7.12
0.7.11
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.3
0.7.2
0.7.1
0.7.0
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.1
0.6.0
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.44
0.4.43
0.4.42
0.4.41
0.4.40
0.4.39
0.4.38
0.4.37
0.4.36
0.4.35
0.4.34
0.4.33
0.4.32
0.4.30
0.4.29
0.4.28
0.4.27
0.4.26
0.4.25
0.4.24
0.4.23
0.4.22
0.4.21
0.4.20
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
AI code archaeology
Current section
Files
Jump to
Current section
Files
lib/shell/from_optimus.ex
defmodule Shell.FromOptimus do
@moduledoc """
Converts an Optimus spec into the `Shell.Completion` DSL format.
The Optimus spec is assumed to be a keyword list with keys such as:
- :name (required)
- :about or :description (for the description)
- :options and :flags (each a keyword list)
- :subcommands (a keyword list where each value is a subcommand spec)
- Optionally :arguments
The conversion ignores keys like :version, :help, :required, :default, etc.
It uses the long flag (if available) as the canonical option name.
For flags, it sets `takes_argument: false`.
"""
@spec convert(Keyword.t()) :: map()
def convert(opt_spec) when is_list(opt_spec) do
convert_spec(opt_spec)
end
@doc false
@spec convert_spec(Keyword.t()) :: map()
defp convert_spec(opt_spec) when is_list(opt_spec) do
name = Keyword.fetch!(opt_spec, :name)
description =
Keyword.get(opt_spec, :about) ||
Keyword.get(opt_spec, :description) ||
""
# Convert options (which expect a value) and flags (which are boolean switches)
options = convert_options(Keyword.get(opt_spec, :options, []))
flags = convert_flags(Keyword.get(opt_spec, :flags, []))
all_options = options ++ flags
# Convert subcommands (assumed to be a keyword list)
subcommands_kw = Keyword.get(opt_spec, :subcommands, [])
subcommands =
case subcommands_kw do
list when is_list(list) ->
Enum.map(list, fn {_, sub_spec} ->
convert_spec(sub_spec)
end)
_ ->
[]
end
# Convert arguments if provided; otherwise, an empty list.
arguments_kw = Keyword.get(opt_spec, :arguments, [])
arguments =
case arguments_kw do
list when is_list(list) ->
Enum.map(list, &convert_argument/1)
_ ->
[]
end
%{
name: name,
description: description,
subcommands: subcommands,
options: all_options,
arguments: arguments
}
end
defp convert_spec(opt_spec) when is_map(opt_spec) do
opt_spec |> Map.to_list() |> convert_spec()
end
@spec convert_options(Keyword.t()) :: [map()]
defp convert_options(options_kw) when is_list(options_kw) do
Enum.map(options_kw, fn {key, spec} ->
long = Keyword.get(spec, :long, "--" <> Atom.to_string(key))
# For our DSL, an option is assumed to take an argument (unless overridden by flags)
%{name: long}
end)
end
@spec convert_flags(Keyword.t()) :: [map()]
defp convert_flags(flags_kw) when is_list(flags_kw) do
Enum.map(flags_kw, fn {key, spec} ->
long = Keyword.get(spec, :long, "--" <> Atom.to_string(key))
# For flags, explicitly mark that they do not take an argument.
%{name: long, takes_argument: false}
end)
end
@spec convert_argument(Keyword.t()) :: map()
defp convert_argument(arg_spec) when is_list(arg_spec) do
# For an argument we use the provided :value_name (if any) as the argument name.
value_name = Keyword.get(arg_spec, :value_name, "arg")
# If the Optimus spec provided any information on how to complete it (via :from),
# you could map that here. Otherwise, we'll leave it out.
from = Keyword.get(arg_spec, :from)
arg_map = %{name: value_name}
if from, do: Map.put(arg_map, :from, from), else: arg_map
end
defp convert_argument(arg_spec) when is_map(arg_spec) do
arg_spec |> Map.to_list() |> convert_argument()
end
end