2

I'm working on a Ruby gem that should be used as a CLI utility.

I've decided to use Thor, that is used by the rails command and seems to be very flexible (on the differences with rake: link).

The problem is I can't find how to handle input error. For example, if I type in a wrong option, Thor automatically returns a nice warning:

$ myawesomescript blabla
Could not find command "blabla".

But, if I use a command that can't be resolved, things get ugly. For example, there is a "help" default command and I have defined a "hello" command. If I type just "h" this is what I get:

$ myawesomescript h
/Users/Tom/.rvm/gems/ruby-2.0.0-p0/gems/thor-0.18.1/lib/thor.rb:424:in `normalize_command_name': Ambiguous command h matches [hello, help] (ArgumentError)
    from /Users/Tom/.rvm/gems/ruby-2.0.0-p0/gems/thor-0.18.1/lib/thor.rb:340:in `dispatch'
    from /Users/Tom/.rvm/gems/ruby-2.0.0-p0/gems/thor-0.18.1/lib/thor/base.rb:439:in `start'
    from /Users/Tom/Documents/ruby/myawesomescript/bin/myawesomescript:9:in `<top (required)>'
    from /Users/Tom/.rvm/gems/ruby-2.0.0-p0/bin/myawesomescript:23:in `load'
    from /Users/Tom/.rvm/gems/ruby-2.0.0-p0/bin/myawesomescript:23:in `<main>'
    from /Users/Tom/.rvm/gems/ruby-2.0.0-p0/bin/ruby_noexec_wrapper:14:in `eval'
    from /Users/Tom/.rvm/gems/ruby-2.0.0-p0/bin/ruby_noexec_wrapper:14:in `<main>'
myawesomescript $

Now, I know that just typing "h" is stupid, and that I could just rename my commands, but I don't want users to see these kind of error messages.

I tried to override that method with:

def normalize_command_name(meth)
  super(meth)
rescue ArgumentError => e
  puts "print something useful"
end

...but it doesn't work


New details:

OK, I noticed that that method was declared on the class, not the instances. I tried the following and seems to work nicely, but it's not ideal and a bit hacky:

file: lib/myawesomescript/thor_overrides.rb

require 'thor'

class Thor
  class << self

    protected
      def normalize_command_name(meth)
        return default_command.to_s.gsub('-', '_') unless meth

        possibilities = find_command_possibilities(meth)
        if possibilities.size > 1
          raise ArgumentError, "Ambiguous command #{meth} matches [#{possibilities.join(', ')}]"
        elsif possibilities.size < 1
          meth = meth || default_command
        elsif map[meth]
          meth = map[meth]
        else
          meth = possibilities.first
        end

        meth.to_s.gsub('-','_') # treat foo-bar as foo_bar
      rescue ArgumentError => e
        # do nothing
      end
      alias normalize_task_name normalize_command_name
  end
end

There I added the lines:

rescue ArgumentError => e
  # do nothing

And it does the trick, as it seems that somewhere else some piece of code takes care of the error message:

$ myawesomescript h
Could not find command "h".

Anyway, is there a better way?

Community
  • 1
  • 1
tompave
  • 11,952
  • 7
  • 37
  • 63
  • Could you share the complete Thor script? – acw Apr 17 '13 at 16:14
  • mmm... I'm afraid it got quite long, although it's just front-end logic with calls to other classes. It doesn't deviate from the examples on the [thor home](http://whatisthor.com/), though. – tompave Apr 17 '13 at 18:34

1 Answers1

1

If you look at the error message:

 Ambiguous command h matches [hello, help]

The above means, for h, thor is finding more than one matches. This is due to help command already defined(built-in).

Instead of trying to monkey patch way around it, I would suggest you use the built-in help command to show help & options on what your CLI tool does.

To get one letter command shortcuts working - you should name your command not to start from letter h, like foo or bar, yo & so on etc.

In case if you want have commands starting from letter h, just be more specific.

CuriousMind
  • 33,537
  • 28
  • 98
  • 137
  • Thank you for the suggestion. Yes, it makes sense, but the question was more about preventing the ruby backtrace to be shown _in general_, and not just in this specific care. Still, cheers for the late answer. – tompave Nov 27 '16 at 15:34