Skip to content

Commit c21bdb1

Browse files
committed
Removed flag_based_complete and index_based_complete functions.
1 parent ea128a7 commit c21bdb1

File tree

6 files changed

+7
-315
lines changed

6 files changed

+7
-315
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ shell, and the option for a persistent bottom bar that can display realtime stat
3838
1. `Cmd.formatted_completions` -> `Completions.completion_table`
3939
1. `Cmd.matches_delimited` -> `Completions.is_delimited`
4040
1. `Cmd.allow_appended_space/allow_closing_quote` -> `Completions.allow_finalization`
41+
- Removed `flag_based_complete` and `index_based_complete` functions since their functionality
42+
is already provided in arpgarse-based completion.
4143
- Enhancements
4244
- New `cmd2.Cmd` parameters
4345
- **auto_suggest**: (boolean) if `True`, provide fish shell style auto-suggestions. These

cmd2/cmd2.py

Lines changed: 0 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1895,100 +1895,6 @@ def delimiter_complete(
18951895

18961896
return Completions(items, allow_finalization=allow_finalization, is_delimited=True)
18971897

1898-
def flag_based_complete(
1899-
self,
1900-
text: str,
1901-
line: str,
1902-
begidx: int,
1903-
endidx: int,
1904-
flag_dict: dict[str, Iterable[Matchable] | CompleterBound],
1905-
*,
1906-
all_else: None | Iterable[Matchable] | CompleterBound = None,
1907-
) -> Completions:
1908-
"""Completes based on a particular flag preceding the token being completed.
1909-
1910-
:param text: the string prefix we are attempting to match (all matches must begin with it)
1911-
:param line: the current input line with leading whitespace removed
1912-
:param begidx: the beginning index of the prefix text
1913-
:param endidx: the ending index of the prefix text
1914-
:param flag_dict: dictionary whose structure is the following:
1915-
`keys` - flags (ex: -c, --create) that result in completion for the next argument in the
1916-
command line
1917-
`values` - there are two types of values:
1918-
1. iterable of Matchables to match against
1919-
2. function that performs completion (ex: path_complete)
1920-
:param all_else: an optional parameter for completing any token that isn't preceded by a flag in flag_dict
1921-
:return: a Completions object
1922-
"""
1923-
# Get all tokens through the one being completed
1924-
tokens, _ = self.tokens_for_completion(line, begidx, endidx)
1925-
if not tokens: # pragma: no cover
1926-
return Completions()
1927-
1928-
match_against = all_else
1929-
1930-
# Must have at least 2 args for a flag to precede the token being completed
1931-
if len(tokens) > 1:
1932-
flag = tokens[-2]
1933-
if flag in flag_dict:
1934-
match_against = flag_dict[flag]
1935-
1936-
# Perform completion using an Iterable
1937-
if isinstance(match_against, Iterable):
1938-
return self.basic_complete(text, line, begidx, endidx, match_against)
1939-
1940-
# Perform completion using a function
1941-
if callable(match_against):
1942-
return match_against(text, line, begidx, endidx)
1943-
1944-
return Completions()
1945-
1946-
def index_based_complete(
1947-
self,
1948-
text: str,
1949-
line: str,
1950-
begidx: int,
1951-
endidx: int,
1952-
index_dict: Mapping[int, Iterable[Matchable] | CompleterBound],
1953-
*,
1954-
all_else: Iterable[Matchable] | CompleterBound | None = None,
1955-
) -> Completions:
1956-
"""Completes based on a fixed position in the input string.
1957-
1958-
:param text: the string prefix we are attempting to match (all matches must begin with it)
1959-
:param line: the current input line with leading whitespace removed
1960-
:param begidx: the beginning index of the prefix text
1961-
:param endidx: the ending index of the prefix text
1962-
:param index_dict: dictionary whose structure is the following:
1963-
`keys` - 0-based token indexes into command line that determine which tokens perform tab
1964-
completion
1965-
`values` - there are two types of values:
1966-
1. iterable of Matchables to match against
1967-
2. function that performs completion (ex: path_complete)
1968-
:param all_else: an optional parameter for completing any token that isn't at an index in index_dict
1969-
:return: a Completions object
1970-
"""
1971-
# Get all tokens through the one being completed
1972-
tokens, _ = self.tokens_for_completion(line, begidx, endidx)
1973-
if not tokens: # pragma: no cover
1974-
return Completions()
1975-
1976-
# Get the index of the token being completed
1977-
index = len(tokens) - 1
1978-
1979-
# Check if token is at an index in the dictionary
1980-
match_against: Iterable[Matchable] | CompleterBound | None = index_dict.get(index, all_else)
1981-
1982-
# Perform completion using a Iterable
1983-
if isinstance(match_against, Iterable):
1984-
return self.basic_complete(text, line, begidx, endidx, match_against)
1985-
1986-
# Perform completion using a function
1987-
if callable(match_against):
1988-
return match_against(text, line, begidx, endidx)
1989-
1990-
return Completions()
1991-
19921898
@staticmethod
19931899
def _complete_users(text: str, add_trailing_sep_if_dir: bool) -> Completions:
19941900
"""Complete ~ and ~user strings.

docs/features/completion.md

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,6 @@ complete_bar = functools.partialmethod(cmd2.Cmd.path_complete, path_filter=os.pa
5656
> [basic_completion](https://github.com/python-cmd2/cmd2/blob/main/examples/basic_completion.py)
5757
> example for a demonstration of how to use this feature
5858
59-
- [flag_based_complete][cmd2.Cmd.flag_based_complete] - helper method for tab completion based on a
60-
particular flag preceding the token being completed
61-
62-
- [index_based_complete][cmd2.Cmd.index_based_complete] - helper method for tab completion based on
63-
a fixed position in the input string
64-
65-
> - See the
66-
> [basic_completion](https://github.com/python-cmd2/cmd2/blob/main/examples/basic_completion.py)
67-
> example for a demonstration of how to use these features
68-
> - `flag_based_complete()` and `index_based_complete()` are basic methods and should only be
69-
> used if you are not familiar with argparse. The recommended approach for tab completing
70-
> positional tokens and flags is to use [argparse-based](#argparse-based) completion.
71-
7259
## Raising Exceptions During Completion
7360

7461
There are times when an error occurs while tab completing and a message needs to be reported to the

examples/basic_completion.py

Lines changed: 5 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
11
#!/usr/bin/env python
22
"""A simple example demonstrating how to enable tab completion by assigning a completer function to do_* commands.
3+
34
This also demonstrates capabilities of the following completer features included with cmd2:
45
- CompletionError exceptions
56
- delimiter_complete()
6-
- flag_based_complete() (see note below)
7-
- index_based_complete() (see note below).
87
9-
flag_based_complete() and index_based_complete() are basic methods and should only be used if you are not
10-
familiar with argparse. The recommended approach for tab completing positional tokens and flags is to use
11-
argparse-based completion. For an example integrating tab completion with argparse, see argparse_completion.py
8+
The recommended approach for tab completing is to use argparse-based completion.
9+
For an example integrating tab completion with argparse, see argparse_completion.py.
1210
"""
1311

1412
import functools
13+
from typing import NoReturn
1514

1615
import cmd2
17-
from cmd2 import Completions
18-
19-
# List of strings used with completion functions
20-
food_item_strs = ['Pizza', 'Ham', 'Ham Sandwich', 'Potato']
21-
sport_item_strs = ['Bat', 'Basket', 'Basketball', 'Football', 'Space Ball']
2216

2317
# This data is used to demonstrate delimiter_complete
2418
file_strs = [
@@ -34,44 +28,6 @@ class BasicCompletion(cmd2.Cmd):
3428
def __init__(self) -> None:
3529
super().__init__(auto_suggest=False, include_py=True)
3630

37-
def do_flag_based(self, statement: cmd2.Statement) -> None:
38-
"""Tab completes arguments based on a preceding flag using flag_based_complete
39-
-f, --food [completes food items]
40-
-s, --sport [completes sports]
41-
-p, --path [completes local file system paths].
42-
"""
43-
self.poutput(f"Args: {statement.args}")
44-
45-
def complete_flag_based(self, text, line, begidx, endidx) -> Completions:
46-
"""Completion function for do_flag_based."""
47-
flag_dict = {
48-
# Tab complete food items after -f and --food flags in command line
49-
'-f': food_item_strs,
50-
'--food': food_item_strs,
51-
# Tab complete sport items after -s and --sport flags in command line
52-
'-s': sport_item_strs,
53-
'--sport': sport_item_strs,
54-
# Tab complete using path_complete function after -p and --path flags in command line
55-
'-p': self.path_complete,
56-
'--path': self.path_complete,
57-
}
58-
59-
return self.flag_based_complete(text, line, begidx, endidx, flag_dict=flag_dict)
60-
61-
def do_index_based(self, statement: cmd2.Statement) -> None:
62-
"""Tab completes first 3 arguments using index_based_complete."""
63-
self.poutput(f"Args: {statement.args}")
64-
65-
def complete_index_based(self, text, line, begidx, endidx) -> Completions:
66-
"""Completion function for do_index_based."""
67-
index_dict = {
68-
1: food_item_strs, # Tab complete food items at index 1 in command line
69-
2: sport_item_strs, # Tab complete sport items at index 2 in command line
70-
3: self.path_complete, # Tab complete using path_complete function at index 3 in command line
71-
}
72-
73-
return self.index_based_complete(text, line, begidx, endidx, index_dict=index_dict)
74-
7531
def do_delimiter_complete(self, statement: cmd2.Statement) -> None:
7632
"""Tab completes files from a list using delimiter_complete."""
7733
self.poutput(f"Args: {statement.args}")
@@ -83,7 +39,7 @@ def do_raise_error(self, statement: cmd2.Statement) -> None:
8339
"""Demonstrates effect of raising CompletionError."""
8440
self.poutput(f"Args: {statement.args}")
8541

86-
def complete_raise_error(self, _text, _line, _begidx, _endidx) -> Completions:
42+
def complete_raise_error(self, _text: str, _line: str, _begidx: int, _endidx: int) -> NoReturn:
8743
"""CompletionErrors can be raised if an error occurs while tab completing.
8844
8945
Example use cases

examples/modular_commands/commandset_basic.py

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@
1111

1212
@with_default_category('Basic Completion')
1313
class BasicCompletionCommandSet(CommandSet):
14-
# List of strings used with completion functions
15-
food_item_strs = ('Pizza', 'Ham', 'Ham Sandwich', 'Potato')
16-
sport_item_strs = ('Bat', 'Basket', 'Basketball', 'Football', 'Space Ball')
17-
1814
# This data is used to demonstrate delimiter_complete
1915
file_strs = (
2016
'/home/user/file.db',
@@ -24,44 +20,6 @@ class BasicCompletionCommandSet(CommandSet):
2420
'/home/other user/tests.db',
2521
)
2622

27-
def do_flag_based(self, statement: Statement) -> None:
28-
"""Tab completes arguments based on a preceding flag using flag_based_complete
29-
-f, --food [completes food items]
30-
-s, --sport [completes sports]
31-
-p, --path [completes local file system paths].
32-
"""
33-
self._cmd.poutput(f"Args: {statement.args}")
34-
35-
def complete_flag_based(self, text: str, line: str, begidx: int, endidx: int) -> list[str]:
36-
"""Completion function for do_flag_based."""
37-
flag_dict = {
38-
# Tab complete food items after -f and --food flags in command line
39-
'-f': self.food_item_strs,
40-
'--food': self.food_item_strs,
41-
# Tab complete sport items after -s and --sport flags in command line
42-
'-s': self.sport_item_strs,
43-
'--sport': self.sport_item_strs,
44-
# Tab complete using path_complete function after -p and --path flags in command line
45-
'-p': self._cmd.path_complete,
46-
'--path': self._cmd.path_complete,
47-
}
48-
49-
return self._cmd.flag_based_complete(text, line, begidx, endidx, flag_dict=flag_dict)
50-
51-
def do_index_based(self, statement: Statement) -> None:
52-
"""Tab completes first 3 arguments using index_based_complete."""
53-
self._cmd.poutput(f"Args: {statement.args}")
54-
55-
def complete_index_based(self, text: str, line: str, begidx: int, endidx: int) -> list[str]:
56-
"""Completion function for do_index_based."""
57-
index_dict = {
58-
1: self.food_item_strs, # Tab complete food items at index 1 in command line
59-
2: self.sport_item_strs, # Tab complete sport items at index 2 in command line
60-
3: self._cmd.path_complete, # Tab complete using path_complete function at index 3 in command line
61-
}
62-
63-
return self._cmd.index_based_complete(text, line, begidx, endidx, index_dict=index_dict)
64-
6523
def do_delimiter_complete(self, statement: Statement) -> None:
6624
"""Tab completes files from a list using delimiter_complete."""
6725
self._cmd.poutput(f"Args: {statement.args}")

tests/test_completion.py

Lines changed: 0 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -137,22 +137,6 @@ def do_alternate(self, args) -> None:
137137
'/home/other user/tests',
138138
]
139139

140-
# Dictionary used with flag based completion functions
141-
flag_dict = {
142-
# Tab complete food items after -f and --food flag in command line
143-
'-f': food_item_strs,
144-
'--food': food_item_strs,
145-
# Tab complete sport items after -s and --sport flag in command line
146-
'-s': sport_item_strs,
147-
'--sport': sport_item_strs,
148-
}
149-
150-
# Dictionary used with index based completion functions
151-
index_dict = {
152-
1: food_item_strs, # Tab complete food items at index 1 in command line
153-
2: sport_item_strs, # Tab complete sport items at index 2 in command line
154-
}
155-
156140

157141
class CompletionsExample(cmd2.Cmd):
158142
"""Example cmd2 application used to exercise tab completion tests"""
@@ -720,107 +704,6 @@ def test_delimiter_completion_nomatch(cmd2_app) -> None:
720704
assert not completions
721705

722706

723-
def test_flag_based_completion(cmd2_app) -> None:
724-
text = 'P'
725-
line = f'list_food -f {text}'
726-
endidx = len(line)
727-
begidx = endidx - len(text)
728-
729-
expected = ['Pizza', 'Potato']
730-
completions = cmd2_app.flag_based_complete(text, line, begidx, endidx, flag_dict)
731-
assert completions.to_strings() == Completions.from_values(expected).to_strings()
732-
733-
734-
def test_flag_based_completion_nomatch(cmd2_app) -> None:
735-
text = 'q'
736-
line = f'list_food -f {text}'
737-
endidx = len(line)
738-
begidx = endidx - len(text)
739-
740-
completions = cmd2_app.flag_based_complete(text, line, begidx, endidx, flag_dict)
741-
assert not completions
742-
743-
744-
def test_flag_based_default_completer(cmd2_app, request) -> None:
745-
test_dir = os.path.dirname(request.module.__file__)
746-
747-
text = os.path.join(test_dir, 'c')
748-
line = f'list_food {text}'
749-
750-
endidx = len(line)
751-
begidx = endidx - len(text)
752-
753-
expected = [text + 'onftest.py']
754-
completions = cmd2_app.flag_based_complete(text, line, begidx, endidx, flag_dict, all_else=cmd2_app.path_complete)
755-
assert completions.to_strings() == Completions.from_values(expected).to_strings()
756-
757-
758-
def test_flag_based_callable_completer(cmd2_app, request) -> None:
759-
test_dir = os.path.dirname(request.module.__file__)
760-
761-
text = os.path.join(test_dir, 'c')
762-
line = f'list_food -o {text}'
763-
764-
endidx = len(line)
765-
begidx = endidx - len(text)
766-
767-
flag_dict['-o'] = cmd2_app.path_complete
768-
769-
expected = [text + 'onftest.py']
770-
completions = cmd2_app.flag_based_complete(text, line, begidx, endidx, flag_dict)
771-
assert completions.to_strings() == Completions.from_values(expected).to_strings()
772-
773-
774-
def test_index_based_completion(cmd2_app) -> None:
775-
text = ''
776-
line = f'command Pizza {text}'
777-
endidx = len(line)
778-
begidx = endidx - len(text)
779-
780-
expected = sport_item_strs
781-
completions = cmd2_app.index_based_complete(text, line, begidx, endidx, index_dict)
782-
assert completions.to_strings() == Completions.from_values(expected).to_strings()
783-
784-
785-
def test_index_based_completion_nomatch(cmd2_app) -> None:
786-
text = 'q'
787-
line = f'command {text}'
788-
endidx = len(line)
789-
begidx = endidx - len(text)
790-
completions = cmd2_app.index_based_complete(text, line, begidx, endidx, index_dict)
791-
assert not completions
792-
793-
794-
def test_index_based_default_completer(cmd2_app, request) -> None:
795-
test_dir = os.path.dirname(request.module.__file__)
796-
797-
text = os.path.join(test_dir, 'c')
798-
line = f'command Pizza Bat Computer {text}'
799-
800-
endidx = len(line)
801-
begidx = endidx - len(text)
802-
803-
expected = [text + 'onftest.py']
804-
completions = cmd2_app.index_based_complete(text, line, begidx, endidx, index_dict, all_else=cmd2_app.path_complete)
805-
assert completions.to_strings() == Completions.from_values(expected).to_strings()
806-
807-
808-
def test_index_based_callable_completer(cmd2_app, request) -> None:
809-
test_dir = os.path.dirname(request.module.__file__)
810-
811-
text = os.path.join(test_dir, 'c')
812-
line = f'command Pizza Bat {text}'
813-
814-
endidx = len(line)
815-
begidx = endidx - len(text)
816-
817-
index_dict[3] = cmd2_app.path_complete
818-
819-
expected = [text + 'onftest.py']
820-
completions = cmd2_app.index_based_complete(text, line, begidx, endidx, index_dict)
821-
assert completions.to_strings() == Completions.from_values(expected).to_strings()
822-
823-
824707
def test_tokens_for_completion_quoted(cmd2_app) -> None:
825708
text = 'Pi'
826709
line = f'list_food "{text}"'

0 commit comments

Comments
 (0)