File: argparse_completion.py

package info (click to toggle)
cmd2 3.2.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 2,664 kB
  • sloc: python: 17,488; makefile: 114; sh: 39; javascript: 7
file content (132 lines) | stat: -rwxr-xr-x 4,937 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/env python
"""A simple example demonstrating how to integrate tab completion with argparse-based commands."""

import argparse

import rich.box
from rich.style import Style
from rich.table import Table
from rich.text import Text

from cmd2 import (
    Cmd,
    Cmd2ArgumentParser,
    Cmd2Style,
    Color,
    CompletionError,
    CompletionItem,
    with_argparser,
)

# Data source for argparse.choices
food_item_strs = ['Pizza', 'Ham', 'Ham Sandwich', 'Potato']


class ArgparseCompletion(Cmd):
    def __init__(self) -> None:
        super().__init__(include_ipy=True)
        self.sport_item_strs = ['Bat', 'Basket', 'Basketball', 'Football', 'Space Ball']

    def choices_provider(self) -> list[str]:
        """A choices provider is useful when the choice list is based on instance data of your application."""
        return self.sport_item_strs

    def choices_completion_error(self) -> list[str]:
        """CompletionErrors can be raised if an error occurs while tab completing.

        Example use cases
            - Reading a database to retrieve a tab completion data set failed
            - A previous command line argument that determines the data set being completed is invalid
        """
        if self.debug:
            return self.sport_item_strs
        raise CompletionError("debug must be true")

    def choices_completion_item(self) -> list[CompletionItem]:
        """Return CompletionItem instead of strings. These give more context to what's being tab completed."""
        fancy_item = Text.assemble(
            "These things can\ncontain newlines and\n",
            Text("styled text!!", style=Style(color=Color.BRIGHT_YELLOW, underline=True)),
        )

        table_item = Table(
            "Left Column",
            "Right Column",
            box=rich.box.ROUNDED,
            border_style=Cmd2Style.TABLE_BORDER,
        )
        table_item.add_row("Yes, it's true.", "CompletionItems can")
        table_item.add_row("even display description", "data in tables!")

        items = {
            1: "My item",
            2: "Another item",
            3: "Yet another item",
            4: fancy_item,
            5: table_item,
        }
        return [CompletionItem(item_id, [description]) for item_id, description in items.items()]

    def choices_arg_tokens(self, arg_tokens: dict[str, list[str]]) -> list[str]:
        """If a choices or completer function/method takes a value called arg_tokens, then it will be
        passed a dictionary that maps the command line tokens up through the one being completed
        to their argparse argument name.  All values of the arg_tokens dictionary are lists, even if
        a particular argument expects only 1 token.
        """
        # Check if choices_provider flag has appeared
        values = ['choices_provider', 'flag']
        if 'choices_provider' in arg_tokens:
            values.append('is {}'.format(arg_tokens['choices_provider'][0]))
        else:
            values.append('not supplied')
        return values

    # Parser for example command
    example_parser = Cmd2ArgumentParser(
        description="Command demonstrating tab completion with argparse\nNotice even the flags of this command tab complete"
    )

    # Tab complete from a list using argparse choices. Set metavar if you don't
    # want the entire choices list showing in the usage text for this command.
    example_parser.add_argument('--choices', choices=food_item_strs, metavar="CHOICE", help="tab complete using choices")

    # Tab complete from choices provided by a choices_provider
    example_parser.add_argument(
        '--choices_provider', choices_provider=choices_provider, help="tab complete using a choices_provider"
    )

    # Tab complete using a completer
    example_parser.add_argument('--completer', completer=Cmd.path_complete, help="tab complete using a completer")

    # Demonstrate raising a CompletionError while tab completing
    example_parser.add_argument(
        '--completion_error',
        choices_provider=choices_completion_error,
        help="raise a CompletionError while tab completing if debug is False",
    )

    # Demonstrate returning CompletionItems instead of strings
    example_parser.add_argument(
        '--completion_item',
        choices_provider=choices_completion_item,
        metavar="ITEM_ID",
        descriptive_headers=["Description"],
        help="demonstrate use of CompletionItems",
    )

    # Demonstrate use of arg_tokens dictionary
    example_parser.add_argument(
        '--arg_tokens', choices_provider=choices_arg_tokens, help="demonstrate use of arg_tokens dictionary"
    )

    @with_argparser(example_parser)
    def do_example(self, _: argparse.Namespace) -> None:
        """The example command."""
        self.poutput("I do nothing")


if __name__ == '__main__':
    import sys

    app = ArgparseCompletion()
    sys.exit(app.cmdloop())