Skip to content

Commands registration and commands section #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
noraj opened this issue Nov 4, 2023 · 3 comments
Closed

Commands registration and commands section #12

noraj opened this issue Nov 4, 2023 · 3 comments
Labels
enhancement New feature or request

Comments

@noraj
Copy link

noraj commented Nov 4, 2023

Describe the problem

Having :commands section would help a lot.

Right now it's a pain for:

  1. registering all commands
  2. registering and dynamically filling a commands section

Here is what I ended up doing (example for 1 command).

In my binary:

ilc = CyberMots::ILC::Commandes.new
ilc.parse(ARGV)
ilc.lance

The default root command:

...
      usage do
        no_command
        program 'cybermots'
        desc 'YAKA une description'
      end
...
      def lance
        if params.errors.any?
          puts params.errors.summary
        else
          cmd, args = case ARGV[0]
                      when 'maj'
                        [Maj.new, ARGV[1..]]
                      end

          if cmd.nil?
            if params[:version]
              puts "CyberMots version #{CyberMots::VERSION}"
            else
              h = help(width: ILC::LARGEUR_TERM) do |sections|
                sections.add_after :description, :commandes, <<~COMMANDES.chomp

                  Commandes :
                    #{Maj.command.first} : #{Maj.desc.first.first}
                COMMANDES
              end
              print h
            end
          else
            cmd.parse args
            cmd.lance
          end
        end
      end

Because I want that when the root pseudo-command (no command) help is triggered, to display a section with all available commands.

➜ cybermots -a
Utilisation : cybermots [OPTIONS]

YAKA une description

Commandes :
  maj : Met à jour le dictionnaire

Options :
  -a, --aide     Affiche l'aide
  -v, --version  Affiche la version

But of course I'm not injection any commands section on commands themselves (unless of course the command would have sub commands).

➜ cybermots maj -a
Utilisation : cybermots maj [OPTIONS]

Met à jour le dictionnaire

Options :
  -a, --aide  Affiche l'aide

Random example I found from a gem to register several commands:

https://github.com/OfficialPhilcomm/staticz/blob/1eaa3945f48f81138c129e73c303f9bf975f3318/lib/staticz.rb#L9-L25

Then this gem hacks into the description section to inject a pseudo commands section which is 100% static

https://github.com/OfficialPhilcomm/staticz/blob/1eaa3945f48f81138c129e73c303f9bf975f3318/lib/commands/base_command.rb#L11-L17

Of course the most official way to do it right now is using sections.add_after :description, :commands but it's static too unless you inject each command name and description.

Here another example where one preferred not to use tty-options to craft a default command that will list all available commands while it uses tty-options for all other commands.

https://github.com/smashwilson/branchtree/blob/dc0a24f3841169da224ee2a883b1a9a77b244525/lib/branchtree.rb#L6-L28

How would the new feature work?

I don't know but in the past I use dry-cli that has a way to register commands so there is no need to hack into ARGV.

Example in production, registering commands is as easy as this clean mapping and it will automatically display a commands section.

Here another original very complex way of doing it dynamically

https://github.com/MadBomber/sqa/blob/main/lib/sqa/cli.rb

Seems that every one try to hack very hard around this common issue.

Drawbacks

I don't see any.

@noraj noraj added the enhancement New feature or request label Nov 4, 2023
@piotrmurach
Copy link
Owner

Hi Alexandre 👋

Thanks for giving this gem a try.

This gem, in terms of scope, is complete. I plan to add more DSL goodies to make it easier to use, for example, to specify conflicting options. However, I don't expect the shape of it to change much. Only to become more polished with time.

This means that it will never support commands. Like many of tty components, they are all focused on doing one thing well and being as composable as possible.

As for creating CLI applications with commands, I've tried to answer this in the closed issue. Please have a read when you get a moment. Essentially, the commands will be handled by another library. However, as I developed the tty-runner I realised a few things. The most crucial was the handling of dependencies in commands. I'm in the process of figuring out how the dependency injection may work. Unfortunately, I can't give you any estimates.

In the meantime, if you want to support commands, there is a discussion that may help you out.

@noraj
Copy link
Author

noraj commented Nov 6, 2023

I see, so commands are not in the scope of tty-options but that's something for tty-runner. Do you plan to release it someday? Or should I ally tty-options for buildings single commands and dry-cli for managing all commands?

Thanks for the pointers.

Thanks for giving this gem a try.

Yeah, I'm a big user of docopt.rb which is just awesome and magic for simple applications, but it soon begins to be limited when you wan't to build complex application, as, for example, options will conflict between commands etc. For one project with multiple commands I gave a try to dry-cli (which is part of dry-rb that tries to achieve something similar to ttytoolkit) which is very good for building many commands but severely lacks of tons of essential features that are included in tty-options. So if you think tty-runner is not ready maybe using tty-options and dry-cli could complete each other well.

@piotrmurach
Copy link
Owner

Do you plan to release it someday?

Of course, but there are a few thorny issues that I first need to figure out like the aforementioned dependencies handling in commands. It will require writing a separate gem to deal with this part of the issue. But please don't wait for tty-runner release. Give it a star and check in from time to time.

Or should I ally tty-options for buildings single commands and dry-cli for managing all commands?

I'm not sure that's possible. As far as I can tell, the dry-cli uses optparse under the covers. That's why I built tty-option from the ground up to allow me full freedom in shaping it into a powerful DSL. I'm not clear how would you integrate the two. If you manage, please let me know.

I gave a try to dry-cli (which is part of dry-rb that tries to achieve something similar to ttytoolkit)

The dry-rb and ttytoolkit goals couldn't be more different. The ttytoolkit aims to be a collection of gems to ease building terminal applications(prompts, spinners, progress bars etc). The ultimate goal is for TTY, sorry for the cliche, to be similar to Rails in terms of ergonomics and conventions. So you can scaffold quickly command line applications that can be arbitrarily complex, e.i. docker type of interface. That's why, for example, the tty-option exposes params to allow universal access to all the command line parsed inputs. Once it all comes together it will be glorious day 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants