示例#1
0
def choices_left(input, csrange):
	"""Assembles a list of terms that allow a valid input line
	given the prefix passed as `input` has been typed in so far.
	Those terms can include command keywords and argument values
	and depend on the command syntax to which the input line so far
	typed in matches, as well as legal argument values for that
	incomplete input line.
	The resulting list will only contain keywords or argument values
	that either have been started typing in, or those that may legally
	extend the current prefix, in case the latter doesn't end with
	an incomplete keyword or argument value.
	"""
	# TODO: read carefully for potential logical flaws!
	# TODO: read carefully for potential logical flaws!
	# TODO: read carefully for potential logical flaws!
	if not input:
		input = ''
	# range of relevant input (beginning of incomplete word
	#	and cursor position)
	beg, end = csrange
	# begin traversing language tree as long as it matches current input
	level = cmdict
	level_down = level
	# split input string into single terms
	# BUT only up to cursor position!
	terms = trmex.findall(input[:end])
	# append empty string if line ends on whitespace. thus the next
	# keyword/value in order can be determined later
	if re.match('.*\s+\Z', input[:end]) or end-beg<1:
		terms.append('')
	util.log('autocomplete: detected tokens are {}'.format(terms))
	#print '\nfind choices for:',terms
	# #########################3
	# parse incomplete input
	# word by word
	for term in terms:
		# walk downwards
		level = level_down
		if term in level:
			#print 'fitting:', term
			level_down = level.get(term)
		else:
			# if not a keyword, term might be an attribute value
			argnames = [t for t in level.keys()
				if argex.search(t)]
			resolved = False
			if len(argnames)>0:
				# check if term satisfies any attribute value requirements
				# TODO: auch hier das problem, dasz sich mit dem erstbesten
				# TODO zufrieden gegeben wird..?
				for a in argnames:
					if not resolved:
						arg = argex.findall(a)[0]
						# print '(argument to match is {})'.format(a)
						if arguments.validate(arg, term):
							# value matches attribute. proceed
							level_down = level.get(a)
							resolved=True
			if not resolved:
				# here is probably where the input breaks up.
				# also possibly where input goes on invalidly
				# nevertheless, we have to proceed until there
				# is no input left at all. otherwise, we might
				# end up with autocomplete suggestions for terms
				# in the middle of nowhere. If an input turns out
				# to be invalid way before it is done parsing,
				# then we simply can't provide autocompletion
				# for that input.
				# TODO: or can we? how exactly is cursor position
				# handled by readline module???
				break
	# incomplete input line has been matched against known
	# commands as far as possible. what do we have here?
	# possibility 1): input ends w potential or partly typed keyword
	# possibility 2): input ends where a value should follow
	# or is partly typed in
	#print 'fragment, keys:', term, level.keys()
	choices1 = level.keys()[:]
	util.log('autocomplete: possible input is {}.'.format(choices1))
	#print term, ':', choices1
	choices = []
	for c in choices1:
		# resolve argument, if any
		if argex.search(c):
			a = argex.findall(c)[0]
			util.log('Apply for completion candidates for arg {}.'.format(a))
			choices.extend(arguments.get_suggestions(a, term))
		else:
			# if not expecting argument: check if keyword can be
			# completed
			if c.startswith(term):
				choices.append(c)
	# by default, append whitespace behind completion choice
	# if completion is ultimate (e.g. command names).
	# If choice ends on ;, this means it can possibly be
	# extended further, but is not meant to stay like it is
	# (e.g. directory names: even if completed, you can still
	# go deeper in file structure)
	choices = [''.join(c[:-1])+[c[-1]+' ',''][int(c[-1]==';')]
							for c in choices if len(c) > 0]
	util.log('Suggest {} completion candidates:'.format(len(choices)))
	util.log(', '.join(choices))
	#print 'suggestions:',choices, ''
	return choices
示例#2
0
def choices_left(input, csrange):
    """Assembles a list of terms that allow a valid input line
	given the prefix passed as `input` has been typed in so far.
	Those terms can include command keywords and argument values
	and depend on the command syntax to which the input line so far
	typed in matches, as well as legal argument values for that
	incomplete input line.
	The resulting list will only contain keywords or argument values
	that either have been started typing in, or those that may legally
	extend the current prefix, in case the latter doesn't end with
	an incomplete keyword or argument value.
	"""
    # TODO: read carefully for potential logical flaws!
    # TODO: read carefully for potential logical flaws!
    # TODO: read carefully for potential logical flaws!
    if not input:
        input = ''
    # range of relevant input (beginning of incomplete word
    #	and cursor position)
    beg, end = csrange
    # begin traversing language tree as long as it matches current input
    level = cmdict
    level_down = level
    # split input string into single terms
    # BUT only up to cursor position!
    terms = trmex.findall(input[:end])
    # append empty string if line ends on whitespace. thus the next
    # keyword/value in order can be determined later
    if re.match('.*\s+\Z', input[:end]) or end - beg < 1:
        terms.append('')
    util.log('autocomplete: detected tokens are {}'.format(terms))
    #print '\nfind choices for:',terms
    # #########################3
    # parse incomplete input
    # word by word
    for term in terms:
        # walk downwards
        level = level_down
        if term in level:
            #print 'fitting:', term
            level_down = level.get(term)
        else:
            # if not a keyword, term might be an attribute value
            argnames = [t for t in level.keys() if argex.search(t)]
            resolved = False
            if len(argnames) > 0:
                # check if term satisfies any attribute value requirements
                # TODO: auch hier das problem, dasz sich mit dem erstbesten
                # TODO zufrieden gegeben wird..?
                for a in argnames:
                    if not resolved:
                        arg = argex.findall(a)[0]
                        # print '(argument to match is {})'.format(a)
                        if arguments.validate(arg, term):
                            # value matches attribute. proceed
                            level_down = level.get(a)
                            resolved = True
            if not resolved:
                # here is probably where the input breaks up.
                # also possibly where input goes on invalidly
                # nevertheless, we have to proceed until there
                # is no input left at all. otherwise, we might
                # end up with autocomplete suggestions for terms
                # in the middle of nowhere. If an input turns out
                # to be invalid way before it is done parsing,
                # then we simply can't provide autocompletion
                # for that input.
                # TODO: or can we? how exactly is cursor position
                # handled by readline module???
                break
    # incomplete input line has been matched against known
    # commands as far as possible. what do we have here?
    # possibility 1): input ends w potential or partly typed keyword
    # possibility 2): input ends where a value should follow
    # or is partly typed in
    #print 'fragment, keys:', term, level.keys()
    choices1 = level.keys()[:]
    util.log('autocomplete: possible input is {}.'.format(choices1))
    #print term, ':', choices1
    choices = []
    for c in choices1:
        # resolve argument, if any
        if argex.search(c):
            a = argex.findall(c)[0]
            util.log('Apply for completion candidates for arg {}.'.format(a))
            choices.extend(arguments.get_suggestions(a, term))
        else:
            # if not expecting argument: check if keyword can be
            # completed
            if c.startswith(term):
                choices.append(c)
    # by default, append whitespace behind completion choice
    # if completion is ultimate (e.g. command names).
    # If choice ends on ;, this means it can possibly be
    # extended further, but is not meant to stay like it is
    # (e.g. directory names: even if completed, you can still
    # go deeper in file structure)
    choices = [
        ''.join(c[:-1]) + [c[-1] + ' ', ''][int(c[-1] == ';')] for c in choices
        if len(c) > 0
    ]
    util.log('Suggest {} completion candidates:'.format(len(choices)))
    util.log(', '.join(choices))
    #print 'suggestions:',choices, ''
    return choices
示例#3
0
def execute(input):
	"""\
	Tests given input string against currently
	registered command syntaxes. If input turns out
	to be a valid command, a corresponding handler
	function is called. If matching syntax contains
	argument placeholders (`"command <arg>"`), their
	respective values are extracted from the input and
	passed to the handler function.
	"""
	# split input string into single terms
	terms = trmex.findall(input)
	# init path log for recreation of generic command
	path = []
	args = []
	kwargs = {}
	# return message
	msg = ''
	# check if terms match known commands:
	# begin at language tree root
	level = cmdict
	# walk down as long as input seems to be
	# a valid command language word, i.e. input
	# term reachable by walking along its predecessors
	term = ''
	for term in terms:
		#print ' '.join(level.keys())
		# still on track?
		if term in level:
			level = level.get(term)
			path.append(term)
		else:
			# might be just an argument value that we
			# need to recognize, validate and extract
			# first, get all argument ids that
			# might be applicable
			argnames = [t for t in level.keys()
				if argex.search(t)]
			resolved = False
			if len(argnames)>0:
				# then test if found input is valid for
				# at least one of them
				#TODO: we will probably have to recurse
				#TODO here, because we might get on the
				# wrong track by picking just any matching
				# placeholder here
				for a in argnames:
					if not resolved:
						arg = argex.findall(a)[0]
						if arguments.validate(arg, term):
							#print 'reading value for argument',
							#print '{}: {}.'.format(a,term)
							# input valid! collect value
							args.append(term)
							kwargs[arg] = term
							# proceed
							level = level.get(a)
							path.append(a)
							resolved=True
			if not resolved:
				# path lost -> input not in language
				# not a valid command
				msg = term
				term = None
				break
	# do we have a match? or not?
	if term is None:
		return '!!Syntax error!!: term "{}" not recognized.'.format(msg)
	else:
		# if EOL code terminates term sequence, we are good.
		# if not, input is incomplete
		if level.get('') is None:
			msg = msg_incomplete_cmd(level.keys())
			# return a hint on expected input
			return msg
		else:
			# we have a match!
			# command is valid! get handler!
			# print ' '.join(path)
			func = level.get('')
			#print 'Calling {}'.format(func.__name__)
			ret = func(*args, **kwargs)
			# log argument values
			for arg,v in kwargs.items():
				arguments.to_history(arg,v)
			return ret
示例#4
0
def execute(input):
    """\
	Tests given input string against currently
	registered command syntaxes. If input turns out
	to be a valid command, a corresponding handler
	function is called. If matching syntax contains
	argument placeholders (`"command <arg>"`), their
	respective values are extracted from the input and
	passed to the handler function.
	"""
    # split input string into single terms
    terms = trmex.findall(input)
    # init path log for recreation of generic command
    path = []
    args = []
    kwargs = {}
    # return message
    msg = ''
    # check if terms match known commands:
    # begin at language tree root
    level = cmdict
    # walk down as long as input seems to be
    # a valid command language word, i.e. input
    # term reachable by walking along its predecessors
    term = ''
    for term in terms:
        #print ' '.join(level.keys())
        # still on track?
        if term in level:
            level = level.get(term)
            path.append(term)
        else:
            # might be just an argument value that we
            # need to recognize, validate and extract
            # first, get all argument ids that
            # might be applicable
            argnames = [t for t in level.keys() if argex.search(t)]
            resolved = False
            if len(argnames) > 0:
                # then test if found input is valid for
                # at least one of them
                #TODO: we will probably have to recurse
                #TODO here, because we might get on the
                # wrong track by picking just any matching
                # placeholder here
                for a in argnames:
                    if not resolved:
                        arg = argex.findall(a)[0]
                        if arguments.validate(arg, term):
                            #print 'reading value for argument',
                            #print '{}: {}.'.format(a,term)
                            # input valid! collect value
                            args.append(term)
                            kwargs[arg] = term
                            # proceed
                            level = level.get(a)
                            path.append(a)
                            resolved = True
            if not resolved:
                # path lost -> input not in language
                # not a valid command
                msg = term
                term = None
                break
    # do we have a match? or not?
    if term is None:
        return '!!Syntax error!!: term "{}" not recognized.'.format(msg)
    else:
        # if EOL code terminates term sequence, we are good.
        # if not, input is incomplete
        if level.get('') is None:
            msg = msg_incomplete_cmd(level.keys())
            # return a hint on expected input
            return msg
        else:
            # we have a match!
            # command is valid! get handler!
            # print ' '.join(path)
            func = level.get('')
            #print 'Calling {}'.format(func.__name__)
            ret = func(*args, **kwargs)
            # log argument values
            for arg, v in kwargs.items():
                arguments.to_history(arg, v)
            return ret