23

I want to write a command line app, a shell if you will, in Ruby.

I want the user to be able to press Tab at certain points and offer completion of values.

How do I do this? What library must I use? Can you point me to some code examples?

4 Answers 4

34

Ah, it seems the standard library is my friend after all. What I was looking for is the Readline library.

Doc and examples here: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/readline/rdoc/Readline.html

In particular, this is a good example from that page to show how completion works:

require 'readline'

LIST = [
  'search', 'download', 'open',
  'help', 'history', 'quit',
  'url', 'next', 'clear',
  'prev', 'past'
].sort

comp = proc { |s| LIST.grep(/^#{Regexp.escape(s)}/) }

Readline.completion_append_character = " "
Readline.completion_proc = comp

while line = Readline.readline('> ', true)
  p line
end

NOTE: The proc receives only the last word entered. If you want the whole line typed so far (because you want to do context-specific completion), add the following line to the above code:

Readline.completer_word_break_characters = "" #Pass whole line to proc each time

(This is by default set to a list of characters that represent word boundaries and causes only the last word to be passed into your proc).

1
  • 2
    One thing to note is that readline uses the systems' underlying readline-like library, which might be libedit. So, some features of the readline ruby lib won't work or will cause crashes. Avoid anything that the docs say is optional or might not work. Commented Dec 17, 2012 at 14:31
10

The Readline library is excellent, I've used it many times. But, if you're making it just for the fun of it, you can also roll your own completion.

Here's a simple completion script:

require 'io/console' # Ruby 1.9
require 'abbrev'

word = ""

@completions = Abbrev.abbrev([
   "function",
   "begin"
])

while (char = $stdin.getch) != "\r"
   word += char
   word = "" if char == " "
   if char == "\t"
      if comp = @completions[word = word[0..-2]]
         print comp[word.length..-1]
      end
   else
      print char
   end
end
puts
2
  • 1
    Rather than manually defining @completions, why not use Abbrev from the standard library?
    – iconoclast
    Commented Aug 20, 2015 at 1:50
  • Thanks for the tip! Updated the example to use the Abbrev library. Commented Aug 20, 2015 at 19:02
1

Some ruby projects can help you create completion without writing complex code:

-13

Well, I suggest that you use Emacs to run your command line Ruby app. In Emacs, my SO friends just recently helped me to solve the Autocomplete tab completion (here and here). Autocomplete seems to be the most intelligent word completion tool to date.

1
  • Dudes, cut it out with that downvoting. Not reinventing the wheel is a good suggestion. This answer of mine does deserve some love. Commented Jul 19, 2014 at 6:45

Not the answer you're looking for? Browse other questions tagged or ask your own question.