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()
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With