Source code for zelfred.query

# -*- coding: utf-8 -*-

"""
The user input in the line editor is called :class:`Query`.
This module provides an objective oriented interface to parse user input string
into machine friendly :class:`Query` object.
"""

import typing as T
import dataclasses


_SEP = "____"


[docs]class QueryParser: """ Utility class that can parse string to :class:`Query`. Naturally, it is just a tokenizer. :param delimiter: the delimiter to split the query string. """ def __init__( self, delimiter: T.Union[str, T.List[str]] = " ", ): if isinstance(delimiter, str): self.delimiter = [ delimiter, ] else: self.delimiter = delimiter
[docs] def parse(self, s: str) -> "Query": """ Convert string query to structured :class:`Query` object. :param s: a string. """ for sep in self.delimiter: s = s.replace(sep, _SEP) parts = s.split(_SEP) trimmed_parts = [c.strip() for c in parts if c.strip()] return Query( raw=s, parts=parts, trimmed_parts=trimmed_parts, )
DEFAULT_QUERY_PARSER = QueryParser()
[docs]@dataclasses.dataclass class Query: """ Structured query object. This is very useful to parse the input of UI handler. :param parts: the parts of query string split by delimiter. For example, if the user input is ``"hello world!"``, then ``parts`` is ``["hello", "world!"]``. :param trimmed_parts: similar to parts, but each part is white-space stripped For example, if the user input is ``" hello world "``, then ``parts`` is ``["", "hello", "world", ""]``, and ``trimmed_parts`` is ``["hello", "world"]``. Usage:: >>> q = Query.from_str(" a b c ") >>> q.trimmed_parts ['a', 'b', 'c'] >>> q.n_trimmed_parts 3 """ raw: str = dataclasses.field() parts: T.List[str] = dataclasses.field() trimmed_parts: T.List[str] = dataclasses.field()
[docs] @classmethod def from_str(cls, s: str, parser=DEFAULT_QUERY_PARSER): """ Parse query from string using the given parser. """ return parser.parse(s)
@property def n_parts(self) -> int: """ The number of items in the ``parts``. """ return len(self.parts) @property def n_trimmed_parts(self) -> int: """ The number of items in the ``trimmed_parts``. """ return len(self.trimmed_parts)