output.ex (5490B)
1 defmodule Credo.CLI.Output do 2 @moduledoc """ 3 This module provides helper functions regarding command line output. 4 """ 5 6 @category_tag_map %{"refactor" => "F"} 7 8 alias Credo.CLI.Output.UI 9 alias Credo.Execution 10 alias Credo.Priority 11 12 def check_tag(category, in_parens \\ true) 13 14 def check_tag(category, in_parens) when is_binary(category) do 15 default_tag = 16 category 17 |> String.at(0) 18 |> String.upcase() 19 20 tag = Map.get(@category_tag_map, category, default_tag) 21 22 if in_parens do 23 "[#{tag}]" 24 else 25 tag 26 end 27 end 28 29 def check_tag(category, in_parens) when is_atom(category) do 30 category 31 |> to_string 32 |> check_tag(in_parens) 33 end 34 35 def check_tag(check_mod, in_parens) do 36 check_mod.category 37 |> to_string 38 |> check_tag(in_parens) 39 end 40 41 def check_color(category) when is_binary(category) do 42 case category do 43 "consistency" -> :cyan 44 "readability" -> :blue 45 "design" -> :olive 46 "refactor" -> :yellow 47 "warning" -> :red 48 _ -> :magenta 49 end 50 end 51 52 def check_color(category) when is_atom(category) do 53 category 54 |> to_string 55 |> check_color 56 end 57 58 def check_color(check_mod) do 59 check_mod.category 60 |> to_string 61 |> check_color 62 end 63 64 @doc """ 65 Returns a suitable color for a given priority. 66 67 iex> Credo.CLI.Output.issue_color(%Credo.Issue{priority: :higher}) 68 :red 69 70 iex> Credo.CLI.Output.issue_color(%Credo.Issue{priority: 20}) 71 :red 72 73 """ 74 def issue_color(issue_or_priority) do 75 case Priority.to_atom(issue_or_priority) do 76 :higher -> :red 77 :high -> :red 78 :normal -> :yellow 79 :low -> :blue 80 :ignore -> :magenta 81 _ -> "?" 82 end 83 end 84 85 @doc """ 86 Returns a suitable arrow for a given priority. 87 88 iex> Credo.CLI.Output.priority_arrow(:high) 89 "↗" 90 91 iex> Credo.CLI.Output.priority_arrow(10) 92 "↗" 93 94 iex> Credo.CLI.Output.priority_arrow(%Credo.Issue{priority: 10}) 95 "↗" 96 """ 97 def priority_arrow(issue_or_priority) do 98 case Priority.to_atom(issue_or_priority) do 99 :higher -> "\u2191" 100 :high -> "\u2197" 101 :normal -> "\u2192" 102 :low -> "\u2198" 103 :ignore -> "\u2193" 104 _ -> "?" 105 end 106 end 107 108 @doc """ 109 Returns a suitable name for a given priority. 110 111 iex> Credo.CLI.Output.priority_name(:normal) 112 "normal" 113 114 iex> Credo.CLI.Output.priority_name(1) 115 "normal" 116 117 iex> Credo.CLI.Output.priority_name(%Credo.Issue{priority: 1}) 118 "normal" 119 120 """ 121 def priority_name(issue_or_priority) do 122 case Priority.to_atom(issue_or_priority) do 123 :higher -> "higher" 124 :high -> "high" 125 :normal -> "normal" 126 :low -> "low" 127 :ignore -> "ignore" 128 _ -> "?" 129 end 130 end 131 132 @doc """ 133 Returns a suitable foreground color for a given `background_color`. 134 135 iex> Credo.CLI.Output.foreground_color(:yellow) 136 :black 137 138 iex> Credo.CLI.Output.foreground_color(:blue) 139 :white 140 141 """ 142 def foreground_color(background_color) 143 144 def foreground_color(:cyan), do: :black 145 def foreground_color(:yellow), do: :black 146 def foreground_color(_), do: :white 147 148 def term_columns(default \\ 80) do 149 case :io.columns() do 150 {:ok, columns} -> 151 columns 152 153 _ -> 154 default 155 end 156 end 157 158 def complain_about_invalid_source_files([]), do: nil 159 160 def complain_about_invalid_source_files(invalid_source_files) do 161 invalid_source_filenames = Enum.map(invalid_source_files, & &1.filename) 162 163 output = [ 164 :reset, 165 :bright, 166 :orange, 167 "info: ", 168 :red, 169 "Some source files could not be parsed correctly and are excluded:\n" 170 ] 171 172 UI.warn(output) 173 174 print_numbered_list(invalid_source_filenames) 175 end 176 177 def complain_about_timed_out_source_files([]), do: nil 178 179 def complain_about_timed_out_source_files(large_source_files) do 180 large_source_filenames = Enum.map(large_source_files, & &1.filename) 181 182 output = [ 183 :reset, 184 :bright, 185 :orange, 186 "info: ", 187 :red, 188 "Some source files were not parsed in the time allotted:\n" 189 ] 190 191 UI.warn(output) 192 193 print_numbered_list(large_source_filenames) 194 end 195 196 def print_skipped_checks(%Execution{skipped_checks: []}), do: nil 197 198 def print_skipped_checks(%Execution{skipped_checks: skipped_checks}) do 199 msg = [ 200 :reset, 201 :bright, 202 :orange, 203 "info: ", 204 :reset, 205 :faint, 206 "some checks were skipped because they're not compatible with\n", 207 :reset, 208 :faint, 209 "your version of Elixir (#{System.version()}).\n\n", 210 "You can deactivate these checks by adding this to the `checks` list in your config:\n" 211 ] 212 213 UI.puts("") 214 UI.puts(msg) 215 216 skipped_checks 217 |> Enum.map(&check_name/1) 218 |> print_disabled_check_config 219 end 220 221 defp check_name({check, _check_info}), do: check_name({check}) 222 223 defp check_name({check}) do 224 check 225 |> to_string 226 |> String.replace(~r/^Elixir\./, "") 227 end 228 229 defp print_numbered_list(list) do 230 list 231 |> Enum.with_index() 232 |> Enum.flat_map(fn {string, index} -> 233 [ 234 :reset, 235 String.pad_leading("#{index + 1})", 5), 236 :faint, 237 " #{string}\n" 238 ] 239 end) 240 |> UI.warn() 241 end 242 243 defp print_disabled_check_config(list) do 244 list 245 |> Enum.flat_map(fn string -> 246 [ 247 :reset, 248 String.pad_leading(" ", 4), 249 :faint, 250 "{#{string}, false},\n" 251 ] 252 end) 253 |> UI.puts() 254 end 255 end