comparison frontends/src/jp/cmd_shell.py @ 2315:8d9bd5d77336

jp (arg_tools): moved get_cmd_choices, get_use_args and escape to a new arg_tools module, so they can be used in other commands than shell
author Goffi <goffi@goffi.org>
date Sat, 08 Jul 2017 21:45:14 +0200
parents 6ff5212997c7
children f4e05600577b
comparison
equal deleted inserted replaced
2314:01f0a954d506 2315:8d9bd5d77336
22 import cmd 22 import cmd
23 import sys 23 import sys
24 from sat.core.i18n import _ 24 from sat.core.i18n import _
25 from sat.core import exceptions 25 from sat.core import exceptions
26 from sat_frontends.jp.constants import Const as C 26 from sat_frontends.jp.constants import Const as C
27 from sat_frontends.jp import arg_tools
27 from sat.tools.common.ansi import ANSI as A 28 from sat.tools.common.ansi import ANSI as A
28 import shlex 29 import shlex
29 import subprocess 30 import subprocess
30 31
31 __commands__ = ["Shell"] 32 __commands__ = ["Shell"]
45 cmd.Cmd.__init__(self) 46 cmd.Cmd.__init__(self)
46 47
47 def parse_args(self, args): 48 def parse_args(self, args):
48 """parse line arguments""" 49 """parse line arguments"""
49 return shlex.split(args, posix=True) 50 return shlex.split(args, posix=True)
50
51 def get_cmd_choices(self, cmd=None, parser=None):
52 if parser is None:
53 parser = self._cur_parser
54 try:
55 choices = parser._subparsers._group_actions[0].choices
56 return choices[cmd] if cmd is not None else choices
57 except (KeyError, AttributeError):
58 raise exceptions.NotFound
59 51
60 def update_path(self): 52 def update_path(self):
61 self._cur_parser = self.host.parser 53 self._cur_parser = self.host.parser
62 self.help = u'' 54 self.help = u''
63 for idx, path_elt in enumerate(self.path): 55 for idx, path_elt in enumerate(self.path):
64 try: 56 try:
65 self._cur_parser = self.get_cmd_choices(path_elt) 57 self._cur_parser = arg_tools.get_cmd_choices(path_elt, self._cur_parser)
66 except exceptions.NotFound: 58 except exceptions.NotFound:
67 self.disp(_(u'bad command path'), error=True) 59 self.disp(_(u'bad command path'), error=True)
68 self.path=self.path[:idx] 60 self.path=self.path[:idx]
69 break 61 break
70 else: 62 else:
71 self.help = self._cur_parser 63 self.help = self._cur_parser
72 64
73 self.prompt = A.color(C.A_PROMPT_PATH, u'/'.join(self.path)) + A.color(C.A_PROMPT_SUF, u'> ') 65 self.prompt = A.color(C.A_PROMPT_PATH, u'/'.join(self.path)) + A.color(C.A_PROMPT_SUF, u'> ')
74 try: 66 try:
75 self.actions = self.get_cmd_choices().keys() 67 self.actions = arg_tools.get_cmd_choices(parser=self._cur_parser).keys()
76 except exceptions.NotFound: 68 except exceptions.NotFound:
77 self.actions = [] 69 self.actions = []
78 70
79 def add_parser_options(self): 71 def add_parser_options(self):
80 pass 72 pass
81
82 def escape_arg(self, arg):
83 """format arg with quotes"""
84 return u'"' + arg.replace(u'"',u'\\"') + u'"'
85 73
86 def format_args(self, args): 74 def format_args(self, args):
87 """format argument to be printed with quotes if needed""" 75 """format argument to be printed with quotes if needed"""
88 for arg in args: 76 for arg in args:
89 if " " in arg: 77 if " " in arg:
90 yield self.escape_arg(arg) 78 yield arg_tools.escape(arg)
91 else: 79 else:
92 yield arg 80 yield arg
93
94 def get_use_args(self, args):
95 """format args for current parser according to self.use"""
96 parser = self._cur_parser
97
98 # we check not optional args to see if there
99 # is a corresonding parser
100 # else USE args would not work correctly (only for current parser)
101 cmd_args = []
102 for arg in args:
103 if arg.startswith('-'):
104 break
105 try:
106 parser = self.get_cmd_choices(arg, parser)
107 except exceptions.NotFound:
108 break
109 cmd_args.append(arg)
110
111 # we remove command args
112 # they'll be in returned list (use_args)
113 del args[:len(cmd_args)]
114
115 opt_args = []
116 pos_args = []
117 actions = {a.dest: a for a in parser._actions}
118 for arg, value in self.use.iteritems():
119 try:
120 action = actions[arg]
121 except KeyError:
122 if self.verbose:
123 self.disp(_(u'ignoring {name}={value}, not corresponding to any argument (in USE)').format(
124 name=arg,
125 value=self.escape_arg(value)))
126 else:
127 if self.verbose:
128 self.disp(_(u'arg {name}={value} set (in USE)').format(name=arg, value=self.escape_arg(value)))
129 if not action.option_strings:
130 pos_args.append(value)
131 else:
132 opt_args.append(action.option_strings[0])
133 opt_args.append(value)
134 return cmd_args + opt_args + pos_args
135 81
136 def run_cmd(self, args, external=False): 82 def run_cmd(self, args, external=False):
137 """run command and retur exit code 83 """run command and retur exit code
138 84
139 @param args[list[string]]: arguments of the command 85 @param args[list[string]]: arguments of the command
234 def do_do(self, args): 180 def do_do(self, args):
235 """lauch a command""" 181 """lauch a command"""
236 args = self.parse_args(args) 182 args = self.parse_args(args)
237 # args may be modified by use_args 183 # args may be modified by use_args
238 # to remove subparsers from it 184 # to remove subparsers from it
239 use_args = self.get_use_args(args) 185 use_args = arg_tools.get_use_args(self.host,
186 args,
187 self.use,
188 verbose=self.verbose,
189 parser=self._cur_parser
190 )
240 cmd_args = self.path + use_args + args 191 cmd_args = self.path + use_args + args
241 self.run_cmd(cmd_args) 192 self.run_cmd(cmd_args)
242 193
243 def do_use(self, args): 194 def do_use(self, args):
244 """fix an argument""" 195 """fix an argument"""
247 if not self.use: 198 if not self.use:
248 self.disp(_(u'no argument in USE')) 199 self.disp(_(u'no argument in USE'))
249 else: 200 else:
250 self.disp(_(u'arguments in USE:')) 201 self.disp(_(u'arguments in USE:'))
251 for arg, value in self.use.iteritems(): 202 for arg, value in self.use.iteritems():
252 self.disp(_(A.color(C.A_SUBHEADER, arg, A.RESET, u' = ', self.escape_arg(value)))) 203 self.disp(_(A.color(C.A_SUBHEADER, arg, A.RESET, u' = ', arg_tools.escape(value))))
253 elif len(args) != 2: 204 elif len(args) != 2:
254 self.disp(u'bad syntax, please use:\nuse [arg] [value]', error=True) 205 self.disp(u'bad syntax, please use:\nuse [arg] [value]', error=True)
255 else: 206 else:
256 self.use[args[0]] = u' '.join(args[1:]) 207 self.use[args[0]] = u' '.join(args[1:])
257 if self.verbose: 208 if self.verbose:
258 self.disp('set {name} = {value}'.format( 209 self.disp('set {name} = {value}'.format(
259 name = args[0], value=self.escape_arg(args[1]))) 210 name = args[0], value=arg_tools.escape(args[1])))
260 211
261 def do_use_clear(self, args): 212 def do_use_clear(self, args):
262 """unset one or many argument(s) in USE, or all of them if no arg is specified""" 213 """unset one or many argument(s) in USE, or all of them if no arg is specified"""
263 args = self.parse_args(args) 214 args = self.parse_args(args)
264 if not args: 215 if not args: