My Projects

The projects that I have spent significant time on.

1

OCT
2006

I Just Want One Character!

Every so often a person asks the question on Ruby Talk, "How can I get just one character from the keyboard (without needing the user to hit return)?" Everyone is always quick to post solutions, but sadly there are some issues with almost every one of them.

The general consensus is that this is a tough problem to solve correctly. I say that's the exact reason to let HighLine handle this for you:

#!/usr/bin/env ruby -w

require "highline/system_extensions"
include HighLine::SystemExtensions

print "Enter one character:  "
char = get_character
puts char.chr

That doesn't look too tough, does it?

What's terrific about this solution is that under-the-hood HighLine will check your platform and libraries and then try to use the solution that makes the most sense for your environment. The code is really pretty robust too, because people a lot smarter than me have been sending in patches for over a year, slowly eliminating all of those tricky edge cases.

As you can see, I've split this functionality of HighLine into a separate module so you don't even need to load the full HighLine system. This was done just because this is such a real and common problem. This section of HighLine is one pure Ruby file, so feel free to vendor it if the external dependency is an issue.

Trust me, reading individual characters from the keyboard doesn't have to be that tough. You just need the right tool for the job.

Comments (8)
  1. Peter
    Peter October 7th, 2006 Reply Link

    Maybe i did something wrong but the above example didn't work for me. I had to change the line:

    #!/usr/bin/env ruby -w
    

    to

    #!/usr/bin/ruby -w
    

    and also I had to add one more line:

    require 'rubygems'
    

    That is maybe because of that env didn't worked for me.

    1. Reply (using GitHub Flavored Markdown)

      Comments on this blog are moderated. Spam is removed, formatting is fixed, and there's a zero tolerance policy on intolerance.

      Ajax loader
    2. James Edward Gray II
      James Edward Gray II October 7th, 2006 Reply Link

      Yeah, that was careless of me. That shebang line only works on some operating systems. It works on my Mac OS X 10.4 for example, but I believe 10.3 chokes on it. Better to point it your local Ruby install, as Peter did.

      If you have HighLine installed as a gem, you will need to make gems available, yes. I generally don't like using an explicit require for that in the code, because it makes rubygems a dependancy. Generally I just run the code with:

      ruby -rubygems ...
      
      1. Reply (using GitHub Flavored Markdown)

        Comments on this blog are moderated. Spam is removed, formatting is fixed, and there's a zero tolerance policy on intolerance.

        Ajax loader
  2. Gregory
    Gregory October 19th, 2006 Reply Link

    SystemExtensions Rocks.

    I vendored it in Ruport and modified it slightly so that I could play around with getting the terminal geometry.

    I think i just added a method or to for convenience, but I should really go ahead and stick them back in HighLine

    1. Reply (using GitHub Flavored Markdown)

      Comments on this blog are moderated. Spam is removed, formatting is fixed, and there's a zero tolerance policy on intolerance.

      Ajax loader
  3. Jon Egil
    Jon Egil October 22nd, 2006 Reply Link

    Very nice, works flawlessly on both Linux(ubuntu) and WinXP. Thanks

    1. Reply (using GitHub Flavored Markdown)

      Comments on this blog are moderated. Spam is removed, formatting is fixed, and there's a zero tolerance policy on intolerance.

      Ajax loader
  4. gm.vlkv@gmail.com
    gm.vlkv@gmail.com October 22nd, 2006 Reply Link

    HighLine::SystemExtensions.get_character does not work when executed on rxvt terminal under cygwin;
    # Unix savvy getc(). (Second choice.) method must be used in this case.

    1. Reply (using GitHub Flavored Markdown)

      Comments on this blog are moderated. Spam is removed, formatting is fixed, and there's a zero tolerance policy on intolerance.

      Ajax loader
    2. James Edward Gray II
      James Edward Gray II October 25th, 2006 Reply Link

      I've just released HighLine 1.2.3 which should fix the Cygwin issue. Thanks for pointing it out.

      1. Reply (using GitHub Flavored Markdown)

        Comments on this blog are moderated. Spam is removed, formatting is fixed, and there's a zero tolerance policy on intolerance.

        Ajax loader
  5. Nemesis Fixx
    Nemesis Fixx October 15th, 2009 Reply Link

    thanks Gray. really saved my night's 'hack' but:

    # -> i had to add extra requires and 
    #################################################
    require 'rubygems'
    require 'highline/import'
    require "highline/system_extensions"
    include HighLine::SystemExtensions
    
    counter = 0
    
    begin
    
    print "#{counter += 1}\r\n" 
    
    sleep 1
    
    Thread.new {
    char  = get_character
    
    if (char.chr != '') 
    exit
    end
    }
    
    end while true
    ###############################################33
    
    #leaves my bash prompt (Ubuntu 8.04) unresponsive (actaully there's no
    #more echoing of keyboard input within the prompt that executes this
    #script!
    #Inform me please, thanks.
    #
    
    1. Reply (using GitHub Flavored Markdown)

      Comments on this blog are moderated. Spam is removed, formatting is fixed, and there's a zero tolerance policy on intolerance.

      Ajax loader
    2. James Edward Gray II
      James Edward Gray II October 15th, 2009 Reply Link

      Well it looks like you just keep spinning off Threads there, one a second. The main Thread doesn't wait for your Thread.new { … } block to finish, so it just keeps cycling and creating more Threads. Perhaps you meant to wait on each Thread to finish before moving on? You could change your Thread code to something like Thread.new { … }.join to accomplish that.

      1. Reply (using GitHub Flavored Markdown)

        Comments on this blog are moderated. Spam is removed, formatting is fixed, and there's a zero tolerance policy on intolerance.

        Ajax loader
Leave a Comment (using GitHub Flavored Markdown)

Comments on this blog are moderated. Spam is removed, formatting is fixed, and there's a zero tolerance policy on intolerance.

Ajax loader