In a chat, our chip is white on our fill and unknown names are black

Our chip had our hue as a light fill under dark text. It now has the fill
that each known sender gets, with a white label, and the PicoCalc can draw
that too: white on the dim twin of the hue. The hop flag is white_ink now.

A chat chip with no key keeps its grey fill, and its label is black. On the
PicoCalc it is black on the light grey of the keyless chip.

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-14 00:06:28 -04:00
1 parent b680b172d7
commit feea5a89db
11 files changed
+121 -115

No files matched your search

+8 -9
View File
@@ -13,19 +13,18 @@ can change how things behave. It does not only add new things.
- **In a chat, your messages show your name.** A channel, a direct chat, and a room put
your messages under `★` and your node's name, and the Messages list shows them in the
same way. Your name has the colour of your key, but in reverse: dark text on a light
fill, where each other sender has light text on a dark fill. A mention of your name has
the same reversed colours, and the message that has it gets a `★` in your colour at the
left of its time. Thus the messages that name you are easy to find down
the left side of the chat. On the PicoCalc, the console cannot draw a light fill, so
there the `★` marks your messages. Before, your messages showed only the `★`.
same way. Your name is white, on the same colour of box that your key gives each chip,
where each other sender has the colour of its key as the text. A mention of your name
has the same white text, and the message that has it gets a `★` in your colour at the
left of its time. Thus the messages that name you are easy to find down the left side
of the chat. Before, your messages showed only the `★`.
- **Your node's star has your colour.** The `★` that marks your node on the map, in
routes, in lists, and in a chat has the colour of your key, the same colour as your name
in a chat. Before, it was yellow. It is yellow only until the device gives MeshTerm your
key. A star in a faded part of a route stays grey.
- **In a chat, a name that MeshTerm cannot match to a node is grey.** The box around a
sender or a mention with no known node has the grey of plain text, on a darker grey. Thus
it does not stand out among the coloured names. Before, it was light blue on slate.
- **In a chat, a name that MeshTerm cannot match to a node is black on grey.** The box
around a sender or a mention with no known node has black text on a grey box. Thus it
does not stand out among the coloured names. Before, it was light blue on slate.
- **A mention has no `@` in front of it.** The coloured box around the name already says
that it is a mention. On a terminal that cannot draw the boxes, a mention keeps its `@`.
- **The line where you write a message shows each mention as a box.** When you type the
+15 -15
View File
@@ -490,22 +490,21 @@ as a grouped list does. Filling a page in is editing its `.md`; no Python follow
- **In a chat, we go by our name** (channel, DM, room, and the Messages list's preview —
nowhere else; JP, 2026-10-13). A route's bare `★` says "you already know who this is",
but a chat is a conversation between names, so our sender chip and every mention of our
name wear our name on the chip of *our key's hue, turned over* — dark ink on a light
fill of the hue (`PathHop.inverse`, the same pair as any chip in the other order), the
one light chip among the senders. Our **sender** chip is `★ Name` (`widgets.self_chip`),
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
name wear our name **in white on the normal fill of our key's hue** — the fill every
known sender gets, with white where they have their hue (`PathHop.white_ink`; JP,
2026-10-14, after a turned-over light chip read wrong). The PicoCalc draws the same
pair, white on the hue's dim twin. Our **sender** chip is `★ Name`
(`widgets.self_chip`), the star in the white label; the star on the page right of the
chip was tried and put back (JP, 2026-10-13). A **mention** of us is the same chip
with no star
(`mention_chip(you=True)`); the message carrying it gets **a `★` in our key's hue**
left of its time instead (`widgets.mention_mark`, the same on every platform and in
arrow mode). The map's yellow star, the chip's notch-and-point pair and its point alone
were all tried there and dropped (JP, 2026-10-13). Every time sits two cells right to
keep the column (`❯`, a space, the star, a space, then `12:34 body`), and the Messages
list puts the star 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 `★`.
list puts the star left of the row's age. Arrow mode draws the chip as a padded block
in the same pair. 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
@@ -539,10 +538,11 @@ as a grouped list does. Filling a page in is editing its `.md`; no Python follow
key routinely; JP, 2026-10-11), a bare hash standing in as a name, an `○` ring — takes
`node.unknown`, THE light grey for an unidentified node, everywhere and on both
platforms. One exception, a chat's **chips** (`PathHop.quiet`, via `widgets.author_chip`
and `mention_hop`): an unknown sender or mention there is the grey of plain text
(`#cccccc`) on that grey at `CHIP_LIGHTNESS`, so it stands back among the coloured
senders (JP, 2026-10-13); routes keep the keyless chip, arrow mode keeps `node.unknown`,
and the PicoCalc keeps the keyless pair (no grey background darker than its text).
and `mention_hop`): an unknown sender or mention there is **black** on a grey fill
(`#cccccc`, the grey of plain text, at `CHIP_LIGHTNESS`), so it stands back among the
coloured senders (JP, 2026-10-14; a plain-text grey label read as still lit); routes
keep the keyless chip, arrow mode keeps `node.unknown`, and the PicoCalc draws black on
its keyless light grey.
Colour is reserved for keyed identities, never seeded from a name's
characters. `node.unknown` is deliberately not `muted`: muted is chrome and may sit a
step darker, while an unidentified node is content you can still act on. Our own node
+5 -5
View File
@@ -1054,9 +1054,9 @@ def _preview_text(
It is the same as the live transcript:
- Our own messages start with our chip, ``★ Name`` turned over (refer to
- Our own messages start with our chip, ``★ Name`` in white (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 a ``★`` in our hue at the
white label, with no star. A message that names us has a ``★`` in our hue 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).
@@ -1078,8 +1078,8 @@ def _preview_text(
if last.outbound:
name, key = us
chip = self_chip(name, key, role=ORIGIN)
# Where no chips are drawn, the chip is a block in reverse video. Our node with no
# name keeps the old byline.
# Where no chips are drawn, the chip is a padded block, white on our fill. Our node
# with no name keeps the old byline.
byline = chip + Text(" ") if name and key else Text("you: ", style="accent")
_append_author(text, chip, byline)
_append_body(text, body_raw, key_of, us)
@@ -1141,7 +1141,7 @@ def _append_body(
that opens on the notch where the terminal draws chips (the same as in the transcript,
refer to :func:`~meshterm.ui.widgets.mention_chip`). It takes the node grey when the
name resolves to no node that we know. A mention of our own name (``us``) has the chip
of our key, turned over, as in the transcript.
of our key with a white label, as in the transcript.
"""
pos = 0
for match in MENTION.finditer(body):
+4 -4
View File
@@ -737,7 +737,7 @@ class ChatScreen(Screen):
sender looks exactly like that node as a hop in a route.
Our messages are the exception. They go under our name, as ``★ Name`` on a chip
that is turned over (refer to :func:`~meshterm.ui.widgets.self_chip`). A route
in white (refer to :func:`~meshterm.ui.widgets.self_chip`). A route
shows our end as the bare ``★``, but a chat is a conversation between names.
Our chip comes from the direction of the message (``outbound``), not from the
``"you"`` label. Thus a remote sender with the name ``you`` still gets the hue of
@@ -777,7 +777,7 @@ class ChatScreen(Screen):
A message that mentions our name has a mark at the left of its time: the ``★``,
in the hue of our key (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
2026-10-13). The chip of the mention in the body has our white label, but 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
@@ -856,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 a ``★`` in our hue at the left of its time
chip, in white, and the line has a ``★`` in our hue 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
@@ -882,7 +882,7 @@ class ChatScreen(Screen):
The two use this one method, so a chip in the compose line is the chip that the
message will show after the send. A mention of our name has our key and the chip
that is turned over. Each other name has the key that the names of the senders
with the white label. Each other name has the key that the names of the senders
give (refer to :meth:`_sender_key`).
"""
if self._self_name and name == self._self_name:
+2 -2
View File
@@ -123,9 +123,9 @@ class MentionEditor(LineEditor):
self._append_run(text, self.text, pos, start, overflow_at, "compose")
hop = hop_of(name)
if self.cursor == start:
hop = replace(hop, cursor=True, inverse=False)
hop = replace(hop, cursor=True, white_ink=False)
elif overflow_at is not None and end > overflow_at:
hop = replace(hop, style="err", inverse=False)
hop = replace(hop, style="err", white_ink=False)
text.append_text(hop_chip(hop, role=DESTINATION))
pos = end
self._append_run(text, self.text, pos, len(self.text), overflow_at, "compose")
+34 -28
View File
@@ -207,12 +207,16 @@ _CHIP_FG = "#0f172a"
_KEYLESS_BG = "#64748b"
#: The label of a keyless chip: the same pair as the chip of a node, in grey.
_KEYLESS_FG = _chip_label(_KEYLESS_BG)
#: The label of a quiet chip (:attr:`PathHop.quiet`): the grey of plain text, the default
#: foreground of the usual dark terminal (Windows Terminal, and the terminal of VS Code).
_QUIET_FG = "#cccccc"
#: The fill of a quiet chip: the grey of its label, darker, by the rule of the chip of a
#: node (:data:`CHIP_LIGHTNESS`).
_QUIET_BG = _chip_fill(_QUIET_FG)
#: The fill of a quiet chip (:attr:`PathHop.quiet`): the grey of plain text (``#cccccc``,
#: the default foreground of Windows Terminal and of the terminal of VS Code), darker by
#: the rule of the chip of a node (:data:`CHIP_LIGHTNESS`).
_QUIET_BG = _chip_fill("#cccccc")
#: The label of a quiet chip: black. A grey label on the grey fill read as a name that the
#: chip still lit, and black reads as a name that it does not (JP, 2026-10-14).
_QUIET_FG = "#000000"
#: The label of our chip in a chat (:attr:`PathHop.white_ink`): white, on the fill that
#: our hue gives each chip.
_WHITE = "#ffffff"
#: The chip fill of our node: a neutral dark grey. Thus the ``★`` on it reads as the
#: marker of the map and not as a chip of a node (JP, 2026-08-09). It is *not* a colour
#: of the spectrum on purpose, and it is not the white that it was before. Our end of a
@@ -324,18 +328,17 @@ class PathHop:
continues again". A chip says the opposite: that a node in the route has the
name ``⋯``. Arrow mode does not need a special case, because a bare label
between two arrows is already the same thing.
inverse: Draw the chip turned over: the hue of ``key`` is the fill, and the darker
fill of each other chip is the ink. It is our node in a chat (refer to
:func:`~meshterm.ui.widgets.self_chip`). Arrow mode draws the label in reverse
video, with the padding of a chip. The console of the PicoCalc has no light
background, so there the chip keeps the colours of each other chip.
white_ink: Draw the label in white, on the fill that the hue of ``key`` gives each
chip. It is our node in a chat (refer to :func:`~meshterm.ui.widgets.self_chip`):
the fill is the same as the fill of each known sender, and the white label
tells it from them (JP, 2026-10-14). Arrow mode draws the same pair, with the
padding of a chip. The PicoCalc draws it too, white on the dim twin of the hue.
quiet: A node with no key in a chat: a sender or a mention that nobody can
identify. Its chip is the grey of plain text on a darker fill of that grey
(:data:`_QUIET_FG`), by the same rule as the chip of a node. Thus it does not
stand out among the senders that have a colour (JP, 2026-10-13). A hop with a
key keeps its hue, and a route keeps the keyless grey. Arrow mode keeps the
``node.unknown`` grey. The console of the PicoCalc has no grey background darker
than its plain text, so there the chip keeps the keyless colours.
identify. Its chip is black on a grey fill (:data:`_QUIET_BG`), so it does not
stand out among the senders that have a colour (JP, 2026-10-14). A hop with a
key keeps its hue, and a route keeps the keyless chip. Arrow mode keeps the
``node.unknown`` grey. The PicoCalc keeps the light grey fill of its keyless chip,
with the black label.
"""
label: str
@@ -347,7 +350,7 @@ class PathHop:
style: str | None = None
cursor: bool = False
gap: bool = False
inverse: bool = False
white_ink: bool = False
quiet: bool = False
@@ -1030,8 +1033,9 @@ class PathLine:
text.append(hop.label, style="selected")
elif hop.dim:
text.append(hop.label, style="faint")
elif hop.inverse and hop.key:
text.append(f" {hop.label} ", style=f"{node_style(hop.key)} reverse")
elif hop.white_ink and hop.key:
fill, ink, _soft = _colours_of(hop)
text.append(f" {hop.label} ", style=f"{_WEIGHT}{ink} on {fill}")
elif hop.style:
text.append(hop.label, style=hop.style)
elif hop.you:
@@ -1235,9 +1239,8 @@ def _spectrum_colours(hop: PathHop) -> _ChipColours:
that automatic half, and not keep its hue among the greys. Plain mode says the same
thing when it fades the name.
A chip that is turned over (``inverse``, our node in a chat) has the same two colours
as the chip of its key, in the other order: the hue is the fill, and the dark fill is
the ink. It is the one light chip in a chat, and the contrast of the pair stays the same.
Our chip in a chat (``white_ink``) has the fill of the chip of its key, and a white
label. A quiet chip (a node with no key in a chat) is black on a grey fill.
"""
if hop.cursor:
return _ChipColours(_style_hex("cursor") or _KEYLESS_BG, _CHIP_FG, _CHIP_FG)
@@ -1247,8 +1250,8 @@ def _spectrum_colours(hop: PathHop) -> _ChipColours:
if hop.dim:
return _ChipColours(_DIM_BG, _DIM_FG, _DIM_FG)
hue = _style_hex(node_style(hop.key)) if hop.key else None
if hop.inverse and hue:
return _ChipColours(hue, _chip_fill(hue), _chip_fill(hue))
if hop.white_ink and hue:
return _ChipColours(_chip_fill(hue), _WHITE, _WHITE)
if hop.you:
ink = _self_ink()
return _ChipColours(_YOU_BG, ink, ink)
@@ -1276,9 +1279,8 @@ def _slot_colours(hop: PathHop) -> _ChipColours:
ribbon. The order of the rules is the same as on a truecolor terminal
(:func:`_spectrum_colours`).
A chip that is turned over (``inverse``) keeps the colours of each other chip here. Its
fill would be a bright slot, and the console cannot draw one as a background. In a chat,
the ``★`` in its label still tells our node from the others.
Our chip in a chat (``white_ink``) is white on the dim twin of its hue, the same rule as
on a truecolor terminal. A quiet chip is black on the light grey of the keyless chip.
"""
if hop.cursor:
return _ChipColours(_SLOT_PAGE, _SLOT_WHITE, _SLOT_WHITE)
@@ -1295,6 +1297,10 @@ def _slot_colours(hop: PathHop) -> _ChipColours:
return _ChipColours(_SLOT_PAGE, ink, ink)
hue = _style_hex(node_style(hop.key)) if hop.key else None
ink = hue if hue in DIM_TWIN else _SLOT_WHITE
if hop.white_ink and hue:
return _ChipColours(DIM_TWIN[ink], _SLOT_WHITE, _SLOT_WHITE)
if hop.quiet and not hue:
return _ChipColours(DIM_TWIN[ink], _SLOT_PAGE, _SLOT_PAGE)
return _ChipColours(DIM_TWIN[ink], ink, ink)
+3 -4
View File
@@ -146,10 +146,9 @@ def specimen_lines() -> list[RenderableType]:
# because a message goes on from its author. The mention at the end opens on the
# notch, because the node that it names is where the message goes, and it has no ``@``.
# The path line's own segment draws them, so this row is also a one-hop sample of the
# route language: the hue in the fill and the keyless grey for a node that nobody can
# identify. Our own messages go under ``★ me``, on the one chip that is turned over
# (dark on a light fill of our hue). The console of the PicoCalc has no light
# background, so there only the star marks it.
# route language: the hue in the fill, and black on grey for a node that nobody can
# identify. Our own messages go under ``★ me``, the one chip with a white label, on
# the fill of our hue.
chips = Text("chips ")
for name, key in _DEMO_NAMES[:2]:
chips.append_text(name_chip(name, key, role=ORIGIN))
+13 -13
View File
@@ -702,22 +702,22 @@ def author_chip(name: str, key: str | None) -> Text:
def self_chip(name: str | None, key: str | None, *, role: str | None = None) -> Text:
"""Our node as the sender in a chat: ``★ Name``, on the chip of our key, turned over.
"""Our node as the sender in a chat: ``★ Name``, in white, on the chip of our key.
A chat (a channel, a direct chat, a room) names each sender, and our node too. A route
shows our end as the bare ``★``, because the user never has to be told who that is. A
chat is a conversation between names, so our messages go under our name (JP,
2026-10-13). Two things make it different from the name of each other node. The ``★``
of the app comes first, in the dark ink of the chip. Also, the chip is turned over: the
other senders are a light hue on a dark fill, and ours is dark on a light fill of our
hue. A star on the page to the right of the chip was tried, and JP put it back in the
chip (2026-10-13). The console of the PicoCalc cannot draw a light background, so
there the chip keeps the colours of each other chip and the ``★`` marks us (refer to
:attr:`~meshterm.ui.pathline.PathHop.inverse`).
of the app comes first. Also, the label is white: the fill is the fill of each known
sender, the darker hue of our key, and the other senders have their hue as the label
(refer to :attr:`~meshterm.ui.pathline.PathHop.white_ink`, JP, 2026-10-14). Before,
the chip was turned over, dark on a light fill of our hue. A star on the page to the
right of the chip was also tried, and JP put it back in the chip (2026-10-13). The
PicoCalc draws the same pair, white on the dim twin of our hue.
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 a ``★`` in our hue at
the left of its time (refer to :func:`mention_mark`).
the same white on our fill, but it has no star. The message that names us has a ``★``
in our hue 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.
@@ -732,7 +732,7 @@ def self_chip(name: str | None, key: str | None, *, role: str | None = None) ->
"""
if not name or not key:
return name_chip("", you=True, role=role)
return hop_chip(PathHop(f"{SELF_GLYPH} {name}", key=key, inverse=True), role=role)
return hop_chip(PathHop(f"{SELF_GLYPH} {name}", key=key, white_ink=True), role=role)
def mention_mark(key: str | None) -> Text:
@@ -770,15 +770,15 @@ def mention_hop(name: str, key: str | None, *, you: bool = False) -> PathHop:
name: The name that the mention gives.
key: Any known prefix of the key of the node, which selects the hue. ``None`` is a
node that MeshTerm cannot place, and it has the keyless grey.
you: ``True`` if the mention names our node. Its chip is turned over, the same as
the chip of our messages (refer to :func:`self_chip`), but it has no star.
you: ``True`` if the mention names our node. Its label is white, the same as the
chip of our messages (refer to :func:`self_chip`), but it has no star.
Returns:
The hop. A caller can change it before it draws it (the compose line draws the
chip under the cursor in the white of the insertion slot).
"""
label = name if powerline_enabled() else f"@{name}"
return PathHop(label, key=key or None, inverse=you and bool(key), quiet=True)
return PathHop(label, key=key or None, white_ink=you and bool(key), quiet=True)
def mention_chip(name: str, key: str | None, *, you: bool = False) -> Text:
+4 -6
View File
@@ -1527,8 +1527,8 @@ def test_channel_self_style_keyed_on_concept_not_label() -> None:
ours = ChatMessage(text="hi", is_channel=True, channel_idx=0, outbound=True)
theirs = ChatMessage(text="you: hi", is_channel=True, channel_idx=0)
mine = _channel_screen([], self_name="Me", self_key=_OUR_KEY)
turned = f"{node_style(_OUR_KEY)} reverse"
assert _ink(mine._group_header("you", ours), " ★ Me ") == turned # our name, turned over
white = _ink(mine._group_header("you", ours), " ★ Me ") # our name, in white
assert white.startswith("bold #ffffff on ")
screen = _channel_screen([])
assert _ink(screen._group_header("you", ours), "★") == "you.mark" # no name: our star
assert _ink(screen._group_header("you", theirs), "you") == "node.unknown" # no key: grey
@@ -1606,19 +1606,17 @@ def test_a_blank_line_closes_each_author_where_the_rows_allow(
def test_a_mention_of_our_name_takes_our_chip_with_no_star(powerline) -> None:
"""The chip of a mention of us is turned over, as our sender chip, but it has no star.
"""The chip of a mention of us is white, as our sender chip, but it has no star.
The mark of a message that names us is at the left of its time (refer to the next
test). With chips, no mention has its ``@``.
"""
from meshterm.ui.theme import node_style
powerline(True)
screen = _channel_screen([], self_name="Me", self_key=_OUR_KEY)
text = screen._render_mentions("hi @[Me] and @[Bob]", selected=False)
assert "★" not in text.plain and "@" not in text.plain
me = next(s for s in text.spans if text.plain[s.start : s.end] == "Me")
assert str(me.style).endswith(f"on {node_style(_OUR_KEY).split()[-1]}") # a light fill
assert str(me.style).startswith("bold #ffffff on ") # the white label
def test_a_message_that_names_us_has_the_mark_left_of_its_time() -> None:
+5 -8
View File
@@ -236,16 +236,13 @@ def picocalc(monkeypatch: pytest.MonkeyPatch) -> None:
set_platform(PICOCALC_LYRA)
def test_the_picocalc_cannot_turn_our_chat_chip_over(picocalc: None) -> None:
"""The console has no light background, so our chat chip keeps the colours of each chip.
Its fill would be a bright slot, and the VT draws a background only from slots 0 to 7.
In a chat, the ``★`` in the label still tells our node from the others.
"""
def test_the_picocalc_draws_our_chat_chip_white_on_its_fill(picocalc: None) -> None:
"""Our chat chip has the fill of each chip of its key, and the white of slot 15."""
from meshterm.ui.pathline import _slot_colours
ours = PathHop(f"{SELF_GLYPH} Me", key="1c", inverse=True)
assert _slot_colours(ours) == _slot_colours(PathHop("Me", key="1c"))
ours = _slot_colours(PathHop(f"{SELF_GLYPH} Me", key="1c", white_ink=True))
normal = _slot_colours(PathHop("Me", key="1c"))
assert ours.fill == normal.fill and ours.ink == slot_hex(15)
def test_the_picocalc_draws_chips_from_its_eight_backgrounds(picocalc: None) -> None:
+28 -21
View File
@@ -353,29 +353,32 @@ def test_name_chip_draws_us_as_the_star_never_as_our_name(powerline) -> None:
assert _span_style(chip, "★").bgcolor.name == "#3f3f46" # a neutral grey, not a hue
def test_self_chip_is_the_chip_of_our_key_turned_over(powerline) -> None:
"""In a chat, our messages go under ``★ Name``, dark on a light fill of our hue.
def test_self_chip_is_white_on_the_fill_of_our_key(powerline) -> None:
"""In a chat, our messages go under ``★ Name``: white on the fill of each known sender.
The two colours are those of the chip of our key, in the other order. Thus the contrast
stays the same, and it is the one light chip among the senders (JP, 2026-10-13).
The fill is the fill that our hue gives each chip, and the white label tells our chip
from the other senders, whose label is their hue (JP, 2026-10-14).
"""
powerline(True)
ours = self_chip("Me", "5e7f", role=ORIGIN)
theirs = name_chip("Me", "5e7f", role=ORIGIN)
assert "★ Me" in ours.plain # the star in the chip, in its dark ink
assert "★ Me" in ours.plain # the star in the chip, in the white of the label
ink, normal = _span_style(ours, "★ Me"), _span_style(theirs, "Me")
assert (ink.color.name, ink.bgcolor.name) == (normal.bgcolor.name, normal.color.name)
assert ink.bgcolor.name == normal.bgcolor.name
assert ink.color.name == "#ffffff"
def test_self_chip_is_a_block_in_reverse_video_without_powerline(powerline) -> None:
"""With no chips, our name is still dark on the hue of our key, padded as a chip is."""
def test_self_chip_is_a_padded_block_without_powerline(powerline) -> None:
"""With no chips, our name is the same pair, padded as a chip is."""
powerline(True)
fill = _span_style(self_chip("Me", "5e7f"), "★ Me").bgcolor.name
powerline(False)
chip = self_chip("Me", "5e7f")
assert chip.plain == " ★ Me "
style = _span_style(chip, " ★ Me ")
assert style.reverse and style.color.name == node_style("5e7f").removeprefix("bold ")
assert (style.color.name, style.bgcolor.name) == ("#ffffff", fill)
def test_a_mention_chip_has_no_at_and_arrow_mode_keeps_it(powerline) -> None:
@@ -388,16 +391,16 @@ def test_a_mention_chip_has_no_at_and_arrow_mode_keeps_it(powerline) -> None:
assert mention_chip("Bob", "d4").plain == "@Bob"
def test_a_mention_of_us_is_turned_over_with_no_star(powerline) -> None:
"""A mention of our name has the chip of our key turned over, and no star in it."""
def test_a_mention_of_us_is_white_with_no_star(powerline) -> None:
"""A mention of our name has the white label on the fill of our key, and no star in it."""
powerline(True)
ours = mention_chip("Me", "5e7f", you=True)
theirs = mention_chip("Me", "5e7f")
assert "★" not in ours.plain
ink, normal = _span_style(ours, "Me"), _span_style(theirs, "Me")
assert (ink.color.name, ink.bgcolor.name) == (normal.bgcolor.name, normal.color.name)
assert not mention_hop("Me", None, you=True).inverse # no key: no hue to turn over
assert (ink.color.name, ink.bgcolor.name) == ("#ffffff", normal.bgcolor.name)
assert not mention_hop("Me", None, you=True).white_ink # no key: no hue for the fill
@pytest.mark.parametrize("chips", [True, False])
@@ -453,11 +456,11 @@ def test_name_chip_greys_a_node_it_cannot_place(powerline) -> None:
assert _span_style(keyless, "·").bgcolor.name == "#64748b" # the keyless grey
def test_a_chat_chip_with_no_key_is_the_grey_of_plain_text(powerline) -> None:
"""In a chat, an unknown sender or mention is plain-text grey on a darker fill of it.
def test_a_chat_chip_with_no_key_is_black_on_grey(powerline) -> None:
"""In a chat, an unknown sender or mention is black on a grey fill.
The fill comes from the label by the rule of the chip of a node. A node with a key keeps
its hue, and arrow mode keeps the ``node.unknown`` grey.
The fill is the grey of plain text, darker by the rule of the chip of a node. A node
with a key keeps its hue, and arrow mode keeps the ``node.unknown`` grey.
"""
from meshterm.ui.pathline import _chip_fill
from meshterm.ui.widgets import author_chip
@@ -465,16 +468,19 @@ def test_a_chat_chip_with_no_key_is_the_grey_of_plain_text(powerline) -> None:
powerline(True)
for chip, label in ((author_chip("Zed", None), "Zed"), (mention_chip("Zed", None), "Zed")):
style = _span_style(chip, label)
assert (style.color.name, style.bgcolor.name) == ("#cccccc", _chip_fill("#cccccc"))
assert (style.color.name, style.bgcolor.name) == ("#000000", _chip_fill("#cccccc"))
keyed = _span_style(author_chip("Bob", "d4"), "Bob")
assert keyed.color.name == node_style("d4").split()[-1] # a key keeps its hue
powerline(False)
assert str(author_chip("Zed", None).spans[0].style) == "node.unknown"
def test_a_chat_chip_with_no_key_keeps_the_keyless_colours_on_the_picocalc(powerline) -> None:
"""The console has no grey background darker than its plain text."""
def test_a_chat_chip_with_no_key_is_black_on_the_keyless_fill_on_the_picocalc(
powerline,
) -> None:
"""The PicoCalc keeps the light grey fill of its keyless chip, with the black label."""
from meshterm.platforms import PICOCALC_LYRA, REGULAR, set_platform
from meshterm.ui.theme import slot_hex
from meshterm.ui.widgets import author_chip
powerline(True)
@@ -482,7 +488,8 @@ def test_a_chat_chip_with_no_key_keeps_the_keyless_colours_on_the_picocalc(power
try:
quiet = _span_style(author_chip("Zed", None), "Zed")
keyless = _span_style(name_chip("Zed"), "Zed")
assert (quiet.color, quiet.bgcolor) == (keyless.color, keyless.bgcolor)
assert quiet.bgcolor == keyless.bgcolor
assert quiet.color.name == slot_hex(0) # black
finally:
set_platform(REGULAR)