Class: CLAide::Command::ArgumentSuggester

Inherits:
Object
  • Object
show all
Defined in:
lib/claide/command/argument_suggester.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(argument, command_class) ⇒ ArgumentSuggester

Returns a new instance of ArgumentSuggester.

Parameters:

  • argument (String)

    The unrecognized argument for which to make a suggestion.

  • command_class (Class)

    The class of the command which encountered the unrecognized arguments.



13
14
15
16
# File 'lib/claide/command/argument_suggester.rb', line 13

def initialize(argument, command_class)
  @argument, @command_class = argument, command_class
  @argument_type = ARGV::Parser.argument_type(@argument)
end

Class Method Details

.levenshtein_distance(a, b) ⇒ Fixnum

Returns the Levenshtein distance between the given strings. From: http://rosettacode.org/wiki/Levenshtein_distance#Ruby

Parameters:

  • a (String)

    The first string to compare.

  • b (String)

    The second string to compare.

Returns:

  • (Fixnum)

    The distance between the strings.



84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/claide/command/argument_suggester.rb', line 84

def self.levenshtein_distance(a, b)
  a, b = a.downcase, b.downcase
  costs = Array(0..b.length)
  (1..a.length).each do |i|
    costs[0], nw = i, i - 1
    (1..b.length).each do |j|
      costs[j], nw = [
        costs[j] + 1, costs[j - 1] + 1, a[i - 1] == b[j - 1] ? nw : nw + 1
      ].min, costs[j]
    end
  end
  costs[b.length]
end

.prettify_suggestion(suggestion, argument_type) ⇒ String

Prettifies the given validation suggestion according to the type.

Parameters:

  • suggestion (String)

    The suggestion to prettify.

  • argument_type (Type)

    The type of the suggestion: either :command or :option.

Returns:

  • (String)

    A handsome suggestion.



64
65
66
67
68
69
70
71
72
# File 'lib/claide/command/argument_suggester.rb', line 64

def self.prettify_suggestion(suggestion, argument_type)
  case argument_type
  when :option, :flag
    suggestion = suggestion.to_s
    suggestion.ansi.blue
  when :arg
    suggestion.ansi.green
  end
end

Instance Method Details

#possibilitiesArray<String>

Returns The list of the valid arguments for a command according to the type of the argument.

Returns:

  • (Array<String>)

    The list of the valid arguments for a command according to the type of the argument.



21
22
23
24
25
26
27
28
# File 'lib/claide/command/argument_suggester.rb', line 21

def possibilities
  case @argument_type
  when :option, :flag
    @command_class.options.map(&:first)
  when :arg
    @command_class.subcommands_for_command_lookup.map(&:command)
  end
end

#suggested_argumentString

Returns a suggested argument from possibilities based on the levenshtein_distance score.

Returns:

  • (String)

    Returns a suggested argument from possibilities based on the levenshtein_distance score.



33
34
35
36
37
# File 'lib/claide/command/argument_suggester.rb', line 33

def suggested_argument
  possibilities.sort_by do |element|
    self.class.levenshtein_distance(@argument, element)
  end.first
end

#suggestionString

Returns a message including a suggestion for the given suggestion.

Returns:

  • (String)

    Returns a message including a suggestion for the given suggestion.



42
43
44
45
46
47
48
49
50
51
52
# File 'lib/claide/command/argument_suggester.rb', line 42

def suggestion
  argument_description = @argument_type == :arg ? 'command' : 'option'
  if suggestion = suggested_argument
    pretty_suggestion = self.class.prettify_suggestion(suggestion,
                                                       @argument_type)
    "Unknown #{argument_description}: `#{@argument}`\n" \
      "Did you mean: #{pretty_suggestion}?"
  else
    "Unknown #{argument_description}: `#{@argument}`"
  end
end