def talk(text, speed = 0.008)
pause = speed * 100
r = /(\.{3}|\.)/
text.split(r).each do |str|
if str.match?(r)
sleep(pause)
else
print str
end
end
puts
end
talk("Mary had .a lit...tle .lamb", 0.04)
#=> Mary had a little lamb
^ ^ ^
A four-second delay occurred after each character indicated by a party hat was printed.
The steps are as follows.
text = "Mary had .a lit...tle .lamb"
speed = 0.04
pause = speed * 100
r = /(\.{3}|\.)/
This regular expression reads, "match three periods or (|
) one period in capture group 1" (the capture group being defined by the parentheses)". This is not the same as /(\.|\.{3})/
, which would match each period of each group of three individually (that is, \.
before |
would succeed for every period, part of a group or not).
a = text.split((r))
#=> ["Mary had ", ".", "a lit", "...", "tle ", ".", "lamb"]
See String#split, which explains the need for the capture group, to include the splitting strings in the array returned.
Continuing,
a.each do |str|
if str.match?(r)
sleep(pause)
else
print str
end
end
This prints (without a newline character) "Mary had "
, sleeps for four seconds, prints "a lit"
, sleeps for another four seconds, and so on.
puts
This last statement is needed to print a newline character to terminate the line.
Another way is to make a few small change to the method given in the question.
def talk(text, speed = 0.008)
pause = speed * 100
text.squeeze('.').each_char do |char|
if char == '.'
sleep(pause)
else
print char
end
end
puts
end
See String#squeeze which converts each string of two or more periods to one period.
This method differs from the earlier one in its treatment of two or more than three periods in a row.