Skip to content

Thoughts on passing flags down to subcommands? #27

Description

@danopia

Clear and concise description of the problem

In a program which exposes multiple commands and/or subcommands, flags from higher up don't seem to get passed down at all. I have a program with one --config flag which should be shared. I'd like to understand how a shared flag should behave.

In the below example, each command has its own flag of a matching name. I'd expect invocations like this to work:

aaa bbb ccc # no flags: {}
aaa bbb ccc --cc=1 # flag for subcommand: {cc: 1}
aaa bbb --bb=1 ccc # flag for middle command: {bb: 1}
aaa bbb ccc --bb=1 # flag for middle command, at the end: {bb: 1}
aaa --aa=1 bbb ccc # flag for main command: {aa: 1}

However, the actual results are like this:

aaa bbb ccc # subcommand run with {}
aaa bbb ccc --cc=1 # subcommand run with {cc:1}
aaa bbb --bb=1 ccc # help shown for 'bbb', including 'ccc' subcommand and '--bb' flag
                   # should instead run subcommand with {bb:1}
aaa bbb ccc --bb=1 # "Unknown flags found." showing that --bb isn't declared
                   # should instead run subcommand with {bb:1}
aaa --aa=1 bbb ccc # help shown for 'aaa', including 'bbb' subcommand and '--aa' flag
                   # should instead run subcommand with {aa:1}

My test program:

import { defineCommand, komando } from "https://deno.land/x/komando@v1.0.2/mod.js";

komando({
  name: 'aaa',
  flags: {
    'aa': { typeFn: String },
  },
  commands: [

    defineCommand({
      name: 'bbb',
      flags: {
        'bb': { typeFn: String },
      },
      commands: [

        defineCommand({
          name: 'ccc',
          flags: {
            'cc': { typeFn: String },
          },
          run: (args, flags) => console.log(flags),
        }),
      ],
    }),
  ],
});

And the help output is currently this:

$ aaa bbb ccc --help

  Usage
    $ aaa bbb ccc [flags]

  Flags
        --cc <cc>

  Inherited Flags
    -h, --help       Show this message

Suggested solution

I'd propose that a command's flags can be parsed before looking up a subcommand, and the results merged into the flags object that is given to the subcommand.

Unfortunately this doesn't help types at all. I think the best way to make types happy is redeclaring the inheritable flags? It's not great, but it's probably workable.

Alternative

If flags can be given at any point (such as aaa --cc=3 bbb ccc in my example) then it wouldn't matter where they are declared / if they get handed down. Then flag inheritance could be emulated by the program. This is probably pretty messy to parse.

Additional context

In my real program I've been simply declaring all applicable flags in each subcommand. The primary issue with this is that all flags are only allowed at the end. When a particular flag is applicable to every subcommand, I want to specify it near the beginning of the command to make shell history more useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions