Beispiel #1
0
	def _execute(self, source, command: str, remaining: str, context: dict):
		success_read = len(command) - len(remaining)
		try:
			result = self.parse(remaining)
		except CommandSyntaxError as error:
			error.set_parsed_command(command[:success_read])
			error.set_failed_command(command[:success_read + error.char_read])
			self.__raise_error(source, error, context)
		else:
			success_read += result.char_read
			trimmed_remaining = utils.remove_divider_prefix(remaining[result.char_read:])

			if self.__does_store_thing():
				context[self.name] = result.value

			if self.requirement is not None:
				if not self.__smart_callback(self.requirement, source, context):
					getter = self.requirement_failure_message_getter if self.requirement_failure_message_getter is not None else lambda: None
					failure_message = self.__smart_callback(getter, source, context)
					self.__raise_error(source, RequirementNotMet(command[:success_read], command[:success_read], failure_message), context)

			# Parsing finished
			if len(trimmed_remaining) == 0:
				if self.callback is not None:
					self.__smart_callback(self.callback, source, context)
				else:
					self.__raise_error(source, UnknownCommand(command[:success_read], command[:success_read]), context)
			# Un-parsed command string remains
			else:
				# Redirecting
				node = self if self.redirect_node is None else self.redirect_node

				argument_unknown = False
				# No child at all
				if not node.has_children():
					argument_unknown = True
				else:
					# Pass the remaining command string to the children
					try:
						# Check literal children first
						next_literal = utils.get_element(trimmed_remaining)
						for child_literal in node.children_literal.get(next_literal, []):
							try:
								child_literal._execute(source, command, trimmed_remaining, context)
								break
							except LiteralNotMatch:
								# it's ok for a direct literal node to fail
								pass
						else:  # All literal children fails
							for child in node.children:
								child._execute(source, command, trimmed_remaining, context)
								break
							else:  # No argument child
								argument_unknown = True
					except CommandError as error:
						self.__handle_error(source, error, context, self.child_error_handlers)
						raise error from None

				if argument_unknown:
					self.__raise_error(source, UnknownArgument(command[:success_read], command), context)
Beispiel #2
0
	def _generate_suggestions(self, context: CommandContext) -> CommandSuggestions:
		"""
		Return a list of tuple (suggested command, suggested argument)
		"""
		def self_suggestions():
			return CommandSuggestions([CommandSuggestion(command_read_at_the_beginning, s) for s in self._get_suggestions(context)])

		suggestions = CommandSuggestions()
		# [!!aa bb cc] dd
		# read         suggested
		command_read_at_the_beginning = context.command_read
		if len(context.command_remaining) == 0:
			return self_suggestions()
		try:
			result = self.parse(context.command_remaining)
		except CommandSyntaxError:
			return self_suggestions()
		else:
			success_read = len(context.command) - len(context.command_remaining) + result.char_read  # type: int
			next_remaining = utils.remove_divider_prefix(context.command_remaining[result.char_read:])  # type: str
			total_read = len(context.command) - len(next_remaining)  # type: int

			with context.read_command(self, result, total_read):
				if self._requirement is not None and not self.__smart_callback(self._requirement, context.source, context):
					return CommandSuggestions()

				# Parsing finished
				if len(next_remaining) == 0:
					# total_read == success_read means DIVIDER does not exists at the end of the input string
					# in that case, ends at this current node
					if success_read == total_read:
						return self_suggestions()

				node = self if self._redirect_node is None else self._redirect_node
				# Check literal children first
				children_literal = node._children_literal.get(utils.get_element(next_remaining), [])
				for child_literal in children_literal:
					with context.enter_child(child_literal):
						suggestions.extend(child_literal._generate_suggestions(context))
				if len(children_literal) == 0:
					for literal_list in node._children_literal.values():
						for child_literal in literal_list:
							with context.enter_child(child_literal):
								suggestions.extend(child_literal._generate_suggestions(context))
					usages = []
					for child in node._children:
						with context.enter_child(child):
							suggestions.extend(child._generate_suggestions(context))
							if len(next_remaining) == 0:
								usages.append(child._get_usage())
					if len(next_remaining) == 0:
						suggestions.complete_hint = '|'.join(usages)
		return suggestions
Beispiel #3
0
    def _execute_command(self, context: CommandContext) -> None:
        command = context.command  # type: str
        try:
            result = self.parse(context.command_remaining)
        except CommandSyntaxError as error:
            error.set_parsed_command(context.command_read)
            error.set_failed_command(
                context.command_read +
                context.command_remaining[:error.char_read])
            self.__raise_error(error, context)
        else:
            next_remaining = utils.remove_divider_prefix(
                context.command_remaining[result.char_read:])  # type: str
            total_read = len(command) - len(next_remaining)  # type: int

            with context.read_command(self, result, total_read):
                if self._requirement is not None:
                    if not self.__smart_callback(self._requirement,
                                                 context.source, context):
                        getter = self._requirement_failure_message_getter or (
                            lambda: None)
                        failure_message = self.__smart_callback(
                            getter, context.source, context)
                        self.__raise_error(
                            RequirementNotMet(context.command_read,
                                              context.command_read,
                                              failure_message), context)

                # Parsing finished
                if len(next_remaining) == 0:
                    if self._callback is not None:
                        self.__smart_callback(self._callback, context.source,
                                              context)
                    else:
                        self.__raise_error(
                            UnknownCommand(context.command_read,
                                           context.command_read), context)
                # Un-parsed command string remains
                else:
                    # Redirecting
                    node = self if self._redirect_node is None else self._redirect_node

                    argument_unknown = False
                    # No child at all
                    if not node.has_children():
                        argument_unknown = True
                    else:
                        # Pass the remaining command string to the children
                        next_literal = utils.get_element(next_remaining)
                        try:
                            # Check literal children first
                            literal_error = None
                            for child_literal in node._children_literal.get(
                                    next_literal, []):
                                try:
                                    with context.enter_child(child_literal):
                                        child_literal._execute_command(context)
                                    break
                                except CommandError as e:
                                    # it's ok for a direct literal node to fail
                                    # other literal might still have a chance to consume this command
                                    literal_error = e
                            else:  # All literal children fails
                                if literal_error is not None:
                                    raise literal_error
                                for child in node._children:
                                    with context.enter_child(child):
                                        child._execute_command(context)
                                    break
                                else:  # No argument child
                                    argument_unknown = True

                        except CommandError as error:
                            self.__handle_error(error, context,
                                                self._child_error_handlers)
                            raise error from None

                    if argument_unknown:
                        self.__raise_error(
                            UnknownArgument(context.command_read, command),
                            context)