I'd like to get an input string of digits (multiples of 5) in one line, but after each block of 5 digits, a space separator character would print to make the input line easier to read and count.
For instance:
Enter random numeric key with a length of 25 digits below:
45325 89345 98834 23453 23453
Rather than:
Enter random numeric key with a length of 25 digits below:
4532589345988342345323453
Is this at all possible?
I tried using getc to read in a character but am getting an error message:
undefined local variable or method `getc' for main:Object (NameError)
You could do something like this:
require 'io/console'
cnt=0
buffer=[]
while cnt<25 do
c=STDIN.getch
if c=~/[0-9]/ then
print c
print " " if (cnt+=1)%5==0
buffer<<c
else
IO::console::beep
end
end
puts "\n#{buffer.join}"
As written, it does what you stated. But typically something would also need to support delete, esc and ^ c at a minimum.
Here is a way to handle those (but I bet there is a better way):
#!/usr/bin/env ruby
require 'io/console'
def get_line(txt, len=25, skip=5)
def left
IO::console::cursor_left(1)
end
def pr(c)
print c
end
def del(x)
x.times{left()}
x.times{pr(' ')}
x.times{left()}
end
def beep
IO::console::beep
end
cnt=col=0
buf=[]
breaks=["\u0003"]
bs=["\x0008", "\u007F"]
print txt
line=""
while buf.length<len do
c=STDIN.getch
if c=~/[0-9]/ then
buf << c
elsif bs.include?(c)
buf.length>0 ? buf.pop : beep()
elsif breaks.include?(c)
buf=[]
break
elsif c=="\e"
buf=[]
else
beep()
end
del(line.length)
line=buf.map.with_index(1){|c,i|
"#{c}#{(i%skip==0) ? " " : ""}"
}.join
line.chars.each{|c| pr(c) }
end
buf.join
end
p get_line("Enter numbers: ")
Or an alternate version that uses a case statement rather than the if
elsif
else
ladder:
require 'io/console'
def get_line(txt, len=25, skip=5)
def left
IO::console::cursor_left(1)
end
def pr(c)
print c
end
def del(x)
x.times{left()}
x.times{pr(' ')}
x.times{left()}
end
beep=-> {IO::console::beep}
backspace=lambda{|c| ["\x0008", "\u007F"].include?(c) }
brk=lambda{|c| ["\u0003"].include?(c) }
cnt=col=0; buf=[]; line=""
print txt
while buf.length<len do
c=STDIN.getch
case c
when /[0-9]/
buf << c
when backspace
buf.length>0 ? buf.pop : beep[]
when brk
buf=[]
break
when "\e"
buf=[]
else
beep[]
end
del(line.length)
line=buf.map.with_index(1){|c,i|
"#{c}#{(i%skip==0) ? " " : ""}"
}.join
line.chars.each{|c| pr(c) }
end
buf.join
end
# works the same
The problem is that there is a great deal of variability in text terminal types, compliance and capabilities. These functions only needs left
, pr
and beep
to work properly on the terminal you use so not that hard. You could do it with ANSI codes as well.