Locating our own node is ^Y, not ^U
Y for you, on the map and in the mesh walk alike. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
71edf6a937
commit
f847ebd637
7 files changed
+23
-23
No files matched your search
@@ -647,7 +647,7 @@ branch on the platform per frame, and never `from meshterm.platforms import PLAT
|
||||
thing that just isn't available this paint. Dimming is presentational — `handle` stays
|
||||
the authority and no-ops. The lane is also the *only* affordance advertisement here, so
|
||||
anything the desktop reaches by a chord or a bare letter (a list's `^PgUp/^PgDn` section
|
||||
jumps, the Time Machine's `w`, the map's `^U`, a row's `Del`) earns a slot — otherwise
|
||||
jumps, the Time Machine's `w`, the map's `^Y`, a row's `Del`) earns a slot — otherwise
|
||||
it is undiscoverable on the device.
|
||||
- `meshterm specimen` prints the whole visual language through the real funnels — the
|
||||
acceptance card on-device, a preview under `--platform picocalc` on the desktop.
|
||||
|
||||
@@ -15,7 +15,7 @@ render_map`. Keys:
|
||||
* ``PgUp`` / ``PgDn`` zoom in / out,
|
||||
* ``Home`` recenters and refits to the dense core of the nodes — the *region* the mesh
|
||||
covers, and the same default view the map opens on,
|
||||
* ``^U`` (for *you*) recenters on **your own node**, keeping the zoom you chose and
|
||||
* ``^Y`` (for *you*) recenters on **your own node**, keeping the zoom you chose and
|
||||
clearing any find (the lane's ``You`` chip; its Shift half also zooms in close),
|
||||
* **typing finds nodes**: every letter key feeds a live name filter — matching nodes keep
|
||||
bright labels while the rest dim to context, ``Backspace`` edits, ``^Enter`` frames the
|
||||
@@ -287,7 +287,7 @@ class MapScreen(Screen):
|
||||
editing keys, so the typed text is always visible somewhere fixed.
|
||||
|
||||
The line spends its whole 72-cell budget, so the two view-jump keys share one atom
|
||||
(``Home/^U region/you``) and ``⇧ fine`` — a refinement of a key the line already
|
||||
(``Home/^Y region/you``) and ``⇧ fine`` — a refinement of a key the line already
|
||||
names, and the only atom here that documents a *modifier* rather than a binding —
|
||||
is the one that gives way to make room for them. The basemap's state used to hang
|
||||
off the end of this line as a suffix; it is a status atom, not a key, so it moved
|
||||
@@ -296,7 +296,7 @@ class MapScreen(Screen):
|
||||
"""
|
||||
if self._filter:
|
||||
return f"find: {self._filter}▏ · ^Enter frame · ⌫ erase · Enter/Esc clear"
|
||||
return "↑↓←→ pan · PgUp/PgDn zoom · Home/^U region/you · type to find · Esc back"
|
||||
return "↑↓←→ pan · PgUp/PgDn zoom · Home/^Y region/you · type to find · Esc back"
|
||||
|
||||
def consume_edge_scrub(self) -> int:
|
||||
"""Right-edge columns the session should force-repaint on the next paint (0 = none).
|
||||
@@ -958,7 +958,7 @@ class MapScreen(Screen):
|
||||
active filter first, the map itself only once the filter is clear.
|
||||
|
||||
Three actions reframe the view, and each has both a key and an F-key chip:
|
||||
``home`` the whole region, ``locate`` (^U, for *you*) our own node — ``locate_zoom``
|
||||
``home`` the whole region, ``locate`` (^Y, for *you*) our own node — ``locate_zoom``
|
||||
the Shift-bank variant that also homes in — and ``frame`` (^Enter) the find
|
||||
matches. ``clear_find`` drops the query without moving the view, which is also
|
||||
what plain **Enter** does.
|
||||
@@ -1041,7 +1041,7 @@ class MapScreen(Screen):
|
||||
return next((m for m in self._markers if m.is_self), None)
|
||||
|
||||
def _locate(self, vp: Viewport, *, zoom_in: bool = False) -> None:
|
||||
"""Recentre on our own node (``^U`` / the ``You`` chip), clearing any find.
|
||||
"""Recentre on our own node (``^Y`` / the ``You`` chip), clearing any find.
|
||||
|
||||
Plain ``You`` keeps the zoom the user chose — pressing it twice does the same
|
||||
thing twice, and pairing it with one Zoom + is a single extra press. Its Shift
|
||||
|
||||
@@ -229,9 +229,9 @@ _HINT_KEY_ACTIONS: dict[str, str] = {
|
||||
}
|
||||
|
||||
#: Marks a word as *some* key notation even where it isn't one this module can map: a
|
||||
#: chord (``^U``), a shifted key (``⇧Tab``), or a bare glyph key (``⌫``). An atom whose
|
||||
#: chord (``^Y``), a shifted key (``⇧Tab``), or a bare glyph key (``⌫``). An atom whose
|
||||
#: verb half carries one of these names more than the keys it opened with, so it is never
|
||||
#: dropped on the strength of the ones it did name (the map's ``Home/^U region/you``).
|
||||
#: dropped on the strength of the ones it did name (the map's ``Home/^Y region/you``).
|
||||
_KEYISH = ("^", "⇧", "⌫", "↑", "↓", "←", "→")
|
||||
|
||||
|
||||
|
||||
@@ -64,8 +64,8 @@ from .spinner import spinner_interval
|
||||
#: ``m``/``i``/``h`` are not free: prompt_toolkit spells Enter, Tab and Backspace as
|
||||
#: ``Keys.ControlM``/``ControlI``/``ControlH``, so claiming them here would rebind those keys.
|
||||
#: A chord's letter is the mnemonic of the *action*, not of one screen's word for it —
|
||||
#: ``locate`` is ^U for **you** (JP, 2026-08-09), the same key on the map and in the mesh
|
||||
#: walk, because what it names on both is our own node.
|
||||
#: ``locate`` is ^Y for **you** (JP, 2026-08-09; ^U until 2026-10-01), the same key on the
|
||||
#: map and in the mesh walk, because what it names on both is our own node.
|
||||
#:
|
||||
#: Two of these are app-wide rather than a screen's: ``to_menu`` (^W) unwinds the whole
|
||||
#: navigation stack back to the main menu, and ``quit`` (^Q, alongside the older ^C) asks
|
||||
@@ -85,9 +85,9 @@ _CTRL_LETTER_CHORDS: dict[str, str] = {
|
||||
# ^S is XOFF's key, and safe here for the same reason ^Q is not XON (see above): raw
|
||||
# mode clears IXON/IXOFF, so the terminal never eats it to freeze the screen.
|
||||
"s": "reveal",
|
||||
"u": "locate",
|
||||
"v": "paste_clipboard",
|
||||
"w": "to_menu",
|
||||
"y": "locate",
|
||||
}
|
||||
|
||||
#: Maps prompt_toolkit keys to the normalized action names screens understand.
|
||||
|
||||
@@ -46,7 +46,7 @@ window, drawn whole while whole fits and *cropped* at either edge the walk conti
|
||||
past — a chip sheared on its own half block, the way every path row in the app that
|
||||
outgrows its lane is cut. At rest the window sits at the tail, so the focus and the
|
||||
steps just taken are in view and it is the walk's start that is cropped; **←→ slide
|
||||
it** to read back over a long walk. **^U** refocuses our own node.
|
||||
it** to read back over a long walk. **^Y** refocuses our own node.
|
||||
**Typing finds** — a global filter over every node in the graph, islands included — and
|
||||
narrows the canvas's fan to matching neighbours as it goes, the focus and the came-from
|
||||
node holding through it; Enter teleports the focus to the highlighted match (the trail
|
||||
@@ -239,7 +239,7 @@ class WalkScreen(Screen):
|
||||
to stand in for *Top* and leave *Bottom* blank to keep the pretence. It takes a
|
||||
slot of the screen's own instead (JP, 2026-08-09), which is what F1-F3 are for,
|
||||
and the pager's Shift bank goes back to meaning here what it means everywhere
|
||||
else: the two ends of the list this screen scrolls. ^U reaches the same action on
|
||||
else: the two ends of the list this screen scrolls. ^Y reaches the same action on
|
||||
a keyboard, the same chord the map spends on our node.
|
||||
|
||||
Both nav slots need rows to move through, which a leaf node in a sparse graph may
|
||||
@@ -285,7 +285,7 @@ class WalkScreen(Screen):
|
||||
self._self_label = self_label
|
||||
self._prefix_bytes = prefix_bytes
|
||||
#: The walked trail of canonical ids; the focus is its last entry. Walking
|
||||
#: appends, ⌫ pops, ^U resets to us, a find teleport restarts it.
|
||||
#: appends, ⌫ pops, ^Y resets to us, a find teleport restarts it.
|
||||
self._trail: list[str] = [topo.self_id]
|
||||
#: Hops the breadcrumb line is scrolled off its *tail* end (see
|
||||
#: :meth:`_trail_text`). 0 is the resting state — the focus flush right — and
|
||||
@@ -431,7 +431,7 @@ class WalkScreen(Screen):
|
||||
atoms = ["↑↓ move"]
|
||||
if scrolls:
|
||||
atoms.append("←→ trail")
|
||||
atoms += ["Enter focus", "⌫ back", "^U you"]
|
||||
atoms += ["Enter focus", "⌫ back", "^Y you"]
|
||||
if not scrolls:
|
||||
atoms.append("type to find")
|
||||
atoms.append("Esc back")
|
||||
@@ -441,7 +441,7 @@ class WalkScreen(Screen):
|
||||
"""Move the highlight, walk, back up, find, or dismiss.
|
||||
|
||||
Home/End are the list's own ends here, as on every other scrolling screen; the jump
|
||||
back to our own node is ``locate`` (^U, and the lane's F3), which is not a place in
|
||||
back to our own node is ``locate`` (^Y, and the lane's F3), which is not a place in
|
||||
this list at all — see :attr:`fkey_lane`.
|
||||
"""
|
||||
rows = self._rows()
|
||||
@@ -491,7 +491,7 @@ class WalkScreen(Screen):
|
||||
elif action == "right":
|
||||
self._trail_scroll = max(0, self._trail_scroll - _HSCROLL_STEP)
|
||||
elif action == "locate":
|
||||
# ^U (and F3): abandon the walk rather than move within it — the trail goes
|
||||
# ^Y (and F3): abandon the walk rather than move within it — the trail goes
|
||||
# back to just us and any find narrowing the list is dropped with it.
|
||||
self._trail = [self._topo.self_id]
|
||||
self._filter = ""
|
||||
@@ -644,7 +644,7 @@ class WalkScreen(Screen):
|
||||
costs the window a cell, so the crop is measured only once both are known, else the
|
||||
line would draw a cell past the row. Sliding stops where the head comes into view
|
||||
rather than running the line off the edge, and any change to the trail itself
|
||||
resets it: a walk, a step back, a teleport and ^U all end with the focus in view,
|
||||
resets it: a walk, a step back, a teleport and ^Y all end with the focus in view,
|
||||
which is where the next move is read from.
|
||||
"""
|
||||
self._trail_width = width
|
||||
|
||||
@@ -359,15 +359,15 @@ def test_dialogs_draw_no_lane_at_all() -> None:
|
||||
def test_map_locate_is_reachable_from_both_control_keys() -> None:
|
||||
"""``locate`` is bound as a chord app-wide, so both Ctrl keys and F2 reach the same action.
|
||||
|
||||
The letter is the mnemonic of the action — ^U for *you* — so it is the same chord on
|
||||
The letter is the mnemonic of the action — ^Y for *you* — so it is the same chord on
|
||||
every screen that can point at our own node, not one screen's initial.
|
||||
"""
|
||||
from prompt_toolkit.keys import Keys
|
||||
|
||||
from meshterm.ui.tui.session import _CTRL_LETTER_CHORDS, _KEY_ACTIONS
|
||||
|
||||
assert _CTRL_LETTER_CHORDS["u"] == "locate" # the right-Ctrl rescue's half
|
||||
assert _KEY_ACTIONS[Keys.ControlU] == "locate" # the ordinary binding, generated from it
|
||||
assert _CTRL_LETTER_CHORDS["y"] == "locate" # the right-Ctrl rescue's half
|
||||
assert _KEY_ACTIONS[Keys.ControlY] == "locate" # the ordinary binding, generated from it
|
||||
|
||||
|
||||
def test_host_battery_reads_the_sysfs_supply(tmp_path, monkeypatch) -> None:
|
||||
@@ -458,7 +458,7 @@ def test_an_atom_the_lane_only_half_covers_stands() -> None:
|
||||
# The atom documents the arrows too, and no slot ever claims those.
|
||||
assert strip_lane_atoms("↑↓ PgUp/PgDn scroll", DEFAULT_LANE) == "↑↓ PgUp/PgDn scroll"
|
||||
# A second key riding in the verb half keeps the atom whole (the map's region/you).
|
||||
assert strip_lane_atoms("Home/^U region/you", DEFAULT_LANE) == "Home/^U region/you"
|
||||
assert strip_lane_atoms("Home/^Y region/you", DEFAULT_LANE) == "Home/^Y region/you"
|
||||
|
||||
|
||||
def test_a_dimmed_chip_still_covers_its_atom() -> None:
|
||||
|
||||
+1
-1
@@ -367,7 +367,7 @@ def test_walk_trail_names_carry_their_node_hues() -> None:
|
||||
|
||||
|
||||
def test_walk_locate_refocuses_us_and_home_end_walk_the_list() -> None:
|
||||
"""^U resets the walk to our own node from anywhere; Home/End are the list's ends."""
|
||||
"""^Y resets the walk to our own node from anywhere; Home/End are the list's ends."""
|
||||
# A hub of spokes off one of our neighbours: a walked-away focus with a list to move in.
|
||||
topo = MeshTopology(US, contacts=[Hub])
|
||||
hub = topo.canonical(Hub.public_key)
|
||||
|
||||
Reference in new issue
Block a user