diff --git a/docs/features.md b/docs/features.md index 625cb074..4249caf5 100644 --- a/docs/features.md +++ b/docs/features.md @@ -17,7 +17,7 @@ - **Tabs & splits** — always open in the current directory - **Repo-grouped sidebar** — the left tab sidebar groups rows under a header per git repository, non-repo tabs in a trailing *Scratch* section; branch switches and in-repo `cd`s never move a row (`sidebar_grouping` in `config.json`: `repo` default, `none` for a flat list) - **Command palette** ⌘ P · scrollback search ⌘ F -- **⌘-click links** · desktop notifications · copy on select (opt-in, Settings → Terminal → Clipboard) +- **⌘/Ctrl-click links** (⌘ on macOS, Ctrl on Windows/Linux) · desktop notifications · copy on select (opt-in, Settings → Terminal → Clipboard) - **Smart double-click selection** — double-click grabs the whole URL, file path, bracket/quote pair, or dictionary-segmented CJK word under the cursor; Shift-click extends a selection (toggle in Settings → Terminal → Mouse; word separators via `word_separators` in `config.json`) - **Eight themes, plus your own** — YAML seed themes with solid, gradient, or image backgrounds; iTerm2 `.itermcolors` import; in-app color editor with a background-image picker - **Sync with system** — Settings → Appearance; pick separate light and dark themes and tty7 follows the OS appearance live (`theme_follow_system`, `theme_preset_light` / `theme_preset_dark` in `config.json`) @@ -48,7 +48,7 @@ and SFTP without shelling out to `ssh`. There is no system-ssh compat mode. - **`~/.ssh/config` aliases** — type one to connect (resolved natively — common fields, best-effort — over russh), or import them as profiles in Settings - **GUI auth** — in-pane sheets for password, key passphrase, 2FA, and host-key confirmation (new vs. changed) - **Built-in SFTP** — a slide-in file panel: browse, upload / download, rename / delete / chmod, drag to Finder -- **Port forwarding** — Local / Remote / Dynamic, preconfigured or added live, plus ⌘-click `localhost:PORT` to auto-forward +- **Port forwarding** — Local / Remote / Dynamic, preconfigured or added live, plus ⌘/Ctrl-click `localhost:PORT` to auto-forward - **Jump hosts & proxies** — multi-hop via profile references or `ProxyJump`, ProxyCommand, SOCKS5 / HTTP | Entry point | Connects via | diff --git a/src/terminal/element.rs b/src/terminal/element.rs index d54fe708..6d8e173d 100644 --- a/src/terminal/element.rs +++ b/src/terminal/element.rs @@ -1189,8 +1189,11 @@ impl TerminalElement { let button = ev.button; let clicks = ev.click_count; view.update(cx, |v, cx| { - // Cmd+click opens a URL under the cursor. - let link_modifier = mods.platform || v.link_modifier_down(); + // Secondary+click (⌘ on macOS, Ctrl on Windows/Linux) opens a + // URL under the cursor. Not the raw platform key: that's Win/ + // Super off macOS, which the OS mostly swallows — and every + // other terminal there opens links on Ctrl+click. + let link_modifier = mods.secondary() || v.link_modifier_down(); if link_modifier && button == MouseButton::Left && v.open_link_at(col, row, cx) { return; } @@ -1244,7 +1247,7 @@ impl TerminalElement { if !mods.shift { v.mouse_motion(col, row, &mods); } - let include_files = mods.platform || v.link_modifier_down(); + let include_files = mods.secondary() || v.link_modifier_down(); v.hover_link_at(col, row, include_files, cx); } else { v.clear_hovered_link(cx); diff --git a/src/ui/hints.rs b/src/ui/hints.rs index ca86f68e..030c5bda 100644 --- a/src/ui/hints.rs +++ b/src/ui/hints.rs @@ -44,7 +44,7 @@ impl Tty7App { cx: &mut Context, ) { let m = &ev.modifiers; - self.set_link_modifier(m.platform, cx); + self.set_link_modifier(m.secondary(), cx); // Mirror `on_key_down`'s chord test: reject the other platform-ish key // (⌃ on macOS, Win/Super elsewhere), Alt, and Shift, so only the bare @@ -79,7 +79,8 @@ impl Tty7App { .detach(); } - /// Push the platform-modifier state down to every pane's link tracking. + /// Push the secondary-modifier state (⌘ on macOS, Ctrl elsewhere — the + /// same key that opens a link on click) down to every pane's link tracking. /// Every tab, not just the active one: `on_modifiers_changed` only fires on /// the frontmost window state, so a background tab that saw "⌘ down" but /// never the matching release would keep a stale `true` — and a stale diff --git a/src/ui/settings.rs b/src/ui/settings.rs index 7c4c8e17..76e3aad5 100644 --- a/src/ui/settings.rs +++ b/src/ui/settings.rs @@ -467,7 +467,7 @@ pub(crate) struct SettingsState { pub(crate) shell_args_input: Entity, /// Custom working-directory path (used when the strategy is `Custom`). pub(crate) wd_path_input: Entity, - /// Command template run when ⌘-clicking a file link (Links section). Empty + /// Command template run when ⌘/Ctrl-clicking a file link (Links section). Empty /// clears the override, restoring the built-in "open in default app". pub(crate) link_file_command_input: Entity, /// Mouse-scroll multiplier slider (Terminal section). @@ -622,6 +622,14 @@ pub(crate) struct Recording { /// unlikely real font name. pub(crate) const FONT_DEFAULT_LABEL: &str = "Default (match primary)"; +/// How the link-click modifier is spelled in the Links copy. It's gpui's +/// `secondary` (see `Modifiers::secondary`), so it must read ⌘ on macOS and +/// Ctrl on Windows/Linux — same split `key_tokens` uses for keycaps. +#[cfg(target_os = "macos")] +const LINK_MODIFIER_LABEL: &str = "⌘"; +#[cfg(not(target_os = "macos"))] +const LINK_MODIFIER_LABEL: &str = "Ctrl"; + /// Humanize a CamelCase action name for display: "CloseActiveTab" → "Close /// Active Tab". pub(crate) fn humanize_action(action: &str) -> String { @@ -3093,7 +3101,7 @@ impl Tty7App { .child(self.section_header("Links", cx)) .child(self.settings_row( "Detect URLs", - "Underline links on hover and open them on ⌘-click.", + format!("Underline links on hover and open them on {LINK_MODIFIER_LABEL}-click."), link_switch, cx, )) @@ -3105,9 +3113,12 @@ impl Tty7App { )) .child(self.settings_row( "Open files with", - "Command run when ⌘-clicking a file link, instead of the default app. \ - Use {path}, {line}, {column}; a flag whose value is absent is dropped \ - (e.g. herdr edit {path} --line={line}). Empty uses the default app.", + format!( + "Command run when {LINK_MODIFIER_LABEL}-clicking a file link, instead of \ + the default app. Use {{path}}, {{line}}, {{column}}; a flag whose value \ + is absent is dropped (e.g. herdr edit {{path}} --line={{line}}). Empty \ + uses the default app." + ), link_file_command_control, cx, ))