Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pyparsing: get token location in results name

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()
like image 781
Christophe Vu-Brugier Avatar asked Dec 11 '25 09:12

Christophe Vu-Brugier


1 Answers

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.

like image 156
PaulMcG Avatar answered Dec 13 '25 21:12

PaulMcG



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!