In a chat, the point of our chip alone marks a message that names us

The notch and the point together were too heavy. The mark is now one cell,
the point of our chip in its fill, then a space before the time. Without
chips, it is ">" in our hue.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jean-Pierre MartineauandClaude Opus 5.5 committed 2026-10-13 23:05:12 -04:00
1 parent 68d5d03324
commit 691170d342
7 files changed
+52 -55

No files matched your search

+10 -9
View File
@@ -488,15 +488,16 @@ as a grouped list does. Filling a page in is editing its `.md`; no Python follow
the star in the chip's dark ink: a yellow star measured under 3:1 on the light fill for
238 of 256 hues, and the star on the page right of the chip was tried and put back (JP,
2026-10-13). A **mention** of us is the turned-over chip with no star
(`mention_chip(you=True)`); the message carrying it gets **the two ends of our chip**
in the two cells left of its time instead — notch then point, no label, in our chip's
fill (`widgets.mention_mark` → `pathline.chip_ends`; `>>` in our hue in arrow mode;
it replaced a `★`, JP 2026-10-13). Every time sits two cells right to keep the column
(`❯`, a space, the mark, then `12:34 body`), and the Messages list puts the mark left
of the row's age. Arrow mode draws the chip as
a padded reverse-video block. The PicoCalc can't put a bright slot behind text, so
there the chip keeps the normal colours and the `★` alone marks us. With no name or key from the device, the bare `★` chip stays. Path lines
(delivery paths, the packet viewer, routes) keep `★`.
(`mention_chip(you=True)`); the message carrying it gets **the point of our chip**
alone, one cell in our chip's fill, left of its time instead (`widgets.mention_mark` →
`pathline.chip_point`; `>` in our hue in arrow mode). It replaced a `★`, and then the
notch-and-point pair, which read as ugly (JP, 2026-10-13). Every time sits two cells
right to keep the column (`❯`, a space, the mark, a space, then `12:34 body`), and the
Messages list puts the mark left of the row's age. Arrow mode draws the chip as a
padded reverse-video block. The PicoCalc can't put a bright slot behind text, so there
the chip keeps the normal colours and the `★` alone marks us. With no name or key from
the device, the bare `★` chip stays. Path lines (delivery paths, the packet viewer,
routes) keep `★`.
- **The compose line draws a mention as its chip** (`ui/compose.py`, `MentionEditor`): the
moment `]` completes an `@[Name]` token it renders as the same chip the transcript will
show, and from then on it is an **atom** — ←/→ step over it, ^←/^→ never stop inside
+5 -5
View File
@@ -986,15 +986,15 @@ def _title(
text.append(" " * _BADGE_WIDTH)
# The relative age lane (right-aligned) is between the badge and the message text. Thus
# the ages are in one neat column, and all the previews start at the same position. A
# last message that names us has the ends of our chip at the left of its age, the same
# as the transcript has them at the left of the time (refer to ChatScreen._body_lines).
# last message that names us has the point of our chip at the left of its age, the same
# as the transcript has it at the left of the time (refer to ChatScreen._body_lines).
age = _ago(last.created_at) if last is not None else ""
lane = f" {age:>{_AGE_WIDTH}}"
if age and last is not None and _names_us(last, us):
mark = len(lane) - len(age) - 2 # the two cells of the mark, then the age
mark = len(lane) - len(age) - 2 # the mark, a space, then the age
text.append(lane[:mark])
text.append_text(mention_mark(us[1]))
text.append(age, style="muted")
text.append(lane[mark + 1 :], style="muted")
else:
text.append(lane, style="muted")
text.append(" ")
@@ -1057,7 +1057,7 @@ def _preview_text(
- Our own messages start with our chip, ``★ Name`` turned over (refer to
:func:`~meshterm.ui.widgets.self_chip`). A mention of our name has the chip that is
turned over, with no star. A message that names us has the ends of our chip at the
turned over, with no star. A message that names us has the point of our chip at the
left of the age of the row (refer to :func:`_title`).
- In a received channel message, the inline ``Name:`` sender is the author, in the hue
that comes from its key (the node grey when no known node has the name).
+5 -4
View File
@@ -775,9 +775,9 @@ class ChatScreen(Screen):
is marked as the reply target (the same as the ``❯`` pointer and the highlight of
the select screen).
A message that mentions our name has a mark at the left of its time: the two ends
of our chip, in its colour, with no label (refer to
:func:`~meshterm.ui.widgets.mention_mark`, JP, 2026-10-13). The chip of the mention
A message that mentions our name has a mark at the left of its time: the point of
our chip, in its colour (refer to :func:`~meshterm.ui.widgets.mention_mark`, JP,
2026-10-13). The chip of the mention
in the body is turned over, but it has no star (refer to
:func:`~meshterm.ui.widgets.mention_hop`). Thus the mark of a message that names us
is in one column, where the eye finds it when it goes down the transcript. Each time
@@ -799,6 +799,7 @@ class ChatScreen(Screen):
prefix.append("❯ " if selected else " ", style="cursor" if selected else None)
if self._names_us(body):
prefix.append_text(mention_mark(self._self_key))
prefix.append(" ")
else:
prefix.append(" ")
prefix.append(f"{stamp:%H:%M} ", style="cursor" if selected else "muted")
@@ -855,7 +856,7 @@ class ChatScreen(Screen):
Thus the user sees that a mention belongs to the node that it names. The text
around the mentions keeps the base style of the line (``cursor`` when the message
is the selected reply target, or else no style). A mention of our own name has our
chip, turned over, and the line has the ends of our chip at the left of its time
chip, turned over, and the line has the point of our chip at the left of its time
(refer to :meth:`_body_lines`). Thus a message that names us is easy to see.
The chip opens on the notch, because the node that a mention names is the
+6 -10
View File
@@ -1294,12 +1294,11 @@ def _bind_chips(platform: Platform) -> None:
_colours_of, _WEIGHT, _FLAT = _slot_colours, "not bold ", "not bold "
def chip_ends(hop: PathHop) -> Text:
"""The two ends of the chip of ``hop`` with no label between them: the notch, then the point.
def chip_point(hop: PathHop) -> Text:
"""The point of the chip of ``hop`` alone: one cell in the fill of the chip.
It is two cells in the fill of the chip, the same two cells that open and close a chip
of a destination (refer to :meth:`PathLine._notch`). A chat puts it at the left of the
time of a message that names us, in the fill of our chip (refer to
It is the same cell that closes a chip whose route goes on. A chat puts it at the left
of the time of a message that names us, in the fill of our chip (refer to
:func:`~meshterm.ui.widgets.mention_mark`). The colours come from the palette of the
platform, so the PicoCalc draws it in the fill that the chip has there.
@@ -1307,12 +1306,9 @@ def chip_ends(hop: PathHop) -> Text:
hop: The hop whose chip gives the fill.
Returns:
The two styled cells.
The one styled cell.
"""
fill = _colours_of(hop).fill
text = PathLine._notch(fill)
text.append(POWERLINE_SEP, style=f"{_FLAT}{fill}")
return text
return Text(POWERLINE_SEP, style=f"{_FLAT}{_colours_of(hop).fill}")
def _shorten(value: str, hash_bytes: int | None) -> str:
+14 -14
View File
@@ -57,7 +57,7 @@ from .marks import (
LabelRgbOf,
parse_hex,
)
from .pathline import SELF_GLYPH, PathHop, PathLine, chip_ends, path_line
from .pathline import SELF_GLYPH, PathHop, PathLine, chip_point, path_line
from .termfont import powerline_enabled
from .theme import glyph, mark_rgb, name_style, node_style, snr_style
@@ -698,8 +698,8 @@ def self_chip(name: str | None, key: str | None, *, role: str | None = None) ->
:attr:`~meshterm.ui.pathline.PathHop.inverse`).
A mention of our name is a different mark (refer to :func:`mention_chip`). The chip is
turned over, but it has no star. The message that names us has the ends of our chip at
the left of its time (refer to :func:`mention_mark`).
turned over, but it has no star. The message that names us has the point of our chip
at the left of its time (refer to :func:`mention_mark`).
Our node with no name or no key (the device did not report them) keeps the bare ``★``
chip of a route.
@@ -718,26 +718,26 @@ def self_chip(name: str | None, key: str | None, *, role: str | None = None) ->
def mention_mark(key: str | None) -> Text:
"""The mark of a message that names us: the two ends of our chip, with no label.
"""The mark of a message that names us: the point of our chip, alone.
The notch, then the point, in the fill of our chip (refer to
:func:`~meshterm.ui.pathline.chip_ends`). The chat puts it in the two cells at the left
of the time of each message that mentions our name, and the Messages list puts it at
the left of the age of a row whose last message does (JP, 2026-10-13). It replaced a
``★``. The mark has the colour of the chip that the mention has in the body, so the eye
joins the two. Where the terminal draws no chips, it is ``>>`` in our hue, the colour
that our chip has there.
One cell in the fill of our chip (refer to :func:`~meshterm.ui.pathline.chip_point`).
The chat puts it at the left of the time of each message that mentions our name, and
the Messages list puts it at the left of the age of a row whose last message does (JP,
2026-10-13). It replaced a ``★``, and then the notch and the point together, which JP
found too heavy. The mark has the colour of the chip that the mention has in the body,
so the eye joins the two. Where the terminal draws no chips, it is ``>`` in our hue,
the colour that our chip has there.
Args:
key: Our public key, which gives the hue. With ``None``, the mark has the keyless
grey, the same as the chip of the mention.
Returns:
The mark, two cells wide.
The mark, one cell wide. The caller puts a space after it.
"""
if powerline_enabled():
return chip_ends(PathHop("", key=key or None, inverse=bool(key)))
return Text(">>", style=node_style(key) if key else "node.unknown")
return chip_point(PathHop("", key=key or None, inverse=bool(key)))
return Text(">", style=node_style(key) if key else "node.unknown")
def mention_hop(name: str, key: str | None, *, you: bool = False) -> PathHop:
+4 -4
View File
@@ -1624,7 +1624,7 @@ def test_a_mention_of_our_name_takes_our_chip_with_no_star(powerline) -> None:
def test_a_message_that_names_us_has_the_mark_left_of_its_time() -> None:
"""The mark goes in the two cells before the time, and each time moves two cells right.
The suite draws no chips, so the mark is ``>>`` in our hue (refer to the widget tests
The suite draws no chips, so the mark is ``>`` in our hue (refer to the widget tests
for the two ends of the chip).
"""
from datetime import datetime, timezone
@@ -1637,12 +1637,12 @@ def test_a_message_that_names_us_has_the_mark_left_of_its_time() -> None:
]
screen = _channel_screen(messages, self_name="Me", self_key=_OUR_KEY)
rows = _strip_ansi("\n".join(screen._render_grouped(72))).splitlines()
assert any(row.startswith(f" >>{stamp} hi") for row in rows)
assert any(row.startswith(f" > {stamp} hi") for row in rows)
assert any(row.startswith(f" {stamp} hi") for row in rows) # the other message
screen.handle("up")
screen.handle("up") # the first message: the pointer, then the mark
rows = _strip_ansi("\n".join(screen._render_grouped(72))).splitlines()
assert any(row.startswith(f"❯ >>{stamp} hi") for row in rows)
assert any(row.startswith(f"❯ > {stamp} hi") for row in rows)
def _channel_screen(
@@ -1766,7 +1766,7 @@ def test_a_row_whose_last_message_names_us_has_the_mark_left_of_its_age(
lanes = _lanes([conv])
marked = _title(ctx, conv, {"chan:c0": named}, _NO_KEYS, lanes, us=us).plain
plain = _title(ctx, conv, {"chan:c0": other}, _NO_KEYS, lanes, us=us).plain
assert ">>now " in marked and ">>" not in plain
assert "> now " in marked and ">" not in plain
assert marked.index("now") == plain.index("now") # the mark takes the cells of the gap
+8 -9
View File
@@ -399,23 +399,22 @@ def test_a_mention_of_us_is_turned_over_with_no_star(powerline) -> None:
assert not mention_hop("Me", None, you=True).inverse # no key: no hue to turn over
def test_the_mark_of_a_message_that_names_us_is_the_ends_of_our_chip(powerline) -> None:
"""The notch, then the point, in the fill of our chip, and no label between them."""
def test_the_mark_of_a_message_that_names_us_is_the_point_of_our_chip(powerline) -> None:
"""One cell: the point, in the fill of our chip."""
powerline(True)
mark = mention_mark("5e7f")
fill = _span_style(mention_chip("Me", "5e7f", you=True), "Me").bgcolor.name
assert mark.plain == POWERLINE_SEP * 2
notch, point = (Style.parse(str(span.style)) for span in mark.spans)
assert notch.reverse and notch.color.name == fill # cut out of the fill
assert not point.reverse and point.color.name == fill # the point of the fill
assert mark.plain == POWERLINE_SEP
point = Style.parse(str(mark.style))
assert not point.reverse and point.color.name == fill
def test_the_mark_without_chips_is_two_arrows_in_our_hue(powerline) -> None:
"""With no chips, the mark is ``>>``, in the hue that our chip has in arrow mode."""
def test_the_mark_without_chips_is_an_arrow_in_our_hue(powerline) -> None:
"""With no chips, the mark is ``>``, in the hue that our chip has in arrow mode."""
powerline(False)
mark = mention_mark("5e7f")
assert mark.plain == ">>" and str(mark.style) == node_style("5e7f")
assert mark.plain == ">" and str(mark.style) == node_style("5e7f")
assert str(mention_mark(None).style) == "node.unknown"