Class: Annoy
- Inherits:
-
Object
- Object
- Annoy
- Defined in:
- lib/annoy.rb
Overview
Annoy
Like your annoying friend that asks you questions all the time.
Rudy uses Annoy to present the user with a simple question before continuing with a destructive action.
Defined Under Namespace
Classes: GiveUp
Constant Summary collapse
- @@operators =
{ :low => %w(+ -), :medium => %w(* -), :high => %w(& * -), :insane => %w(** << | & *) }.freeze
- @@strlen =
{ :low => 2, :medium => 3, :high => 4, :insane => 32 }.freeze
- @@randsize =
{ :low => 10, :medium => 12, :high => 50, :insane => 1000 }.freeze
- @@period =
max seconds to wait
3600.freeze
- @@flavors =
[:numeric, :string].freeze
- @@skip =
skip questions
false
Instance Attribute Summary collapse
-
#answer ⇒ Object
Returns the value of attribute answer.
-
#factor ⇒ Object
Returns the value of attribute factor.
-
#flavor ⇒ Object
Returns the value of attribute flavor.
-
#period ⇒ Object
Returns the value of attribute period.
-
#system ⇒ Object
Returns the value of attribute system.
-
#writer ⇒ Object
Returns the value of attribute writer.
Class Method Summary collapse
-
.are_you_sure?(factor = :medium, flavor = :rand, writer = STDOUT) ⇒ Boolean
Runs a challenge with the message, “Are you sure?” See: Annoy.challenge?.
-
.challenge?(msg = "Please confirm.", factor = :medium, flavor = :rand, writer = STDOUT, period = nil) ⇒ Boolean
Prints a question to
writer
and waits for a response on STDIN. -
.disable_skip ⇒ Object
Tells annoy to prompt for a response.
-
.enable_skip ⇒ Object
Calling this method tells Annoy to not prompt for a response.
-
.get_user_input(msg, echo = nil, period = nil) ⇒ Object
Get a response from the user.
-
.numeric_question(factor = :medium) ⇒ Object
-
Generates a rudimentary numeric equation in the form: (Integer OPERATOR Integer).
-
-
.pose_question(msg, regexp, writer = STDOUT, period = nil) ⇒ Object
Prints a question to writer and waits for a response on STDIN.
-
.proceed?(factor = :medium, flavor = :rand, writer = STDOUT) ⇒ Boolean
Runs a challenge with the message, “Proceed?” See: Annoy.challenge?.
-
.question(factor = :medium, flavor = :rand) ⇒ Object
A wrapper for string_question and numberic_question.
-
.skip? ⇒ Boolean
Returns true of Annoy is in skip mode.
-
.string_question(factor = :medium) ⇒ Object
Generates a random string.
-
.timed_display(msg, writer, period = nil) ⇒ Object
Display
msg
forperiod
seconds.
Instance Method Summary collapse
-
#challenge?(msg = "Please confirm.") ⇒ Boolean
See: Annoy.challenge? Uses the value of @flavor, @factor, and @writer.
-
#initialize(opts = {:factor=>:medium, :flavor=>:rand, :writer=>STDOUT, :period=>nil}) ⇒ Annoy
constructor
-
factor
annoyance factor, one of :low (default), :medium, :high, :insane *flavor
annoyance flavor, one of :rand (default), :numeric, string *writer
an IO object to write to.
-
-
#pose_question(msg, regexp) ⇒ Object
See: Annoy.pose_question Uses the value of @writer.
-
#question ⇒ Object
Generates and returns a question.
Constructor Details
#initialize(opts = {:factor=>:medium, :flavor=>:rand, :writer=>STDOUT, :period=>nil}) ⇒ Annoy
-
factor
annoyance factor, one of :low (default), :medium, :high, :insane -
flavor
annoyance flavor, one of :rand (default), :numeric, string -
writer
an IO object to write to. Default: STDERR -
period
the amount of time to wait in seconds. Default: 60
62 63 64 65 66 67 68 69 70 |
# File 'lib/annoy.rb', line 62 def initialize(opts={:factor=>:medium, :flavor=>:rand, :writer=>STDOUT, :period=>nil}) @factor = opts[:factor] @flavor = Annoy.get_flavor(opts[:flavor]) @writer = opts[:writer] @period = opts[:period] || @@period unless Annoy.respond_to?("#{@flavor}_question") raise "Hey, hey, hey. I don't know that flavor! (#{@flavor})" end end |
Instance Attribute Details
#answer ⇒ Object
Returns the value of attribute answer.
20 21 22 |
# File 'lib/annoy.rb', line 20 def answer @answer end |
#factor ⇒ Object
Returns the value of attribute factor.
18 19 20 |
# File 'lib/annoy.rb', line 18 def factor @factor end |
#flavor ⇒ Object
Returns the value of attribute flavor.
19 20 21 |
# File 'lib/annoy.rb', line 19 def flavor @flavor end |
#period ⇒ Object
Returns the value of attribute period.
22 23 24 |
# File 'lib/annoy.rb', line 22 def period @period end |
#system ⇒ Object
Returns the value of attribute system.
23 24 25 |
# File 'lib/annoy.rb', line 23 def system @system end |
#writer ⇒ Object
Returns the value of attribute writer.
21 22 23 |
# File 'lib/annoy.rb', line 21 def writer @writer end |
Class Method Details
.are_you_sure?(factor = :medium, flavor = :rand, writer = STDOUT) ⇒ Boolean
Runs a challenge with the message, “Are you sure?” See: Annoy.challenge?
154 155 156 |
# File 'lib/annoy.rb', line 154 def Annoy.are_you_sure?(factor=:medium, flavor=:rand, writer=STDOUT) Annoy.challenge?("Are you sure?", factor, flavor, writer) end |
.challenge?(msg = "Please confirm.", factor = :medium, flavor = :rand, writer = STDOUT, period = nil) ⇒ Boolean
Prints a question to writer
and waits for a response on STDIN. It checks whether STDIN is connected a tty so it doesn’t block on gets when there’s no human around to annoy. It will return TRUE when STDIN is NOT connected to a tty (when STDIN.tty? returns false).
-
msg
The message to print. Default: “Please confirm.”
Returns true when the answer is correct, otherwise false.
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/annoy.rb', line 113 def Annoy.challenge?(msg="Please confirm.", factor=:medium, flavor=:rand, writer=STDOUT, period=nil) return true unless STDIN.tty? # Humans only! return true if Annoy.skip? begin success = Timeout::timeout(period || @@period) do flavor = Annoy.get_flavor(flavor) question, answer = Annoy.question(factor, flavor) msg = "#{msg} To continue, #{Annoy.verb(flavor)} #{question}: " #writer.print msg #if ![:medium, :high, :insane].member?(factor) && flavor == :numeric #writer.print "(#{answer}) " #writer.flush #end #response = Annoy.get_response(writer) highline = HighLine.new response = highline.ask(msg) { |q| q.echo = '*' # Don't display response q.overwrite = true # Erase the question afterwards q.whitespace = :strip # Remove whitespace from the response q.answer_type = Integer if flavor == :numeric } ret = (response == answer) writer.puts "Incorrect" unless ret ret end rescue Interrupt writer.puts $/, "Giving up!" false rescue Annoy::GiveUp => ex writer.puts $/, "Giving up!" false rescue Timeout::Error => ex writer.puts $/, "Times up!" false end end |
.disable_skip ⇒ Object
Tells annoy to prompt for a response.
54 |
# File 'lib/annoy.rb', line 54 def Annoy.disable_skip; @@skip = false; end |
.enable_skip ⇒ Object
Calling this method tells Annoy to not prompt for a response. All questions will return true.
52 |
# File 'lib/annoy.rb', line 52 def Annoy.enable_skip; @@skip = true; end |
.get_user_input(msg, echo = nil, period = nil) ⇒ Object
Get a response from the user. Returns the string as typed by the user with extraneous whitespace removed.
-
msg
(required) text to display to user -
echo
(optional) character to display as user types. Used for hiding passwords. -
period
(optional) amount of time to wait.
NOTE: Annoy uses Highline to get user responses. If msg
ends with a space character, Highline will not print a new line. If there is no space character Highline will print a new line.
Annoy.get_user_input("Password?") # => Password?
# => 'user types here'
Annoy.get_user_input("Password? ") # => Password? 'user types here'
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/annoy.rb', line 219 def Annoy.get_user_input(msg, echo=nil, period=nil) return unless STDIN.tty? # Only ask a question if there's a human return if Annoy.skip? response = nil begin success = Timeout::timeout(period || @@period) do highline = HighLine.new response = highline.ask(msg) { |q| unless echo.nil? q.overwrite = true # Erase the question afterwards q.echo = echo # Don't display response end q.whitespace = :strip # Remove whitespace from the response } end rescue Timeout::Error => ex puts $/, "Times up!" end response end |
.numeric_question(factor = :medium) ⇒ Object
-
Generates a rudimentary numeric equation in the form: (Integer OPERATOR Integer).
-
Returns [equation, answer]
95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/annoy.rb', line 95 def Annoy.numeric_question(factor=:medium) equation = answer = 0 while answer < 10 vals = [rand(@@randsize[factor])+1, @@operators[factor][ rand(@@operators[factor].size) ], rand(@@randsize[factor])+1 ] equation = "(%d %s %d)" % vals answer = eval(equation) end [equation, answer] end |
.pose_question(msg, regexp, writer = STDOUT, period = nil) ⇒ Object
Prints a question to writer and waits for a response on STDIN. It checks whether STDIN is connected a tty so it doesn’t block on gets. when there’s no human around to annoy. It will return TRUE when STDIN is NOT connected to a tty or if writer
is nil.
-
msg
The question to pose to the user -
regexp
The regular expression to match the answer.
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/annoy.rb', line 182 def Annoy.pose_question(msg, regexp, writer=STDOUT, period=nil) return true unless STDIN.tty? # Only ask a question if there's a human return true if Annoy.skip? return true if writer.nil? begin success = Timeout::timeout(period || @@period) do regexp &&= Regexp.new regexp highline = HighLine.new response = highline.ask(msg) { |q| q.echo = '*' # Don't display response q.overwrite = true # Erase the question afterwards q.whitespace = :strip # Remove whitespace from the response } regexp.match(response) end rescue Timeout::Error => ex writer.puts $/, "Times up!" false end end |
.proceed?(factor = :medium, flavor = :rand, writer = STDOUT) ⇒ Boolean
Runs a challenge with the message, “Proceed?” See: Annoy.challenge?
160 161 162 |
# File 'lib/annoy.rb', line 160 def Annoy.proceed?(factor=:medium, flavor=:rand, writer=STDOUT) Annoy.challenge?("Proceed?", factor, flavor, writer) end |
.question(factor = :medium, flavor = :rand) ⇒ Object
A wrapper for string_question and numberic_question
80 81 82 83 |
# File 'lib/annoy.rb', line 80 def Annoy.question(factor=:medium, flavor=:rand) raise "Come on, you ruined the flavor!" unless flavor Annoy.send("#{flavor}_question", factor) end |
.skip? ⇒ Boolean
Returns true of Annoy is in skip mode
56 |
# File 'lib/annoy.rb', line 56 def Annoy.skip?; @@skip; end |
.string_question(factor = :medium) ⇒ Object
Generates a random string
86 87 88 89 90 91 |
# File 'lib/annoy.rb', line 86 def Annoy.string_question(factor=:medium) # Strings don't need to be evaluated so the answer is the # same as the question. str = strand @@strlen[factor] [str,str] end |
.timed_display(msg, writer, period = nil) ⇒ Object
Display msg
for period
seconds. NOTE: msg
should be a short, single line. This is a naive approach which simply overwrites the current line.
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/annoy.rb', line 243 def Annoy.timed_display(msg, writer, period=nil) return true unless STDIN.tty? # Only ask a question if there's a human if Annoy.skip? #writer.puts msg return true end if writer.nil? sleep period+1 return true end begin period ||= @@period success = Timeout::timeout(period) do writer.puts "Message will display for #{period} seconds" writer.print msg writer.flush if writer.respond_to?(:flush) sleep period+1 end rescue Timeout::Error => ex writer.print "\r" << ' '*msg.size end true end |
Instance Method Details
#challenge?(msg = "Please confirm.") ⇒ Boolean
See: Annoy.challenge? Uses the value of @flavor, @factor, and @writer
166 167 168 |
# File 'lib/annoy.rb', line 166 def challenge?(msg="Please confirm.") Annoy.challenge?(msg, @factor, @flavor, @writer) end |
#pose_question(msg, regexp) ⇒ Object
See: Annoy.pose_question Uses the value of @writer
172 173 174 |
# File 'lib/annoy.rb', line 172 def pose_question(msg, regexp) Annoy.pose_question(msg, regexp, @writer) end |