class UserInput

Provides functions to convert terminal input to desired data-types and does some verifications. Keyboard-input is always non-blocking, to allow syntax-checking on the fly and to accelerate the work-flow, wherever possible.

Public Class Methods

a2i(ar) click to toggle source

For cases when no data-type can be imposed for the input, but ultimately an integer is needed. [4,3,2] becomes 432. Beware, that the character-values must have been converted to int, already, by substracting 48 from any number-symbol, or by converting its character incarnation to int.

# File lib/user_input.rb, line 201
def self::a2i(ar)
  if ar.respond_to?(:to_ary)
    ar.reverse!
    res = 0
    ar.each_with_index do |n, i|
      res += (n * 10**i)
    end
    return res
  else
    puts "Invalid input " << ar.to_s
    return 0
  end
end
char_input() click to toggle source
# File lib/user_input.rb, line 109
def self::char_input
  begin
    char = wait_for_user()
    if( 'q' == char.chr.downcase)
      print "\n\tBye "
      return :quit_game
    elsif ('a'..'z').member?(char.chr.downcase)
      return char
    end
  rescue Interrupt
    exit true
  end
end
debout(str) click to toggle source

Brutal log-function: See your desired message, then hit 'q' to exit program.

# File lib/user_input.rb, line 33
def self::debout(str)
  if $DEBUG == :DEBUG
    puts str
    if(wait_for_user().chr == 'q')
      exit true
    end
  end
end
float_input() click to toggle source
# File lib/user_input.rb, line 90
def self::float_input
  ar = []
  loop do
    begin
      char = wait_for_user()
      if char == 10 || char == 13
        return ar.join.to_f
      elsif( 'q' == char.chr.downcase)
        print "\n\tBye "
        return :quit_game
      else
        ar << char
      end
    rescue Interrupt
      exit true
    end
  end
end
input() click to toggle source
# File lib/user_input.rb, line 124
def self::input
  inp = []
  loop do
    begin
      char = wait_for_user()
      if char == 10 || char == 13
        return inp
      elsif( 'q' == char.chr.downcase)
        print "\n\tBye. "
        return :quit_game
      elsif ('a'..'z').member?(char.chr.downcase)
        return char.chr
      else
        inp << char - 48
      end
    rescue Interrupt
      exit true
    end

  end
end
int_array_input(len, range = nil) click to toggle source
# File lib/user_input.rb, line 146
def self::int_array_input(len, range = nil)
  ar = []
  until ar.length == len
    if(range)
      print ' (Available: '
      disp = range.to_a - ar
      if disp.length > 2
        puts disp.join(', ') << ')' 
      elsif disp.length == 2
        puts disp.first.to_s << ' or ' << disp.last.to_s << ')'
      else
        puts disp.first.to_s << ')'
      end
    end

    begin
      char = wait_for_user()
      if( 'q' == char.chr.downcase)
        print "\n\tBye. "
        return :quit_game
      elsif range && range.member?(char - 48)
        num = char - 48
        if(ar.member?(num)) 
          puts '%d cannot happen twice!' %num
          puts 'Try again or push "q" to quit.'
        else
          ar << num
        end
      else
        print "%s is not a valid input." %char.chr
        if(range)
          print ' (Available: '
          disp = range.to_a - ar
          if disp.length > 2
            puts disp.join(', ') << ')' 
          elsif disp.length == 2
            puts disp.first.to_s << ' or ' << disp.last.to_s << ')'
          else
            puts disp.first.to_s << ')'
          end
        end
        puts 'Try again or push "q" to quit.'
      end
    rescue Interrupt
      exit true
    end
  end
  return ar
end
int_input(range = nil) click to toggle source
# File lib/user_input.rb, line 60
def self::int_input(range = nil)
  ar = []
  loop do
    begin
      char = wait_for_user()
      if char == 10 || char == 13
        if(range && range.min > ar.join.to_i)
          puts "\n%d is too small. Choose a number from the list of events or 0 (zero)" %ar.join.to_i
          ar.clear
        else
          return ar.join.to_i
        end
      elsif( 'q' == char.chr.downcase)
        print "\n\tBye "
        return :quit_game
      else
        num = char - 48
        ar << num
        print num
        if(range && range.max < ar.join.to_i )
          puts "\n%d is becoming too big. Choose a number from the list of events or 0 (zero)" %ar.join.to_i
          ar.clear
        end
      end
    rescue Interrupt
      exit true
    end
  end
end
string_input() click to toggle source
# File lib/user_input.rb, line 42
def self::string_input
  inp = ""
  loop do
    begin
      char = wait_for_user()
      if char == 10 || char == 13
        return inp
      elsif( 'q' == char.chr.downcase)
        exit true
      else
        inp << char
      end
    rescue Interrupt
      exit true
    end
  end
end

Private Class Methods

wait_for_user() click to toggle source

The marvellous and mystic, heard-about so-long… unblocking read from STDIN!!

# File lib/user_input.rb, line 218
def self::wait_for_user()
  char = nil
  # There is a difference which makes me prefer the below code from STDIN.raw(args)
  # You can try
  # char = STDIN.raw(&:getc)
  # .., which does *not* work the same way and it won't for me.

  STDIN.raw do 
    STDIN.noecho do
      until (STDIN.ready?)
        sleep(0.1)
      end
      char = (STDIN.read_nonblock(1).ord rescue nil)
    end
  end
  return char
end