Class: IO::Nosey::Parker

Inherits:
Object
  • Object
show all
Defined in:
lib/io/nosey/parker.rb

Defined Under Namespace

Classes: Error, InvalidInputError

Constant Summary collapse

AskOpts =
OptionalArgument.define {
  opt(:input, condition: Regexp)
  opt(:parse, aliases: [:parser], condition: ->v { Parker.adjustable?(v) })
  opt(:return, condition: ->v { Eqq.pattern?(v) })
  opt(:default, condition: CAN(:to_str))
  opt(:echo, condition: BOOLEAN(), default: true)
  opt(:error, condition: CAN(:to_str), default: 'Your answer is invalid.')
  opt(:multi_line, condition: BOOLEAN(), default: false)
}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(input: $stdin, output: $stdout) ⇒ Parker

Returns a new instance of Parker.

Parameters:

  • input (IO, StringIO) (defaults to: $stdin)
  • output (IO, StringIO) (defaults to: $stdout)


25
26
27
# File 'lib/io/nosey/parker.rb', line 25

def initialize(input: $stdin, output: $stdout)
  @input, @output = input, output
end

Class Method Details

.adjustable?(object) ⇒ Boolean

Returns:

  • (Boolean)


10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/io/nosey/parker.rb', line 10

def self.adjustable?(object)
  case object
  when Proc
    object.arity == 1
  else
    if object.respond_to?(:to_proc)
      object.to_proc.arity == 1
    else
      false
    end
  end
end

Instance Method Details

#agree?(prompt) ⇒ Boolean

Parameters:

  • prompt (String)

Returns:

  • (Boolean)


88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/io/nosey/parker.rb', line 88

def agree?(prompt)
  @output.print("#{prompt} [y or n]")

  input = @input.getch
  @output.print("\n")

  case input
  when 'n', 'N'
    false
  when 'y', 'Y'
    true
  else
    raise InvalidInputError
  end
rescue InvalidInputError
  retry
end

#ask(prompt, **kw_args) ⇒ Object

Parameters:

  • prompt (String)


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
# File 'lib/io/nosey/parker.rb', line 40

def ask(prompt, **kw_args)
  opts = AskOpts.parse(kw_args)

  @output.print(prompt)

  if opts.default?
    @output.print("(default: #{opts.default})")
  end

  if opts.multi_line
    if opts.echo
      input = @input.read
    else
      input = @input.noecho(&:read)
      @output.puts
    end
  else
    if opts.echo
      input = @input.gets.chomp
    else
      input = @input.noecho(&:gets).chomp
      @output.puts
    end
  end

  if input.empty? && opts.default?
    input = opts.default
  end

  if opts.input? && !valid?(opts.input, input)
    raise InvalidInputError, opts.error
  end

  if opts.parse?
    input = opts.parse.call(input)
  end

  if opts.return? && !valid?(opts.return, input)
    raise InvalidInputError, opts.error
  end

  input
rescue InvalidInputError
  @output.puts $!.message unless $!.message.empty?
  retry
end

#choose(prompt, choices) ⇒ Object

Returns a member of choices.

Parameters:

  • prompt (String)
  • choices (Hash{Object => String})

    key: value, value: description

Returns:

  • a member of choices

Raises:

  • (ArgumentError)


109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/io/nosey/parker.rb', line 109

def choose(prompt, choices)
  raise ArgumentError if choices.empty?

  @output.puts prompt
  @output.puts [:index, :value, :description].join("\t")

  pairs = {}
  index = 1
  choices.each_pair do |value, description|
    @output.puts [index, value, description].join("\t")
    pairs[index] = value
    index += 1
  end

  number = ask('Select index:',
               input: /\A(\d+)\z/,
               parse: ->v { Integer(v) },
               return: Eqq.AND(Integer, 1..(index - 1)))

  pairs[number]
end