Making a flashing console message with ruby - ruby

0.upto(9) do
STDOUT.print "Flash!"
sleep 0.5
STDOUT.print "\b\b\b\b\b\b" # (6 backspaces, the length of "Flash!")
sleep 0.5
end
This code doesn't work. It prints Flash! to the screen, but it doesn't flash. It just stays there, as though the backspaces aren't taking effect. But I do this:
0.upto(9) do
STDOUT.print "Flash!"
sleep 0.5
STDOUT.print "\b\b\b\b\b" # (5 backspaces, the length of "Flash! - 1")
sleep 0.5
end
and it almost works. It prints this: FFFFFFFFFFlash!(after 9 loops) Why do the backspaces stop taking effect when their number is equal to the length of the string they're deleting?
How can I overcome this problem and create a flashing message, only using libraries that are part of rails?
I tried a workaround like this:
0.upto(9) do
STDOUT.print " Flash!"
sleep 0.5
STDOUT.print "\b\b\b\b\b\b"
sleep 0.5
end
(Note the space in " Flash!"), but what happens is the message appears to crawl across the screen! An interesting effect, but not what I want.
I'm using Command Prompt with Ruby and Rails in Windows 7

Typically this would be written something like:
0.upto(9) do
STDOUT.print "\rFlash!"
sleep 0.5
STDOUT.print "\r " # Send return and six spaces
sleep 0.5
end
Back in the days when we'd talk to TTY and dot-matrix printers, we'd rapidly become used to the carriage-control characters, like "\r", "\n", "\t", etc. Today, people rarely do that to start, because they want to use the web, and browsers; Learning to talk to devices comes a lot later.
"\r" means return the carriage to its home position, which, on a type-writer moved the roller all the way to the right so we could start typing on the left margin again. Printers with moving heads reversed that and would move the print-head all the way to the left, but, in either case, printing started on the left-margin again. With the console/telnet/video-TTY, it moves the cursor to the left margin. It's all the same, just different technology.
A little more usable routine would be:
msg = 'Flash!'
10.times do
print "\r#{ msg }"
sleep 0.5
print "\r#{ ' ' * msg.size }" # Send return and however many spaces are needed.
sleep 0.5
end
Change msg to what you want, and the code will automatically use the right number of spaces to overwrite the characters.

Anyway, it looks like backspace (at least in windows) just positions the cursor back, you need/want to overwrite the character with a space at that point (or 6 of them) to "blank" the text out.

Or, you can just use this
def text_flasher(text)
puts "\e[5m#{text}\e[0m"
end
use text_flasher in the console and you'll see the magic :)

Right, based on #rogerdpack 's input I have devised a solution:
def flashing_output(output)
message = output
backspace = "\b"
space = " "
backspace_array = []
space_array = []
length = message.length
length.times do
backspace_array << backspace
space_array << space
end
0.upto(9) do
print message
sleep 0.5
print backspace_array.join.to_s + space_array.join.to_s + backspace_array.join.to_s + backspace_array.join.to_s
sleep 0.5
end
end
flashing_output("Flashing Foobars! (not a euphemism)")

Related

Check if button is pressed or not

I have a Raspberry Pi with a Siri Proxy that is controlling my garage door, the garage door has only one command for open and close. To check if the garage door is opened to not I bought a magnet switch and I builded a flout point button. I already tried
doorstate = `gpio read 5`.chomp #gives value 1 or 0, 1 is opened, 0 is closed
print doorstate
if doorstate == "1"
print "The garage door is already opened.\n"
elsif doorstate == "0"
print "OK, I'll open it for you!\n"
else
print "Error, please open it manually.\n"
end
Can someone please tell me how I can check fi the returned value or string from doorstate = 'gpio read 5' is equal to a string?
I'm guessing here that the result of 'gpio read 5' contains a line ending.
Try chomping it off:
doorstate = `gpio read 5`.chomp
To verify the class of doorstate, insert p doorstate.class at line 2.
You need to change your single quotes (') to backticks (`, the little thing with the tilde on your keyboard). That will execute the command. The rest of your code is fine.

loop autoit script until end of doc

I have an autoit script that basicly copies the first line of text, and then pastes it again in the same line. I would like to do this over and over until the end of the document. Any suggestions?
Run("notepad.exe filename.txt")
WinWaitActive("Untitled - Notepad")
Send("+{END}")
Send("^C")
Sleep (1000)
Send("{END}")
Sleep (1000)
Send(" ")
Send("^V")
Send("{HOME}")
Send("{DOWN}")
You can use this code:
$filename = "filename.txt"
Run("notepad.exe " & $filename)
WinWaitActive($filename & " - Notepad")
$lines= StringRegExp(FileRead($filename), #CR, 3)
$count = UBound($lines)
For $i = 0 To $count
Send("+{END}")
Send("^C")
Sleep (1000)
Send("{END}")
Sleep (1000)
Send(" ")
Send("^V")
Send("{HOME}")
Send("{DOWN}")
Next
You have to wait for the Window with the filename in it's title. If the filename has spaces inside, you need to put quotes around the parameter after notepad.exe.
Somehow you need to get the count of line numbers. I just read the whole file with AutoIt and search for a "carriage return". The resulting Array has the size of the line numbers. That number is then used in a For-...-To-...-Loop.
You can decrease the sleep-times to 100ms. And it would be much easier to use FileReadLine and probably FileWriteLine to do your task, as FileReadLine can be used until the end of file is reached. It will set #error to -1. See the documentation for more info.

Get numbers from a list in a file, output to another file in Ruby?

I have a big text file that contains - among others- lines like these:
"X" : "452345230"
I want to find all lines that contain "X" , and take just the number (without the quotation marks), and then output the numbers in another file, in this fashion:
452349532
234523452
213412411
219456433
etc.
What I did so far is this:
myfile = File.open("myfile.txt")
x = []
myfile.grep(/"X"/) {|line|
x << line.match( /"(\d{9})/ ).values_at( 1 )[0]
puts x
File.open("output.txt", 'w') {|f| f.write(x) }
}
it works, but the list it produces is of this form:
["23419230", "2349345234" , ... ]
How do I output it like I showed before, just numbers and each number in a line?
Thanks.
Here's a solution that doesn't leave files open:
File.open("output.txt", 'w') do |output|
File.open("myfile.txt").each do |line|
output.puts line[/\d{9}/] if line[/"X"/]
end
end
I couldn't reproduce what you saw:
$ cat myfile.txt
"X" : "452345230"
"X" : "452345231"
"X" : "452345232"
"X" : "452345233"
$ ./scanner.rb
452345230
452345230
452345231
452345230
452345231
452345232
452345230
452345231
452345232
452345233
$ cat output.txt
452345230452345231452345232452345233$
However, I did notice that your application is incredibly wasteful and probably not doing what you expect: You open output.txt, write some content to it, then close it again. The next time it is opened in the loop, it is overwritten. If your file is 1000 lines long, this won't be so bad, you're only making 1000 files. If your file is 1,000,000 lines long, this is going to represent a pretty horrible performance penalty as you create a file, write into it, and then delete it again, one million times. Oops.
I re-wrote your tool a little bit:
$ cat scanner.rb
#!/usr/bin/ruby -w
myfile = File.open("myfile.txt")
output = File.open("output.txt", 'w')
myfile.grep(/"X"/) {|line|
x = line.match( /"(\d{9})/ ).values_at( 1 )[0]
puts x
output.write(x + "\n")
}
This opens each file exactly onces, writes each new line one at a time, and then lets them both be closed when the application quits. Depending upon if this is a small portion of your application or the entire thing, this might be alright. (If this is a small portion of the program, then definitely close the files when you're done with them.)
This might still be wasteful for one million matched lines -- those writes are almost certainly handed straight to the system call write(2), which will involve some overhead.
How many of these will you be running? Millions? Billions? If this needs more refinement feel free to ask...
Solution:
myfile = File.open("myfile.txt")
File.open("output.txt", 'w') do |output|
content = myfile.lines.map { |line| line.scan(/^"X".*(\d{9})/) }.flatten.join("\n")
output.write(content)
end
Edited: I updated the code reducing it a bit. If the example above seems complicated, you can also grab the data you want with the following statement (could be a little bit clear of what's happening):
content = myfile.lines.select { |line| line =~ /"X"/ }.map { |line| line.scan(/\d{9}/) }.join("\n")

test if a PDF file is finished in Ruby (on Solaris/Unix)?

i have a server, that generates or copies PDF-Files to a specific folder.
i wrote a ruby script (my first ever), that regularily checks for own PDF-files and displayes them with acrobat. So simple so nice.
But now I have the Problem: how to detect the PDF is complete?
The generated PDF ends with %%EOF\n
but the copied ones are generated with some Apple-Magic (Acrobat Writer I think), that has an %%EOF near the beginning of the File, lots of binary Zeros and another %%EOF near the end with a carriage return (or line feed) and a binary zero at the end.
while true
dir = readpfad
Dir.foreach(dir) do |f|
datei = File.join(dir, f)
if File.file?(datei)
if File.stat(datei).owned?
if datei[-9..-1].upcase == "__PDF.PDF"
if File.stat(datei).size > 5
test = File.new(datei)
dummy = test.readlines
if dummy[-1][0..4] == "%%EOF"
#move the file, so it will not be shown again
cmd = "mv " + datei + " " + movepfad
system(cmd)
acro = ACROREAD + " " + File.join(movepfad, f) + "&"
system(acro)
else
puts ">>>" + dummy[-1] + "<<<"
end
end
end
end
end
end
sleep 1
end
Any help or idea?
Thanks
Peter
All the %%EOF token means is that there should be one within the last 1024 bytes of the physical end of file. The structure of PDF is such that a PDF document may have 1 or more %%EOF tokens within it (the details are in the spec).
As such, "contains %%EOF" is not equivalent to "completely copied". Really, the correct answer is that the server should signal when it's done and your code should be a client of that signal. In general, polling -- especially IO bound polling is the wrong answer to this problem.

Testing time critical code

I've written a feature for my library Rubikon that displays a throbber (a spinning — as you may have seen in other console apps) as long as some other code is running.
To test this feature I capture the output of the throbber in a StringIO and compare it with the expected value. As the throbber is only displayed as long as the other code is running the content of the IO gets longer when the code runs longer. In my tests I do a simple sleep 1 and should have a constant 1 second delay. This works most of the time, but sometimes (apparently due to external factors like heavy load on the CPU) it fails, because the code doesn't run for 1 second, but for a bit more, so that the throbber prints a few additional characters.
My question is: Is there any possibility to test such time critical features in Ruby?
From your github repository, I found this test for the Throbber class:
should 'work correctly' do
ostream = StringIO.new
thread = Thread.new { sleep 1 }
throbber = Throbber.new(ostream, thread)
thread.join
throbber.join
assert_equal " \b-\b\\\b|\b/\b", ostream.string
end
I'll assume that a throbber iterates over ['-', '\', '|', '/'], backspacing before each write, once per second. Consider the following test:
should 'work correctly' do
ostream = StringIO.new
started_at = Time.now
ended_at = nil
thread = Thread.new { sleep 1; ended_at = Time.now }
throbber = Throbber.new(ostream, thread)
thread.join
throbber.join
duration = ended_at - started_at
iterated_chars = " -\\|/"
expected = ""
if duration >= 1
# After n seconds we should have n copies of " -\\|/", excluding \b for now
expected << iterated_chars * duration.to_i
end
# Next append the characters we'd get from working for fractions of a second:
remainder = duration - duration.to_i
expected << iterated_chars[0..((iterated_chars.length*remainder).to_i)] if remainder > 0.0
expected = expected.split('').join("\b") + "\b"
assert_equal expected, ostream.string
end
The last assignment of expected is a bit unpleasant, but I made the assumption that the throbber would write character/backspace pairs atomically. If this is not true, you should be able to insert the \b escape sequence into the iterated_chars string and remove the last assignment entirely.
This question is similar (I think, altough I'm not completely sure) to this one:
Only real time operating system can
give you such precision. You can
assume Thread.Sleep has a precision of
about 20 ms so you could, in theory
sleep until the desired time - the
actual time is about 20 ms and THEN
spin for 20 ms but you'll have to
waste those 20 ms. And even that
doesn't guarantee that you'll get real
time results, the scheduler might just
take your thread out just when it was
about to execute the RELEVANT part
(just after spinning)
The problem is not rubby (possibly, I'm no expert in ruby), the problem is the real time capabilities of your operating system.

Resources