Reputation: 2731
I am working on a program that parses a command line with pyparsing. It uses the readline library to provide command edition and completion.
In the context of the application, a valid command line is a path (optional), followed by a command name (optional) and some parameters (also optional).
To offer command completion, the application parses the command line to see if the element to complete is a path, a command or a completion. Readline gives the indexes of the element that needs completion. I would like to match these indexes with the location of the path, the command name or the parameters of the parsed results returned by pyparsing.
How can I get the location of the different tokens and keep using setResultsName() to name my tokens?
from pyparsing import Optional, Regex, Word
from pyparsing import alphanums
class Shell(object):
def __init__(self):
# Simplified grammar of the command line
# path command parameters
command = Word(alphanums + '_').setResultsName('command')
bookmark = Regex('@([A-Za-z0-9:_.]|-)+')
pathstd = Regex('([A-Za-z0-9:_.]|-)*' + '/' + '([A-Za-z0-9:_./]|-)*') \
| '..' | '.'
path = (bookmark | pathstd | '*')('path')
parser = Optional(path) + Optional(command) # + Optional(parameters)
self.parser = parser
def parse_cmdline(self, line):
parse_results = self.parser.parseString(line)
path = parse_results.path
command = parse_results.command
return (parse_results, path, command)
def complete(self):
"""Completion method called by readline"""
cmdline = readline.get_line_buffer()
(result_trees, path, command) = self.parse_cmdline(cmdline)
beg = readline.get_begidx()
end = readline.get_endidx()
prefix = cmdline[beg:end]
# if beg == path.location:
# completion = self.get_path_completion()
# elif beg == command.location:
# completion = self.get_command_completion()
# elif beg in parameters.location:
# completion = self.get_parameter_completion()
Upvotes: 3
Views: 941
Reputation: 63739
Try adding a locator to your command and path expressions:
locator = Empty().setParseAction(lambda s,l,t: l)
def locatedExpr(expr):
return Group(locator("location") + expr("value"))
class Shell(object):
def __init__(self):
# Simplified grammar of the command line
# path command parameters
#command = Word(alphanums + '_').setResultsName('command')
command = locatedExpr(Word(alphanums + '_'))('command')
bookmark = Regex('@([A-Za-z0-9:_.]|-)+')
pathstd = Regex('([A-Za-z0-9:_.]|-)*' + '/' + '([A-Za-z0-9:_./]|-)*') \
| '..' | '.'
#path = (bookmark | pathstd | '*')('path')
path = locatedExpr(bookmark | pathstd | '*')('path')
parser = Optional(path) + Optional(command) # + Optional(parameters)
self.parser = parser
Now you should be able to access path.location
and path.value
to get the location and matched text for the path, and likewise for command.
Upvotes: 4