Parse a possibly partial command. Return a sequence of ParseResults and a sequence of remainder type help items.
(
self, cmdstr: str
)
| 194 | |
| 195 | @functools.lru_cache(maxsize=128) |
| 196 | def parse_partial( |
| 197 | self, cmdstr: str |
| 198 | ) -> tuple[Sequence[ParseResult], Sequence[CommandParameter]]: |
| 199 | """ |
| 200 | Parse a possibly partial command. Return a sequence of ParseResults and a sequence of remainder type help items. |
| 201 | """ |
| 202 | |
| 203 | parts: pyparsing.ParseResults = command_lexer.expr.parseString( |
| 204 | cmdstr, parseAll=True |
| 205 | ) |
| 206 | |
| 207 | parsed: list[ParseResult] = [] |
| 208 | next_params: list[CommandParameter] = [ |
| 209 | CommandParameter("", mitmproxy.types.Cmd), |
| 210 | CommandParameter("", mitmproxy.types.CmdArgs), |
| 211 | ] |
| 212 | expected: CommandParameter | None = None |
| 213 | for part in parts: |
| 214 | if part.isspace(): |
| 215 | parsed.append( |
| 216 | ParseResult( |
| 217 | value=part, |
| 218 | type=mitmproxy.types.Space, |
| 219 | valid=True, |
| 220 | ) |
| 221 | ) |
| 222 | continue |
| 223 | |
| 224 | if expected and expected.kind is inspect.Parameter.VAR_POSITIONAL: |
| 225 | assert not next_params |
| 226 | elif next_params: |
| 227 | expected = next_params.pop(0) |
| 228 | else: |
| 229 | expected = CommandParameter("", mitmproxy.types.Unknown) |
| 230 | |
| 231 | arg_is_known_command = ( |
| 232 | expected.type == mitmproxy.types.Cmd and part in self.commands |
| 233 | ) |
| 234 | arg_is_unknown_command = ( |
| 235 | expected.type == mitmproxy.types.Cmd and part not in self.commands |
| 236 | ) |
| 237 | command_args_following = ( |
| 238 | next_params and next_params[0].type == mitmproxy.types.CmdArgs |
| 239 | ) |
| 240 | if arg_is_known_command and command_args_following: |
| 241 | next_params = self.commands[part].parameters + next_params[1:] |
| 242 | if arg_is_unknown_command and command_args_following: |
| 243 | next_params.pop(0) |
| 244 | |
| 245 | to = mitmproxy.types.CommandTypes.get(expected.type, None) |
| 246 | valid = False |
| 247 | if to: |
| 248 | try: |
| 249 | to.parse(self, expected.type, part) |
| 250 | except ValueError: |
| 251 | valid = False |
| 252 | else: |
| 253 | valid = True |