Skip to content

Ignore/pass over the double dash (--) marker #1340

Closed

Description

@Higgcz

I'm working on a command line application which includes something like ssh wrapper. Basically what I'm doing is I'm resolving hostname myself, but then I want to pass all other parameters to the underlying ssh command. However, I've noticed that Click is consuming the first double dash (--) marker.

I was hoping Click has somewhere a variable containing all unprocessed arguments, but apparently, that's not the case, or at least I couldn't find it. So, in the end, I ended up adding one more click.Context option called ignore_end_of_the_opts_marker that tells Click to pass over the double dash, so if you combine it with ignore_unknown_options, you can pick all unprocessed arguments.

Eg.:

@click.command(context_settings=dict(
    ignore_unknown_options=True,
    ignore_end_of_the_opts_marker=True
    ))
@click.argument('args', nargs=-1, type=click.UNPROCESSED)
@click.pass_context
def cli(ctx, args):
    print('All the arguments:', args)

I've noticed some people are also writing wrapper-like tools, so maybe more people would be interested in this option.

So far, I'm not sure if it's worth a Pull Request, let me know if it is, I've tried to document everything consistently with the rest of the code, but I can imagine there could be a better name for this option. Or maybe you have a better idea of how to solve this issue.

Anyway, if someone is interested, here is my fork: https://github.com/Higgcz/click

Activity

  1. adzenith commented on Dec 16, 2020

    @adzenith

    Thoughts on making this into a PR? I would love to see this in upstream click.

  2. Midnighter commented on Jun 24, 2021

    @Midnighter
  3. sashati commented on Sep 23, 2021

    @sashati
  4. POD666 commented on Oct 4, 2021

    @POD666

    I end up with the following snippet:

    class HandleDoubleDashArg(click.Group):
        def parse_args(self, ctx, args):
            if "--" in args:
                # concat all options that follow double dash into tuple
                double_dash_idx = args.index("--")
                args = args[:double_dash_idx] + [tuple(args[double_dash_idx + 1 :])]
                # ['--arg', '123', '--', 'qwe', 'rty'] -> ['--arg', '123', ('qwe', 'rty')]
            elif "--help" in args:
                pass  # skip if help is requested
            else:
                # trick: feed an empty string as positional argument
                # so that the latests from args is considered as child command
    
                # find child command
                for child_command in self.commands:
                    if child_command in args:
                        idx = args.index(child_command)
                        args.insert(idx, ())
                        # ['--arg', '123', 'my_child_command'] -> ['--arg', '123', (), 'my_child_command']
                        break
                else:
                    # TODO: to be improved
                    args.insert(-1, ())
                    # ['--arg', '123', 'qwerty'] -> ['--arg', '123', (), 'qwerty']
                    # -> should lead to `Error: No such command 'qwerty'`
                    # ['--arg', '123', 'qwerty', '--qwe'] -> ['--arg', '123', 'qwerty', (), '--qwe']
                    # -> Error: No such command '()'.
                    # ['--arg', '123', 'qwerty', '--qwe', '--rty'] -> ['--arg', '123', 'qwerty', '--qwe', (), '--rty']
                    # -> Error: No such command '--qwe'.
            super(HandleDoubleDashArg, self).parse_args(ctx, args)
    
    
    @click.group(cls=HandleDoubleDashArg, invoke_without_command=True)
    @click.option("--arg")
    @click.argument("double_dash_args")
    @click.pass_context
    def my_group_command(ctx, double_dash_args):
        # ...
        if ctx.invoked_subcommand is None:
            # ...
            pass
    
    
    @my_group_command.command()
    def my_child_command(ctx):
        # ...
        pass

    It's limited to my use case but might be helpful.

  5. davidism commented on Feb 27, 2022

    @davidism
    Member

    Pretty much a duplicate of #619, see additional discussion there. Just like if you need to pass an argument that looks like an option, use -- if you need to pass a -- as an argument.

    wrapper -- ssh -v -- bash -c ...
    
  6. locked as resolved and limited conversation to collaborators on Mar 14, 2022
  7. added
    parsingParsing, parameters, commands, chaining, context
    on Aug 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    parsingParsing, parameters, commands, chaining, context

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions