Skip to content

Commit aa546af

Browse files
authored
Merge pull request #499 from python-cmd2/autocomp_init
Copied and reduced the tab_autocompletion example to specifically exe…
2 parents 7a24851 + ec02165 commit aa546af

File tree

1 file changed

+240
-0
lines changed

1 file changed

+240
-0
lines changed

examples/tab_autocomp_dynamic.py

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
#!/usr/bin/env python3
2+
# coding=utf-8
3+
"""
4+
A example usage of AutoCompleter with delayed initialization of the argparse object
5+
6+
Copyright 2018 Eric Lin <[email protected]>
7+
Released under MIT license, see LICENSE file
8+
"""
9+
import argparse
10+
import itertools
11+
from typing import List
12+
13+
import cmd2
14+
from cmd2 import argparse_completer
15+
16+
actors = ['Mark Hamill', 'Harrison Ford', 'Carrie Fisher', 'Alec Guinness', 'Peter Mayhew',
17+
'Anthony Daniels', 'Adam Driver', 'Daisy Ridley', 'John Boyega', 'Oscar Isaac',
18+
'Lupita Nyong\'o', 'Andy Serkis', 'Liam Neeson', 'Ewan McGregor', 'Natalie Portman',
19+
'Jake Lloyd', 'Hayden Christensen', 'Christopher Lee']
20+
21+
22+
def query_actors() -> List[str]:
23+
"""Simulating a function that queries and returns a completion values"""
24+
return actors
25+
26+
27+
class TabCompleteExample(cmd2.Cmd):
28+
""" Example cmd2 application where we a base command which has a couple subcommands."""
29+
30+
CAT_AUTOCOMPLETE = 'AutoComplete Examples'
31+
32+
def __init__(self):
33+
super().__init__()
34+
35+
video_types_subparsers = TabCompleteExample.video_parser.add_subparsers(title='Media Types', dest='type')
36+
37+
vid_movies_parser = argparse_completer.ACArgumentParser(prog='movies')
38+
vid_movies_parser.set_defaults(func=TabCompleteExample._do_vid_media_movies)
39+
40+
vid_movies_commands_subparsers = vid_movies_parser.add_subparsers(title='Commands', dest='command')
41+
42+
vid_movies_list_parser = vid_movies_commands_subparsers.add_parser('list')
43+
44+
vid_movies_list_parser.add_argument('-t', '--title', help='Title Filter')
45+
vid_movies_list_parser.add_argument('-r', '--rating', help='Rating Filter', nargs='+',
46+
choices=TabCompleteExample.ratings_types)
47+
# save a reference to the action object
48+
director_action = vid_movies_list_parser.add_argument('-d', '--director', help='Director Filter')
49+
actor_action = vid_movies_list_parser.add_argument('-a', '--actor', help='Actor Filter', action='append')
50+
51+
# tag the action objects with completion providers. This can be a collection or a callable
52+
setattr(director_action, argparse_completer.ACTION_ARG_CHOICES, TabCompleteExample.static_list_directors)
53+
setattr(actor_action, argparse_completer.ACTION_ARG_CHOICES, query_actors)
54+
55+
vid_movies_add_parser = vid_movies_commands_subparsers.add_parser('add')
56+
vid_movies_add_parser.add_argument('title', help='Movie Title')
57+
vid_movies_add_parser.add_argument('rating', help='Movie Rating', choices=TabCompleteExample.ratings_types)
58+
59+
# save a reference to the action object
60+
director_action = vid_movies_add_parser.add_argument('-d', '--director', help='Director', nargs=(1, 2),
61+
required=True)
62+
actor_action = vid_movies_add_parser.add_argument('actor', help='Actors', nargs='*')
63+
64+
vid_movies_load_parser = vid_movies_commands_subparsers.add_parser('load')
65+
vid_movie_file_action = vid_movies_load_parser.add_argument('movie_file', help='Movie database')
66+
67+
vid_movies_read_parser = vid_movies_commands_subparsers.add_parser('read')
68+
vid_movie_fread_action = vid_movies_read_parser.add_argument('movie_file', help='Movie database')
69+
70+
# tag the action objects with completion providers. This can be a collection or a callable
71+
setattr(director_action, argparse_completer.ACTION_ARG_CHOICES, TabCompleteExample.static_list_directors)
72+
setattr(actor_action, argparse_completer.ACTION_ARG_CHOICES, 'instance_query_actors')
73+
74+
# tag the file property with a custom completion function 'delimeter_complete' provided by cmd2.
75+
setattr(vid_movie_file_action, argparse_completer.ACTION_ARG_CHOICES,
76+
('delimiter_complete',
77+
{'delimiter': '/',
78+
'match_against': TabCompleteExample.file_list}))
79+
setattr(vid_movie_fread_action, argparse_completer.ACTION_ARG_CHOICES,
80+
('path_complete', [False, False]))
81+
82+
vid_movies_delete_parser = vid_movies_commands_subparsers.add_parser('delete')
83+
vid_delete_movie_id = vid_movies_delete_parser.add_argument('movie_id', help='Movie ID')
84+
setattr(vid_delete_movie_id, argparse_completer.ACTION_ARG_CHOICES, TabCompleteExample.instance_query_movie_ids)
85+
setattr(vid_delete_movie_id, argparse_completer.ACTION_DESCRIPTIVE_COMPLETION_HEADER, 'Title')
86+
87+
# Add the 'movies' parser as a parent of sub-parser
88+
video_types_subparsers.add_parser('movies', parents=[vid_movies_parser], add_help=False)
89+
90+
91+
92+
vid_shows_parser = argparse_completer.ACArgumentParser(prog='shows')
93+
vid_shows_parser.set_defaults(func=TabCompleteExample._do_vid_media_shows)
94+
95+
vid_shows_commands_subparsers = vid_shows_parser.add_subparsers(title='Commands', dest='command')
96+
97+
vid_shows_list_parser = vid_shows_commands_subparsers.add_parser('list')
98+
99+
video_types_subparsers.add_parser('shows', parents=[vid_shows_parser], add_help=False)
100+
101+
102+
# For mocking a data source for the example commands
103+
ratings_types = ['G', 'PG', 'PG-13', 'R', 'NC-17']
104+
show_ratings = ['TV-Y', 'TV-Y7', 'TV-G', 'TV-PG', 'TV-14', 'TV-MA']
105+
static_list_directors = ['J. J. Abrams', 'Irvin Kershner', 'George Lucas', 'Richard Marquand',
106+
'Rian Johnson', 'Gareth Edwards']
107+
USER_MOVIE_LIBRARY = ['ROGUE1', 'SW_EP04', 'SW_EP05']
108+
MOVIE_DATABASE_IDS = ['SW_EP1', 'SW_EP02', 'SW_EP03', 'ROGUE1', 'SW_EP04',
109+
'SW_EP05', 'SW_EP06', 'SW_EP07', 'SW_EP08', 'SW_EP09']
110+
MOVIE_DATABASE = {'SW_EP04': {'title': 'Star Wars: Episode IV - A New Hope',
111+
'rating': 'PG',
112+
'director': ['George Lucas'],
113+
'actor': ['Mark Hamill', 'Harrison Ford', 'Carrie Fisher',
114+
'Alec Guinness', 'Peter Mayhew', 'Anthony Daniels']
115+
},
116+
'SW_EP05': {'title': 'Star Wars: Episode V - The Empire Strikes Back',
117+
'rating': 'PG',
118+
'director': ['Irvin Kershner'],
119+
'actor': ['Mark Hamill', 'Harrison Ford', 'Carrie Fisher',
120+
'Alec Guinness', 'Peter Mayhew', 'Anthony Daniels']
121+
},
122+
'SW_EP06': {'title': 'Star Wars: Episode VI - Return of the Jedi',
123+
'rating': 'PG',
124+
'director': ['Richard Marquand'],
125+
'actor': ['Mark Hamill', 'Harrison Ford', 'Carrie Fisher',
126+
'Alec Guinness', 'Peter Mayhew', 'Anthony Daniels']
127+
},
128+
'SW_EP1': {'title': 'Star Wars: Episode I - The Phantom Menace',
129+
'rating': 'PG',
130+
'director': ['George Lucas'],
131+
'actor': ['Liam Neeson', 'Ewan McGregor', 'Natalie Portman', 'Jake Lloyd']
132+
},
133+
'SW_EP02': {'title': 'Star Wars: Episode II - Attack of the Clones',
134+
'rating': 'PG',
135+
'director': ['George Lucas'],
136+
'actor': ['Liam Neeson', 'Ewan McGregor', 'Natalie Portman',
137+
'Hayden Christensen', 'Christopher Lee']
138+
},
139+
'SW_EP03': {'title': 'Star Wars: Episode III - Revenge of the Sith',
140+
'rating': 'PG-13',
141+
'director': ['George Lucas'],
142+
'actor': ['Liam Neeson', 'Ewan McGregor', 'Natalie Portman',
143+
'Hayden Christensen']
144+
},
145+
146+
}
147+
USER_SHOW_LIBRARY = {'SW_REB': ['S01E01', 'S02E02']}
148+
SHOW_DATABASE_IDS = ['SW_CW', 'SW_TCW', 'SW_REB']
149+
SHOW_DATABASE = {'SW_CW': {'title': 'Star Wars: Clone Wars',
150+
'rating': 'TV-Y7',
151+
'seasons': {1: ['S01E01', 'S01E02', 'S01E03'],
152+
2: ['S02E01', 'S02E02', 'S02E03']}
153+
},
154+
'SW_TCW': {'title': 'Star Wars: The Clone Wars',
155+
'rating': 'TV-PG',
156+
'seasons': {1: ['S01E01', 'S01E02', 'S01E03'],
157+
2: ['S02E01', 'S02E02', 'S02E03']}
158+
},
159+
'SW_REB': {'title': 'Star Wars: Rebels',
160+
'rating': 'TV-Y7',
161+
'seasons': {1: ['S01E01', 'S01E02', 'S01E03'],
162+
2: ['S02E01', 'S02E02', 'S02E03']}
163+
},
164+
}
165+
166+
file_list = \
167+
[
168+
'/home/user/file.db',
169+
'/home/user/file space.db',
170+
'/home/user/another.db',
171+
'/home/other user/maps.db',
172+
'/home/other user/tests.db'
173+
]
174+
175+
def instance_query_actors(self) -> List[str]:
176+
"""Simulating a function that queries and returns a completion values"""
177+
return actors
178+
179+
def instance_query_movie_ids(self) -> List[str]:
180+
"""Demonstrates showing tabular hinting of tab completion information"""
181+
completions_with_desc = []
182+
183+
for movie_id in self.MOVIE_DATABASE_IDS:
184+
if movie_id in self.MOVIE_DATABASE:
185+
movie_entry = self.MOVIE_DATABASE[movie_id]
186+
completions_with_desc.append(argparse_completer.CompletionItem(movie_id, movie_entry['title']))
187+
188+
return completions_with_desc
189+
190+
191+
###################################################################################
192+
# The media command demonstrates a completer with multiple layers of subcommands
193+
# - This example demonstrates how to tag a completion attribute on each action, enabling argument
194+
# completion without implementing a complete_COMMAND function
195+
196+
def _do_vid_media_movies(self, args) -> None:
197+
if not args.command:
198+
self.do_help('video movies')
199+
elif args.command == 'list':
200+
for movie_id in TabCompleteExample.MOVIE_DATABASE:
201+
movie = TabCompleteExample.MOVIE_DATABASE[movie_id]
202+
print('{}\n-----------------------------\n{} ID: {}\nDirector: {}\nCast:\n {}\n\n'
203+
.format(movie['title'], movie['rating'], movie_id,
204+
', '.join(movie['director']),
205+
'\n '.join(movie['actor'])))
206+
207+
def _do_vid_media_shows(self, args) -> None:
208+
if not args.command:
209+
self.do_help('video shows')
210+
211+
elif args.command == 'list':
212+
for show_id in TabCompleteExample.SHOW_DATABASE:
213+
show = TabCompleteExample.SHOW_DATABASE[show_id]
214+
print('{}\n-----------------------------\n{} ID: {}'
215+
.format(show['title'], show['rating'], show_id))
216+
for season in show['seasons']:
217+
ep_list = show['seasons'][season]
218+
print(' Season {}:\n {}'
219+
.format(season,
220+
'\n '.join(ep_list)))
221+
print()
222+
223+
video_parser = argparse_completer.ACArgumentParser(prog='video')
224+
225+
@cmd2.with_category(CAT_AUTOCOMPLETE)
226+
@cmd2.with_argparser(video_parser)
227+
def do_video(self, args):
228+
"""Video management command demonstrates multiple layers of subcommands being handled by AutoCompleter"""
229+
func = getattr(args, 'func', None)
230+
if func is not None:
231+
# Call whatever subcommand function was selected
232+
func(self, args)
233+
else:
234+
# No subcommand was provided, so call help
235+
self.do_help('video')
236+
237+
238+
if __name__ == '__main__':
239+
app = TabCompleteExample()
240+
app.cmdloop()

0 commit comments

Comments
 (0)