Namespacing thor commands in a standalone ruby executable

后端 未结 2 1461
遥遥无期
遥遥无期 2021-01-31 11:23

When calling thor commands on the command line, the methods are namespaced by their module/class structure, e.g.

class App < Thor
  desc \'hello\', \'prints h         


        
相关标签:
2条回答
  • 2021-01-31 11:53

    Another way of doing this is to use register:

    class CLI < Thor
      register(SubTask, 'sub', 'sub <command>', 'Description.')
    end
    
    class SubTask < Thor
      desc "bar", "..."
      def bar()
        # ...
      end
    end
    
    CLI.start
    

    Now - assuming your executable is called foo - you can call:

    $ foo sub bar
    

    In the current thor version (0.15.0.rc2) there is a bug though, which causes the help texts to skip the namespace of sub commands:

    $ foo sub
    Tasks:
       foo help [COMMAND]  # Describe subcommands or one specific subcommand
       foo bar             #
    

    You can fix that by overriding self.banner and explicitly setting the namespace.

    class SubTask < Thor
      namespace :sub
    
      def bar ...
    
      def self.banner(task, namespace = true, subcommand = false)
        "#{basename} #{task.formatted_usage(self, true, subcommand)}"
      end
    end
    

    The second parameter of formatted_usage is the only difference to the original implemtation of banner. You can also do this once and have other sub command thor classes inherit from SubTask. Now you get:

    $ foo sub
    Tasks:
       foo sub help [COMMAND]  # Describe subcommands or one specific subcommand
       foo sub bar             #
    

    Hope that helps.

    0 讨论(0)
  • 2021-01-31 11:56

    This is one way with App as the default namespace (quite hacky though):

    #!/usr/bin/env ruby
    require "rubygems"
    require "thor"
    
    class Say < Thor
      # ./app say:hello
      desc 'hello', 'prints hello'
      def hello
        puts 'hello'
      end
    end
    
    class App < Thor
      # ./app nothing
      desc 'nothing', 'does nothing'
      def nothing
        puts 'doing nothing'
      end
    end
    
    begin
      parts = ARGV[0].split(':')
      namespace = Kernel.const_get(parts[0].capitalize)
      parts.shift
      ARGV[0] = parts.join
      namespace.start
    rescue
      App.start
    end
    

    Or, also not ideal:

    define_method 'say:hello'
    
    0 讨论(0)
提交回复
热议问题