-
Notifications
You must be signed in to change notification settings - Fork 414
/
command.ex
159 lines (126 loc) · 3.75 KB
/
command.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
defmodule Credo.CLI.Command do
@moduledoc """
`Command` is used to describe commands which can be executed from the command line.
The default command is `Credo.CLI.Command.Suggest.SuggestCommand`.
A basic command that writes "Hello World" can be implemented like this:
defmodule HelloWorldCommand do
use Credo.CLI.Command
alias Credo.CLI.Output.UI
def call(_exec, _opts) do
UI.puts([:yellow, "Hello ", :orange, "World"])
end
end
"""
@typedoc false
@type t :: module
@doc """
Is called when a Command is invoked.
defmodule FooTask do
use Credo.Execution.Task
def call(exec) do
IO.inspect(exec)
end
end
The `call/1` functions receives an `exec` struct and must return a (modified) `Credo.Execution`.
"""
@callback call(exec :: Credo.Execution.t()) :: Credo.Execution.t()
@doc """
Is called when a Command is initialized.
The `init/1` functions receives an `exec` struct and must return a (modified) `Credo.Execution`.
This can be used to initialize Execution pipelines for the current Command:
defmodule FooTask do
use Credo.Execution.Task
def init(exec) do
Execution.put_pipeline(exec, __MODULE__,
run_my_thing: [
{RunMySpecialThing, []}
],
filter_results: [
{FilterResults, []}
],
print_results: [
{PrintResultsAndSummary, []}
]
)
end
end
"""
@callback init(exec :: Credo.Execution.t()) :: Credo.Execution.t()
@valid_use_opts [
:short_description,
:cli_switches
]
@doc false
defmacro __using__(opts \\ []) do
Enum.each(opts, fn
{key, _name} when key not in @valid_use_opts ->
raise "Could not find key `#{key}` in #{inspect(@valid_use_opts)}"
_ ->
nil
end)
def_short_description =
if opts[:short_description] do
quote do
@impl true
def short_description, do: unquote(opts[:short_description])
end
end
def_cli_switches =
quote do
@impl true
def cli_switches do
unquote(opts[:cli_switches])
|> List.wrap()
|> Enum.map(&Credo.CLI.Switch.ensure/1)
end
end
quote do
@before_compile Credo.CLI.Command
@behaviour Credo.CLI.Command
unquote(def_short_description)
unquote(def_cli_switches)
@deprecated "Use Credo.Execution.Task.run/2 instead"
defp run_task(exec, task), do: Credo.Execution.Task.run(task, exec)
@doc false
@impl true
def init(exec), do: exec
@doc false
@impl true
def call(exec), do: exec
defoverridable init: 1
defoverridable call: 1
end
end
@doc false
defmacro __before_compile__(env) do
quote do
unquote(deprecated_def_short_description(env))
end
end
defp deprecated_def_short_description(env) do
shortdoc = Module.get_attribute(env.module, :shortdoc)
if is_nil(shortdoc) do
if not Module.defines?(env.module, {:short_description, 0}) do
quote do
@impl true
def short_description, do: nil
end
end
else
# deprecated - remove once we ditch @shortdoc
if not Module.defines?(env.module, {:short_description, 0}) do
quote do
@impl true
def short_description do
@shortdoc
end
end
end
end
end
@doc "Runs the Command"
@callback call(exec :: Credo.Execution.t(), opts :: list()) :: Credo.Execution.t()
@doc "Returns a short, one-line description of what the command does"
@callback short_description() :: String.t()
@callback cli_switches() :: [Map.t()]
end