zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

options.ex (5033B)


      1 defmodule Credo.CLI.Options do
      2   @moduledoc """
      3   The `Options` struct represents the options given on the command line.
      4 
      5   The `Options` struct is stored as part of the `Execution` struct.
      6   """
      7 
      8   alias Credo.Priority
      9 
     10   defstruct command: nil,
     11             path: nil,
     12             args: [],
     13             switches: nil,
     14             unknown_switches: [],
     15             unknown_args: []
     16 
     17   @deprecated "Options.parse/7 is deprecated, use Options.parse/8 instead"
     18   def parse(
     19         argv,
     20         current_dir,
     21         command_names,
     22         given_command_name,
     23         ignored_args,
     24         switches_definition,
     25         aliases
     26       ) do
     27     parse(
     28       true,
     29       argv,
     30       current_dir,
     31       command_names,
     32       given_command_name,
     33       ignored_args,
     34       switches_definition,
     35       aliases
     36     )
     37   end
     38 
     39   @doc """
     40   Returns a `Options` struct for the given parameters.
     41   """
     42   def parse(
     43         true = _use_strict_parser?,
     44         argv,
     45         current_dir,
     46         command_names,
     47         given_command_name,
     48         ignored_args,
     49         switches_definition,
     50         aliases
     51       ) do
     52     argv
     53     |> OptionParser.parse(strict: switches_definition, aliases: aliases)
     54     |> parse_result(
     55       current_dir,
     56       command_names,
     57       given_command_name,
     58       ignored_args,
     59       switches_definition
     60     )
     61   end
     62 
     63   def parse(
     64         false = _use_strict_parser?,
     65         argv,
     66         current_dir,
     67         command_names,
     68         given_command_name,
     69         ignored_args,
     70         switches_definition,
     71         aliases
     72       ) do
     73     argv
     74     |> OptionParser.parse(switches: switches_definition, aliases: aliases)
     75     |> parse_result(
     76       current_dir,
     77       command_names,
     78       given_command_name,
     79       ignored_args,
     80       []
     81     )
     82   end
     83 
     84   defp parse_result(
     85          {switches_keywords, args, unknown_switches_keywords},
     86          current_dir,
     87          command_names,
     88          given_command_name,
     89          ignored_args,
     90          switches_definition
     91        ) do
     92     args = Enum.reject(args, &Enum.member?(ignored_args, &1))
     93 
     94     {command, path, unknown_args} =
     95       split_args(args, current_dir, command_names, switches_keywords[:working_dir])
     96 
     97     {switches_keywords, extra_unknown_switches} = patch_switches(switches_keywords)
     98 
     99     switch_definitions_for_lists =
    100       Enum.filter(switches_definition, fn
    101         {_name, :keep} -> true
    102         {_name, [_, :keep]} -> true
    103         {_name, _value} -> false
    104       end)
    105 
    106     switches_with_lists_as_map =
    107       switch_definitions_for_lists
    108       |> Enum.map(fn {name, _value} ->
    109         {name, Keyword.get_values(switches_keywords, name)}
    110       end)
    111       |> Enum.into(%{})
    112 
    113     switches =
    114       switches_keywords
    115       |> Enum.into(%{})
    116       |> Map.merge(switches_with_lists_as_map)
    117 
    118     {path, switches} =
    119       if File.dir?(path) do
    120         {path, switches}
    121       else
    122         {current_dir, Map.put(switches, :files_included, [path])}
    123       end
    124 
    125     %__MODULE__{
    126       command: command || given_command_name,
    127       path: path,
    128       args: unknown_args,
    129       switches: switches,
    130       unknown_switches: unknown_switches_keywords ++ extra_unknown_switches
    131     }
    132   end
    133 
    134   defp patch_switches(switches_keywords) do
    135     {switches, unknowns} = Enum.map_reduce(switches_keywords, [], &patch_switch/2)
    136     switches = Enum.reject(switches, &(&1 == nil))
    137     {switches, unknowns}
    138   end
    139 
    140   defp patch_switch({:min_priority, str}, unknowns) do
    141     priority = priority_as_name(str) || priority_as_number(str)
    142 
    143     case priority do
    144       nil -> {nil, [{"--min-priority", str} | unknowns]}
    145       int -> {{:min_priority, int}, unknowns}
    146     end
    147   end
    148 
    149   defp patch_switch(switch, unknowns), do: {switch, unknowns}
    150 
    151   defp priority_as_name(str), do: Priority.to_integer(str)
    152 
    153   defp priority_as_number(str) do
    154     case Integer.parse(str) do
    155       {int, ""} -> int
    156       _ -> nil
    157     end
    158   end
    159 
    160   defp split_args([], current_dir, _, nil) do
    161     {path, unknown_args} = extract_path([], current_dir)
    162 
    163     {nil, path, unknown_args}
    164   end
    165 
    166   defp split_args([], _current_dir, _, given_working_dir) do
    167     {nil, given_working_dir, []}
    168   end
    169 
    170   defp split_args([head | tail] = args, current_dir, command_names, nil) do
    171     if Enum.member?(command_names, head) do
    172       {path, unknown_args} = extract_path(tail, current_dir)
    173 
    174       {head, path, unknown_args}
    175     else
    176       {path, unknown_args} = extract_path(args, current_dir)
    177 
    178       {nil, path, unknown_args}
    179     end
    180   end
    181 
    182   defp split_args([head | tail] = args, _current_dir, command_names, given_working_dir) do
    183     if Enum.member?(command_names, head) do
    184       {head, given_working_dir, tail}
    185     else
    186       {nil, given_working_dir, args}
    187     end
    188   end
    189 
    190   defp extract_path([], base_dir) do
    191     {base_dir, []}
    192   end
    193 
    194   defp extract_path([path | tail] = args, base_dir) do
    195     if File.exists?(path) or path =~ ~r/[\?\*]/ do
    196       {path, tail}
    197     else
    198       path_with_base = Path.join(base_dir, path)
    199 
    200       if File.exists?(path_with_base) do
    201         {path_with_base, tail}
    202       else
    203         {base_dir, args}
    204       end
    205     end
    206   end
    207 end