0

I'm trying to write a shell in Ruby (using readline), implementing some custom commands. To create the correspondence between given input and methods that are defined in an external module I'm using an hash like this

hash = {
  'command_1' => method(:method_1),
  'command_2' => method(:method_2)
}

And once I got the user input I pass it to the hash calling the method associated with the command-key

hash[input.to_s].()

My questions are: how can I handle variants of the same command? (e.g. for the help command give different output depending if a flag is given, something like help -command_1)
How can I pass parameters to methods in the hash? (e.g. pass to an open command the file to be opened like open file_name)

Thanks to all in advance.

tadman
  • 208,517
  • 23
  • 234
  • 262
A G
  • 1
  • 3
  • You can pass arguments through the `.()` method call. – user229044 Dec 11 '18 at 19:59
  • 3
    Might want to build a true CLI instead using something like [`thor`](https://github.com/erikhuda/thor), [`slop`](https://github.com/leejarvis/slop) , [`commander`](https://github.com/commander-rb/commander) and [many more](https://lab.hookops.com/ruby-cli-gems.html) – engineersmnky Dec 11 '18 at 20:00
  • As said above, there are entire frameworks written around CLIs in ruby - this will likely make your life much easier than trying to reinvent the wheel! But if you really want to build your own (or to have full control of how the entire application works), the fundamental approach - in many languages, including ruby - is to use `ARGV`. – Tom Lord Dec 11 '18 at 20:59
  • Ruby also provides [`ARGF`](https://ruby-doc.org/core/ARGF.html), which also handles streaming input. Also, for some slightly more advanced out-of-the-box tooling, there is a library called [`optparse`](https://ruby-doc.org/stdlib/libdoc/optparse/rdoc/OptionParser.html) in ruby's standard library. – Tom Lord Dec 11 '18 at 21:01
  • I've written a simple shell like this in ruby, using readline, it's at https://github.com/kontena/kontena-plugin-shell – Kimmo Lehto Dec 12 '18 at 07:56
  • Thanks all for the replies. I've quickly looked at **thor** documentation but I've only found a way of passing args on calling (something like `my_program -args1 -args2` ), but I haven't found a way to create a prompt that accept commands until user exit (to give you an idea, something like the _msfconsole_ of metasploit). Did I miss something? – A G Dec 12 '18 at 09:12

1 Answers1

0

While that might work if you wrangle it enough, the easy way is this:

hash = {
  'command_1' => :method_1,
  'command_2' => :method_2
}

send(hash[input.to_s])

The send method allows dynamic dispatch which is way easier than trying to deal with method.

tadman
  • 208,517
  • 23
  • 234
  • 262