Properties: colours by type, readable keys, lines between

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
sarahandClaude Opus 5.5 committed 2026-10-13 16:35:21 +02:00
1 parent ca37409e37
commit 81ebcd66a1
3 files changed
+101 -14

No files matched your search

+55 -9
View File
@@ -23,6 +23,37 @@ OpenOrClose = re.compile(r"^---\s*$")
PropertyLine = re.compile(r"^([^:\s][^:]*?)\s*:\s*(.*)$")
TaskLine = re.compile(r"^(\s*(?:[-*+]|\d+[.)])\s+)\[( |x|X)\]")
BooleanValue = re.compile(r"^(true|false)$", re.IGNORECASE)
Quoted = re.compile(r"""^(["']).*\1$""")
IntegerValue = re.compile(r"^[+-]?\d+$")
FloatValue = re.compile(r"^[+-]?(\d+\.\d*([eE][+-]?\d+)?|\.\d+([eE][+-]?\d+)?|\d+[eE][+-]?\d+)$")
DateValue = re.compile(r"^\d{4}-\d{2}-\d{2}([T ]\d{2}:\d{2}(:\d{2})?)?$")
def ValueKind(Value: str) -> str:
"""What a value is, for its colour: quotes always make it text ("42" is
text, 42 a number), like YAML. Same rules as Properties.js's ValueKind."""
if Value == "":
return "Empty"
if Quoted.match(Value):
return "String"
if BooleanValue.match(Value):
return "Boolean"
if IntegerValue.match(Value):
return "Integer"
if FloatValue.match(Value):
return "Float"
if DateValue.match(Value):
return "Date"
return "String"
def ShownValue(Value: str) -> str:
"""A value as shown: without the quotes that only said "this is text"."""
return Value[1:-1] if Quoted.match(Value) else Value
def KindColour(Kind: str) -> str:
return {"Integer": Palette.Peach, "Float": Palette.Yellow, "Date": Palette.Blue}.get(Kind, Palette.Green)
# Ticks a box: called with the line (0-based, in the whole note) to flip.
OnToggle = Optional[Callable[[int], None]]
@@ -93,26 +124,41 @@ def _Checkbox(Checked: bool, Line: int, Toggle: OnToggle) -> ft.Checkbox:
)
def _Value(Value: str, FontSize: int, MakeMarkdown: Callable[[str], ft.Control]) -> ft.Control:
"""A value in its kind's colour; one with Markdown in it (a link, bold)
is rendered as Markdown instead."""
Shown = ShownValue(Value)
if re.search(r"[\[*_`~]|https?://", Shown):
return MakeMarkdown(Shown)
return ft.Text(Shown, color=KindColour(ValueKind(Value)), size=FontSize, selectable=True)
def PropertiesView(Found: Parsed, FontSize: int, MakeMarkdown: Callable[[str], ft.Control],
Toggle: OnToggle) -> ft.Control:
"""The panel. MakeMarkdown renders a value (links, bold)."""
"""The panel. MakeMarkdown renders a value with Markdown in it (links, bold)."""
Rows: list[ft.Control] = []
for Item in Found.Properties:
if BooleanValue.match(Item.Value):
Shown: ft.Control = _Checkbox(Item.Value.lower() == "true", Item.Line, Toggle)
elif Item.List:
Shown = ft.Row([ft.Container(ft.Text(Entry, color=Palette.Mauve, size=FontSize - 1), bgcolor=Palette.Surface0,
border_radius=4, padding=ft.Padding.symmetric(horizontal=6, vertical=1))
Shown = ft.Row([ft.Container(ft.Text(ShownValue(Entry), color=KindColour(ValueKind(Entry)), size=FontSize - 1),
bgcolor=Palette.Surface0, border_radius=4,
padding=ft.Padding.symmetric(horizontal=6, vertical=1))
for Entry in Item.List], wrap=True, spacing=4, run_spacing=4)
elif Item.Value:
Shown = MakeMarkdown(Item.Value)
Shown = _Value(Item.Value, FontSize, MakeMarkdown)
else:
Shown = ft.Text("Empty", color=Palette.Overlay0, italic=True, size=FontSize - 1)
Rows.append(ft.Row([
ft.Container(ft.Text(Item.Key, color=Palette.Overlay0, size=FontSize - 1, max_lines=1,
overflow=ft.TextOverflow.ELLIPSIS), expand=3),
ft.Container(Shown, expand=7, alignment=ft.Alignment.CENTER_LEFT),
], spacing=12, vertical_alignment=ft.CrossAxisAlignment.CENTER))
Rows.append(ft.Container(
ft.Row([
ft.Container(ft.Text(Item.Key, color=Palette.Text, size=FontSize - 1, max_lines=1,
overflow=ft.TextOverflow.ELLIPSIS), expand=3),
ft.Container(Shown, expand=7, alignment=ft.Alignment.CENTER_LEFT),
], spacing=12, vertical_alignment=ft.CrossAxisAlignment.CENTER),
# A line between properties, like the web view's.
border=ft.Border.only(top=ft.BorderSide(1, Palette.Surface1)) if Rows else None,
padding=ft.Padding.symmetric(vertical=4),
))
return ft.Container(
ft.Column([ft.Text("Properties", color=Palette.Overlay0, size=FontSize - 1), *Rows], spacing=2, tight=True),
bgcolor=Palette.Mantle,