Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aws
GitHub Repository: aws/aws-cli
Path: blob/develop/awscli/completer.py
1566 views
1
# Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License"). You
4
# may not use this file except in compliance with the License. A copy of
5
# the License is located at
6
#
7
# http://aws.amazon.com/apache2.0/
8
#
9
# or in the "license" file accompanying this file. This file is
10
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
# ANY KIND, either express or implied. See the License for the specific
12
# language governing permissions and limitations under the License.
13
14
import copy
15
import logging
16
import sys
17
18
import awscli.clidriver
19
20
LOG = logging.getLogger(__name__)
21
22
23
class Completer:
24
def __init__(self, driver=None):
25
if driver is not None:
26
self.driver = driver
27
else:
28
self.driver = awscli.clidriver.create_clidriver()
29
self.main_help = self.driver.create_help_command()
30
self.main_options = self._get_documented_completions(
31
self.main_help.arg_table
32
)
33
34
def complete(self, cmdline, point=None):
35
if point is None:
36
point = len(cmdline)
37
38
args = cmdline[0:point].split()
39
current_arg = args[-1]
40
cmd_args = [w for w in args if not w.startswith('-')]
41
opts = [w for w in args if w.startswith('-')]
42
43
cmd_name, cmd = self._get_command(self.main_help, cmd_args)
44
subcmd_name, subcmd = self._get_command(cmd, cmd_args)
45
46
if cmd_name is None:
47
# If we didn't find any command names in the cmdline
48
# lets try to complete provider options
49
return self._complete_provider(current_arg, opts)
50
elif subcmd_name is None:
51
return self._complete_command(cmd_name, cmd, current_arg, opts)
52
return self._complete_subcommand(
53
subcmd_name, subcmd, current_arg, opts
54
)
55
56
def _complete_command(self, command_name, command_help, current_arg, opts):
57
if current_arg == command_name:
58
if command_help:
59
return self._get_documented_completions(
60
command_help.command_table
61
)
62
elif current_arg.startswith('-'):
63
return self._find_possible_options(current_arg, opts)
64
elif command_help is not None:
65
# See if they have entered a partial command name
66
return self._get_documented_completions(
67
command_help.command_table, current_arg
68
)
69
return []
70
71
def _complete_subcommand(
72
self, subcmd_name, subcmd_help, current_arg, opts
73
):
74
if current_arg != subcmd_name and current_arg.startswith('-'):
75
return self._find_possible_options(current_arg, opts, subcmd_help)
76
return []
77
78
def _complete_option(self, option_name):
79
if option_name == '--endpoint-url':
80
return []
81
if option_name == '--output':
82
cli_data = self.driver.session.get_data('cli')
83
return cli_data['options']['output']['choices']
84
if option_name == '--profile':
85
return self.driver.session.available_profiles
86
return []
87
88
def _complete_provider(self, current_arg, opts):
89
if current_arg.startswith('-'):
90
return self._find_possible_options(current_arg, opts)
91
elif current_arg == 'aws':
92
return self._get_documented_completions(
93
self.main_help.command_table
94
)
95
else:
96
# Otherwise, see if they have entered a partial command name
97
return self._get_documented_completions(
98
self.main_help.command_table, current_arg
99
)
100
101
def _get_command(self, command_help, command_args):
102
if command_help is not None and command_help.command_table is not None:
103
for command_name in command_args:
104
if command_name in command_help.command_table:
105
cmd_obj = command_help.command_table[command_name]
106
return command_name, cmd_obj.create_help_command()
107
return None, None
108
109
def _get_documented_completions(self, table, startswith=None):
110
names = []
111
for key, command in table.items():
112
if getattr(command, '_UNDOCUMENTED', False):
113
# Don't tab complete undocumented commands/params
114
continue
115
if startswith is not None and not key.startswith(startswith):
116
continue
117
if getattr(command, 'positional_arg', False):
118
continue
119
names.append(key)
120
return names
121
122
def _find_possible_options(self, current_arg, opts, subcmd_help=None):
123
all_options = copy.copy(self.main_options)
124
if subcmd_help is not None:
125
all_options += self._get_documented_completions(
126
subcmd_help.arg_table
127
)
128
129
for option in opts:
130
# Look through list of options on cmdline. If there are
131
# options that have already been specified and they are
132
# not the current word, remove them from list of possibles.
133
if option != current_arg:
134
stripped_opt = option.lstrip('-')
135
if stripped_opt in all_options:
136
all_options.remove(stripped_opt)
137
cw = current_arg.lstrip('-')
138
possibilities = ['--' + n for n in all_options if n.startswith(cw)]
139
if len(possibilities) == 1 and possibilities[0] == current_arg:
140
return self._complete_option(possibilities[0])
141
return possibilities
142
143
144
def complete(cmdline, point):
145
choices = Completer().complete(cmdline, point)
146
print(' \n'.join(choices))
147
148
149
if __name__ == '__main__':
150
if len(sys.argv) == 3:
151
cmdline = sys.argv[1]
152
point = int(sys.argv[2])
153
elif len(sys.argv) == 2:
154
cmdline = sys.argv[1]
155
else:
156
print('usage: %s <cmdline> <point>' % sys.argv[0])
157
sys.exit(1)
158
print(complete(cmdline, point))
159
160