aboutsummaryrefslogtreecommitdiff
path: root/src/app/input
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-06-15 17:29:45 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-06-15 17:45:44 +0300
commit0099c10881fd05ddecd3b535700d41eb3f42b633 (patch)
tree0c05211953394414b35fe6930b5b45594294833a /src/app/input
parent07261e09be60ac0c145685fd11f94351cc0e5ba6 (diff)
fix: use ctrl-click for captured pane links on macos
Diffstat (limited to 'src/app/input')
-rw-r--r--src/app/input/mod.rs12
-rw-r--r--src/app/input/terminal.rs74
2 files changed, 75 insertions, 11 deletions
diff --git a/src/app/input/mod.rs b/src/app/input/mod.rs
index 339f7293..cb4b0d46 100644
--- a/src/app/input/mod.rs
+++ b/src/app/input/mod.rs
@@ -23,23 +23,13 @@ enum WheelRouting {
const WORKSPACE_DRAG_THRESHOLD: u16 = 1;
const TAB_DRAG_THRESHOLD: u16 = 1;
-#[cfg(target_os = "macos")]
-fn modified_url_click_modifier() -> KeyModifiers {
- KeyModifiers::SUPER
-}
-
-#[cfg(not(target_os = "macos"))]
fn modified_url_click_modifier() -> KeyModifiers {
KeyModifiers::CONTROL
}
#[cfg(test)]
#[test]
-fn modified_url_click_modifier_matches_platform_primary_modifier() {
- #[cfg(target_os = "macos")]
- assert_eq!(modified_url_click_modifier(), KeyModifiers::SUPER);
-
- #[cfg(not(target_os = "macos"))]
+fn modified_url_click_modifier_matches_terminal_mouse_reporting() {
assert_eq!(modified_url_click_modifier(), KeyModifiers::CONTROL);
}
diff --git a/src/app/input/terminal.rs b/src/app/input/terminal.rs
index 60f2d4cc..e13412a2 100644
--- a/src/app/input/terminal.rs
+++ b/src/app/input/terminal.rs
@@ -261,6 +261,45 @@ mod tests {
.is_some_and(crate::selection::Selection::is_visible));
}
+ #[cfg(unix)]
+ fn install_test_link_handler(app: &mut App) {
+ let plugin_root = std::env::temp_dir();
+ app.state.installed_plugins = std::collections::HashMap::from([(
+ "example.links".to_string(),
+ crate::api::schema::InstalledPluginInfo {
+ plugin_id: "example.links".into(),
+ name: "Links".into(),
+ version: "0.1.0".into(),
+ min_herdr_version: "0.6.10".into(),
+ description: None,
+ manifest_path: plugin_root.join("herdr-plugin.toml").display().to_string(),
+ plugin_root: plugin_root.display().to_string(),
+ enabled: true,
+ platforms: None,
+ build: Vec::new(),
+ actions: vec![crate::api::schema::PluginManifestAction {
+ id: "open".into(),
+ title: "Open link".into(),
+ description: None,
+ contexts: Vec::new(),
+ platforms: None,
+ command: vec!["sh".into(), "-c".into(), ":".into()],
+ }],
+ events: Vec::new(),
+ panes: Vec::new(),
+ link_handlers: vec![crate::api::schema::PluginManifestLinkHandler {
+ id: "github-issue".into(),
+ title: "Open GitHub issue".into(),
+ pattern: "^https://github\\.com/[^/]+/[^/]+/(issues|pull)/[0-9]+$".into(),
+ action: "open".into(),
+ platforms: None,
+ }],
+ source: crate::api::schema::PluginSourceInfo::default(),
+ warnings: Vec::new(),
+ },
+ )]);
+ }
+
#[tokio::test]
async fn dragging_selection_above_pane_autoscrolls_and_extends_into_scrollback() {
let mut app = app_for_mouse_test();
@@ -465,6 +504,41 @@ mod tests {
assert!(app.selection_highlight_clear_deadline.is_none());
}
+ #[cfg(unix)]
+ #[tokio::test]
+ async fn ctrl_click_url_invokes_plugin_link_handler_but_super_click_does_not() {
+ let line = "see https://github.com/ogulcancelik/herdr/issues/398";
+ let col = line.find("github").expect("url host") as u16;
+
+ let (mut ctrl_app, ctrl_info) = app_with_screen_bytes(line.as_bytes());
+ install_test_link_handler(&mut ctrl_app);
+ ctrl_app.handle_mouse(modified_mouse(
+ MouseEventKind::Down(MouseButton::Left),
+ ctrl_info.inner_rect.x + col,
+ ctrl_info.inner_rect.y,
+ KeyModifiers::CONTROL,
+ ));
+
+ let ctrl_log = ctrl_app
+ .state
+ .plugin_command_logs
+ .last()
+ .expect("ctrl-click should start plugin link handler");
+ assert_eq!(ctrl_log.plugin_id, "example.links");
+ assert_eq!(ctrl_log.action_id.as_deref(), Some("open"));
+
+ let (mut super_app, super_info) = app_with_screen_bytes(line.as_bytes());
+ install_test_link_handler(&mut super_app);
+ super_app.handle_mouse(modified_mouse(
+ MouseEventKind::Down(MouseButton::Left),
+ super_info.inner_rect.x + col,
+ super_info.inner_rect.y,
+ KeyModifiers::SUPER,
+ ));
+
+ assert!(super_app.state.plugin_command_logs.is_empty());
+ }
+
#[tokio::test]
async fn pane_cell_url_resolver_finds_visible_url() {
let line = "see https://example.com/pr/307.";