#!/usr/bin/env bash set -euo pipefail repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" sidebar="$repo_dir/config/dot/quickshell/modules/settings/SettingsSidebar.qml" fail() { printf 'settings sidebar layout contract: %s\n' "$1" >&2 exit 1 } python3 - "$sidebar" <<'PY' || fail 'sidebar does not keep its header and footer pinned around one vertical scroll surface' import re import sys text = open(sys.argv[1], encoding="utf-8").read() def object_block(type_name: str, object_id: str) -> tuple[int, int, str]: pattern = re.compile( rf"\b{re.escape(type_name)}\s*\{{(?:(?!\n\s*[A-Za-z][A-Za-z0-9.]*\s*\{{).)*?" rf"\bid\s*:\s*{re.escape(object_id)}\b", re.S, ) match = pattern.search(text) if not match: raise AssertionError(f"missing {type_name} id {object_id}") start = match.start() opening = text.index("{", start) depth = 0 in_string = False escaped = False index = opening while index < len(text): character = text[index] if in_string: if escaped: escaped = False elif character == "\\": escaped = True elif character == '"': in_string = False elif character == '"': in_string = True elif character == "{": depth += 1 elif character == "}": depth -= 1 if depth == 0: return start, index + 1, text[start:index + 1] index += 1 raise AssertionError(f"unterminated {type_name} id {object_id}") try: header_start, header_end, header = object_block("Column", "sidebarHeader") scroll_start, scroll_end, scroll = object_block("Flickable", "sidebarScroll") footer_start, _, footer = object_block("Rectangle", "healthFooter") assert header_start < scroll_start < scroll_end < footer_start assert re.search(r"anchors\.top\s*:\s*parent\.top", header) assert re.search(r"\bid\s*:\s*searchInput\b", header) assert re.search(r"anchors\.top\s*:\s*sidebarHeader\.bottom", scroll) assert re.search(r"anchors\.bottom\s*:\s*healthFooter\.top", scroll) assert re.search(r"contentWidth\s*:\s*width", scroll) assert re.search(r"contentHeight\s*:\s*scrollContent\.implicitHeight", scroll) assert re.search(r"flickableDirection\s*:\s*Flickable\.VerticalFlick", scroll) assert re.search(r"boundsBehavior\s*:\s*Flickable\.StopAtBounds", scroll) assert re.search(r"clip\s*:\s*true", scroll) assert scroll.count("Flickable {") == 1 assert re.search(r"\bid\s*:\s*scrollContent\b", scroll) assert re.search(r"\bid\s*:\s*searchResults\b", scroll) assert re.search(r"\bid\s*:\s*navigationList\b", scroll) assert re.search(r"visible\s*:\s*root\.query\s*!==\s*\"\"", scroll) assert re.search(r"visible\s*:\s*root\.query\s*===\s*\"\"", scroll) assert re.search(r"anchors\.bottom\s*:\s*parent\.bottom", footer) except AssertionError as error: print(error, file=sys.stderr) raise SystemExit(1) PY printf 'settings sidebar layout contract: PASS\n'