Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a Ruby command line app that supports tab completion?

Tags:

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?

like image 947
mydoghasworms Avatar asked Dec 14 '12 09:12

mydoghasworms


People also ask

How do you completion a tab in Linux?

Command-line completion allows the user to type the first few characters of a command, program, or filename, and press a completion key (normally Tab ↹ ) to fill in the rest of the item. The user then presses Return or ↵ Enter to run the command or open the file.

How do I run a command-line in ruby?

Press Ctrl twice to invoke the Run Anything popup. Type the ruby script. rb command and press Enter . If necessary, you can specify the required command-line options and script arguments.

What is ruby command?

Ruby command is a free and open source programming language; it is flexible and is feature rich. As the name suggests, ruby indeed is a jewel language which comes at a very low entry cost. Its plug and play capability and also easily readable syntax makes it very user-friendly.


2 Answers

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).

like image 175
mydoghasworms Avatar answered Sep 18 '22 16:09

mydoghasworms


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 
like image 36
Josh Voigts Avatar answered Sep 17 '22 16:09

Josh Voigts