Class: Passphrase::CLI

Inherits:
Object
  • Object
show all
Defined in:
lib/passphrase/CLI.rb

Overview

The CLI class encapsulates a simple command line interface to the Passphrase library. The class method CLI.parse merges any given command line arguments with a hash of default options. The resulting hash is then used to instantiate a Passphrase object and generate one passphrase, which is printed on standard output.

Examples:

require "passphrase"
Passphrase::CLI.parse(ARGV)

Class Method Summary collapse

Class Method Details

.display_languages(options) ⇒ Object



92
93
94
95
96
97
# File 'lib/passphrase/CLI.rb', line 92

def self.display_languages(options)
  if options[:languages].empty?
    puts WordlistDatabase.connect.from(:languages).all
    exit(0)
  end
end

.handle_error(error) ⇒ Object



111
112
113
114
# File 'lib/passphrase/CLI.rb', line 111

def self.handle_error(error)
  STDERR.puts "ERROR: #{error.message}"
  exit(1)
end

.parse(args) ⇒ void

This method returns an undefined value.

Parameters:

  • args (Array<String>)

    array of command line elements, typically given by ARGV (may be empty)



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
# File 'lib/passphrase/CLI.rb', line 17

def self.parse(args)
  # Gotcha:
  # The contents of an instance variable can be changed outside the class
  # through a reader attribute. For example,
  #   class A
  #     attr_reader :x
  #     def initialize
  #       @x = { a: 1, b: 2 }
  #     end
  #   end
  #   a = A.new
  #   p a.x        #=> {:a=>1, :b=>2}
  #   x = a.x
  #   x[:b] = 99
  #   p a.x        #=> {:a=>1, :b=>99}
  # Therefore, need to clone the default hash otherwise parsing could
  # alter the hash's contents. Although this causes no harm in the
  # command-line tool, it causes havoc in the test suite.
  options = Default.options.clone

  default_number_of_words = Default.options[:number_of_words]
  default_passwordize = Default.options[:passwordize] ? "--passwordize" : "--no-passwordize"
  default_random_org = Default.options[:use_random_org] ? "--random-org" : "--no-random-org"
  default_number_range = Default.number_range

  parser = OptionParser.new(nil, 28, " " * 4) do |opts|
    opts.banner = "Usage: passphrase [options]"
    opts.on(:OPTIONAL, "-l", "--languages=LANG1,...", Array,
      "Specify languages to use, none for a listing",
      "(default: --languages=all)") do |l|
        options[:languages] = (l || [])
    end
    opts.on(:REQUIRED, "-n NUM", "--num-words=NUM", Integer,
      "Number of words in passphrase #{default_number_range}",
      "(default: --num-words=#{default_number_of_words})") do |n|
        options[:number_of_words] = n
    end
    opts.on(:NONE, "-p", "--[no-]passwordize",
      "Add one cap, one num, and one special char",
      "(default: #{default_passwordize})") do |p|
        options[:passwordize] = p
    end
    opts.on(:NONE, "-r", "--[no-]random-org",
      "Use RANDOM.ORG to generate random numbers",
      "(default: #{default_random_org})") do |r|
        options[:use_random_org] = r
    end
    opts.on_tail("-h", "--help", "Show this message") do
      puts opts
      exit(0)
    end
    opts.on_tail("-v", "--version", "Show version") do
      puts VERSION
      exit(0)
    end
  end

  begin
    parser.parse!(args)
    display_languages(options)
    validate_number_of_words(options)
    passphrase = Passphrase.new(options).passphrase
    print_out(passphrase, options)
  rescue OptionParser::InvalidOption => e
    handle_error(e)
  rescue OptionParser::MissingArgument => e
    handle_error(e)
  # Gracefully handle exit(0) from --help, --version, and --language options
  rescue SystemExit => e
    exit(e.status)
  rescue Exception => e
    handle_error(e)
  end
end


106
107
108
109
# File 'lib/passphrase/CLI.rb', line 106

def self.print_out(passphrase, options)
  puts passphrase
  puts passphrase.to_password if options[:passwordize]
end

.validate_number_of_words(options) ⇒ Object



99
100
101
102
103
104
# File 'lib/passphrase/CLI.rb', line 99

def self.validate_number_of_words(options)
  number_of_words = options[:number_of_words]
  unless Default.number_range.include?(number_of_words)
    raise "Number of words out of range #{Default.number_range}"
  end
end