home · contact · privacy
De-hardcode BrickDesign matchers, sorters.
authorPlom Heller <plom@plomlompom.com>
Sat, 13 Jun 2026 17:27:27 +0000 (19:27 +0200)
committerPlom Heller <plom@plomlompom.com>
Sat, 13 Jun 2026 17:27:27 +0000 (19:27 +0200)
bricksplom.py

index eaff95ccf62b96e80a95997ad538a3703045ae01..0003d6fc57e3b611de713a71f79bff1359e0eeb3 100755 (executable)
@@ -31,12 +31,9 @@ CHAR_COL_TRANSPARENT = '-'
 BOX_PREFIX = 'box:'
 
 PARAM_Q_ID = 'id='
-PARAM_Q_STUDS = 'n_studs='
 PARAM_Q_TEXT = 'text:'
-PARAMS_Q = (PARAM_Q_ID, PARAM_Q_STUDS, PARAM_Q_TEXT)
 TOK_SORT_BOX = 'box'
 TOK_SORT_ID = 'id'
-TOK_SORT_STUDS = 'n_studs'
 
 BrickListing = tuple[int, str, str]  # count, ID, comment
 PageColumn = tuple[BrickListing, ...]
@@ -271,23 +268,39 @@ class BrickDesign(Textfiled, Lookupable):
     def matchers(
             self
             ) -> dict[str, Callable[[str], bool]]:
-        def q_studs(
-                q_body
-                ) -> bool:
-            assert q_body.isdigit()
-            return self.n_studs == int(q_body)
-        return super().matchers | {PARAM_Q_STUDS: q_studs}
+        def attr_matcher(
+                attr_name: str
+                ) -> Callable[[str], bool]:
+            def match(
+                    q_body: str
+                    ) -> bool:
+                assert q_body.isdigit()
+                return getattr(self, attr_name) == int(q_body)
+            return match
+        return super().matchers | {
+            f'{attr_name}=': attr_matcher(attr_name)
+            for attr_name, attr_type in BrickDesignData.__annotations__.items()
+            if attr_type is int}
 
     @property
     def sorters(
             self
             ) -> dict[str, Callable[['BricksDb', tuple[Self, ...]],
                                     tuple[Self, ...]]]:
-        return super().sorters | {
-            TOK_SORT_BOX: self._by_box_sorter('design'),
-            TOK_SORT_STUDS: lambda _, pre_sorted: tuple(
-                sorted(pre_sorted, key=lambda item: item.n_studs))
-                }
+        def attr_sorter(
+                attr_name: str,
+                ) -> Callable[[BricksDb, tuple[Self, ...]], tuple[Self, ...]]:
+            def f_sort(
+                    _: BricksDb,
+                    pre_sorted: tuple[Self, ...]
+                    ) -> tuple[Self, ...]:
+                return tuple(sorted(pre_sorted,
+                                    key=lambda item: getattr(item, attr_name)))
+            return f_sort
+        return super().sorters\
+            | {TOK_SORT_BOX: self._by_box_sorter('design')}\
+            | {attr_name: attr_sorter(attr_name)
+               for attr_name in BrickDesignData.__annotations__}
 
     @classmethod
     def from_textfile(
@@ -694,10 +707,12 @@ class BricksDb:
         items = tuple(table.values())
         if items and sort_by:
             items = items[0].sorters[sort_by](self, items)
-        if match_by:
-            candidates = [p for p in PARAMS_Q if match_by.startswith(p)]
-            assert len(candidates) == 1
-            p_key = candidates[0]
+        if items and match_by:
+            p_key = ''
+            for p_key in [p_key for p_key in items[0].matchers
+                          if match_by.startswith(p_key)]:
+                break
+            assert p_key
             p_val = match_by[len(p_key):]
             items = tuple(item for item in items if item.match(p_key, p_val))
         if len(items) == 1 and not show_raw: