mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-21 16:02:20 +00:00
* feat(ssh): name panes after their host and reach the host form from where you are Five gaps in the SSH flow reported in #438, and the two silent no-ops around them. Panes now carry a display name: a saved host's own name, or its address when nobody named it — every host imported from ~/.ssh/config arrives nameless, and each one opened a tab reading "tty7". The name survives a title reset and a dropped link, and `strip_host_prefix` no longer cuts `deploy@10.0.0.5:2222` down to "2222" on its way to the tab strip. The host form is now reachable from the machine in front of you: the switcher's machine menu edits the host it is showing, or offers to save one for a machine reached by address or by ~/.ssh/config alias. A live connection dialled by hand can be kept as a host from the palette, with everything it was dialled with carried over — the one thing that cannot come along is an ad-hoc jump hop, and that is said out loud rather than saved broken. The New Tab menu lists the saved hosts, most-used first, and the typed address route that already understood -p, -J and config aliases. Both were behind the workspace switcher, its host dialog and the settings list. Finally, the three proxy fields are exclusive — map_proxy picks the first one filled and ignores the rest — so the ones that lose now say which field won instead of leaving it to be discovered by connecting. * feat(ssh): test a connection from the host form, and pick a host by name Three things the host form and the New Tab menu were missing. The form gets a Test button. It hands the spec to the daemon, which dials it the way Connect would — proxy, jump host, host key, auth — and drops the connection again, reporting how long it took. A test never rides an existing connection: one would answer for the credentials that connection was made with, so a password typed wrong would come back green. Anything the handshake stops to ask a person is declined on the spot and reported as what it asked for, since a form is nowhere to answer a password prompt and waiting out the two-minute prompt timeout would be a worse answer than "it got that far and wants your password". The result clears the moment a field changes: vouching for a host that was edited since is worse than saying nothing. The Auth row becomes a dropdown. Six methods is more than a segmented control can label without squeezing, and it is the row that stacks first on a narrow page. The New Tab menu scrolls — PopupMenu only does that past 20 items, and every shell on the machine plus a handful of hosts already runs off a short window — and past the five hosts it lists, Find a Host opens a filter box over all of them. * feat(new-tab): put a search box on the New Tab menu The menu is as long as the machine is — nine shells here, and a ~/.ssh/config with two dozen hosts in it is ordinary — so it needed filtering, not a scrollbar and a row leading somewhere else. A PopupMenu cannot hold a text field: it claims the keyboard for its own navigation, and there is no search input anywhere in it. So the New Tab button now opens a popover holding the same searchable list the command palette is built from, with the shells and the hosts under their own headings and one box over both. Typing filters across both groups; typing an address offers to connect to it, the way the palette does. The standalone host picker this replaces is gone with it, and the row that led there — one search reachable from the button beats two behind a menu. * revert(new-tab): put the New Tab menu back to shells only The searchable popover was the wrong shape for a button in the chrome: too big and too heavy next to the tab strip it hangs off. The menu is the plain shell list it was before this branch — byte for byte, so nothing about it needs re-reviewing — and the hosts, the search box and the row leading to a host picker are gone with it. Everything that came along to serve it goes too: the positional NewTabWithShell command, the picker's palette delegate and its compact row metrics, the standalone host palette, and the four strings they needed. Connecting to a saved host is the palette's job again, which is where it was and where it works. * fix(switcher): size and weight the machine glyphs like the icons beside them The two machine icons are drawn by hand; every other glyph in that gutter comes from lucide. Ours were built to a tighter box — ink 19.3 × 17.3 of a 24 grid against lucide's 22 × 20 — so at the same nominal 16pt the local machine rendered 11.5pt of ink beside a 14.7pt globe and read as a size smaller. Both are redrawn to lucide's extents, which also makes them agree with each other. The local machine's glyph was muted while every remote one was full strength, and while its own name was full strength either way. Beside the machine under it that read as a disabled row rather than as the computer you are sitting at. One weight for all of them now; the "Other Machines" globe keeps its dimmer register, which belongs to the muted section label it sits next to. * fix(tabs): only a port stops the host head being cut off a title Teaching `strip_host_prefix` that `deploy@10.0.0.5:2222` is an address and not a titled directory was done by requiring the tail to start with `/` or `~`. Two very common titles do neither. Debian's stock bash title is `\u@\h: \w` — a space after the colon — so `user@host: ~/work` would have stopped being cut at all, and every one of those tabs would have gone from reading `~/work` to `user@host: ~/wo…`. And tty7's own PowerShell integration writes `ann@BOX:C:/src` whenever the cwd is off the home drive, which would have read `ann@BOX:C:/src` rather than `C:/src`. Key on the port instead, which is the thing that actually makes the string an address: a tail of nothing but digits is kept whole, and everything else is the path it always was. The space belongs to the head, so the tail is trimmed on the way out. * fix(ssh): keep a connection test off the cache, off a stale form, and clear about a changed host key Three ways the new Test could answer for something other than the host in front of it. It dialled with `reuse: false` but still took the connection cache's slot lock, which is held for the whole handshake. So a test stalled every Connect to the same host behind a connection it was never going to leave them — and, queued behind a session already dialling, spent its own budget waiting and came back "connection timed out" about a host that answers fine. A test that is not going to touch the cache has no business locking it: it now skips the slot entirely, and only a reusing dial takes the guard it later fills in. The form dropped a test result whenever a typed field changed, on the grounds that the answer was about the host as it was a moment ago — but the authentication method is a dropdown, and changing it left the green line standing under a handshake the form would no longer make. And a host key that has *changed* was reported with the same words as one nobody has accepted yet. Those are not the same news: the first is a new host, the second is the server presenting a different key than the one on file. `SshTestNeed` now tells them apart and each gets its own line, in all three locales. Verified against a live sshd on localhost: refused port and unresolvable name come back in milliseconds with the connect path's own message, a password host comes back `NeedsInput { Password }` in 55 ms rather than waiting out the two-minute prompt timeout, and two tests of the same host back to back no longer serialize. * chore(palette): drop the root flag the New Tab revert left behind `grouped_root` was split out of `quick_connect_root` for the searchable host picker on the New Tab menu, which was taken back out again. Every constructor now sets the two to the same value, so the second one is a field and a doc comment describing a list that does not exist. * docs(changelog): record the SSH host form, pane names and connection test Every user-facing change in this branch: panes named after their host, the host form reached from the switcher and the palette, and Test. --------- Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>