wezterm icon indicating copy to clipboard operation
wezterm copied to clipboard

Alternative actions for hyperlinks (e.g., copy hyperlink on ctrl+mouse left)

Open fabian-thomas opened this issue 2 years ago • 6 comments

Is your feature request related to a problem? Please describe. I'm currently using alacritty and would like to switch to wezterm for the multiplexing functionality. In alacritty one has the option to specify alernative actions for clicking on hyperlinks or links defined by regex and I would love to have that in wezterm as well. It's easiest to explain that with my current alacritty config (yaml):

  # NOTE: this is just below but the following removed:
  # - ipv6
  # - ipv4
  # - hashs
  # - versions
  # - all words
  define: &link_regex "((ipfs:|ipns:|magnet:|mailto:|gemini:|gopher:|https:|http:|news:|file:|git:|ssh:|ftp:|vnc:)\
            [^\u0000-\u001F\u007F-\u009F<>\"\\s{-}\\^⟨⟩`]+)\
            |[a-zA-Z0-9-_~./!?&@+]+/[a-zA-Z0-9-_~./!?&@]+(:[0-9]+)?(:[0-9]+)?\
            |[a-zA-Z0-9-_~./!?&@+]+(:[0-9]+)?:[0-9]+"

  define: &copy_regex "((ipfs:|ipns:|magnet:|mailto:|gemini:|gopher:|https:|http:|news:|file:|git:|ssh:|ftp:|vnc:)\
            [^\u0000-\u001F\u007F-\u009F<>\"\\s{-}\\^⟨⟩`]+)\
            |([0-9a-fA-F]{1,4}:){1,7}([0-9a-fA-F]{1,4}){0,1}(:[0-9a-fA-F]{1,4}){1,7}\
            |[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\
            |[0-9a-f]{32,64}\
            |([0-9]+\\.)+[0-9]+(-[0-9]+)?\
            |[a-zA-Z0-9-_~./!?&@+]+/[a-zA-Z0-9-_~./!?&@]+(:[0-9]+)?(:[0-9]+)?\
            |[a-zA-Z0-9-_~./!?&@+]+(:[0-9]+)?:[0-9]+\
            |[a-zA-Z0-9-_~./!?&@+:]+"
            # description:
            # protocol links
            # ipv6/mac
            # ipv4
            # hashes/git commits (git log)
            # versions
            # files with colon + line
            # files with colon + line
            # all words without space or paren (check the set of characters)

  enabled:
    # these patterns both copy
    # we have two since only like that we can copy both text and hyperlink
    # hyperlink is Alt additionally
    # this is still not perfect since we need a regex for everything we want to copy with the
    # first mode. We could add a mode where we have hyperlinks true but use the underlying text
    # nevertheless.
  - regex: None
    hyperlinks: true
    action: Copy
    post_processing: true
    mouse:
      enabled: true
      mods: Control|Alt
  - regex: *copy_regex
    hyperlinks: false
    action: Copy
    post_processing: true
    mouse:
      enabled: true
      mods: Control

  - regex: *link_regex
    hyperlinks: true
    command:
      program: "open"
      args: ["--prompt"]
    post_processing: true
    mouse:
      enabled: true
      mods: Alt
  - regex: *link_regex
    hyperlinks: true
    command: open
    post_processing: true
    mouse:
      enabled: true
      mods: None

This config provides me with the following functionality:

  1. When I click any matched link (both by regex and native hyperlink) while holding CTRL, the visible text is copied to clipboard.
  2. When I hold CTLR+ALT and click on a native (non-regex) hyperlink, the hyperlink is copied to clipboard.
  3. When I click on a hyperlink or a regex hyperlink (note that I have two regex patterns, one for copy-only text and one for real links) the link is opened.
  4. When I hold Alt and click on a link (as in 3.), I open the link while prompting for a program that should be used (note that this prompting is something I built myself and is not available in xdg-open).

Describe the solution you'd like I'm not entirely sure how this could be integrated into the current configuration logic. I feel like hyperlinks and hyperlink_rules should be unified so that one can define keybindings for both together. At least we should consider adding the following:

  • Custom actions for both hyperlinks and hyperlink rules based on mouse modifier or keyboard binding.
  • Adding actions for copying the clicked text and the resulting hyperlink to clipboard (e.g., ClipLinkAtCursor and ClipLinkTextAtCursor).
  • The clicked hyperlink could be exposed via lua. (e.g., pane:get_cursor_hyperlink()). Then one could script their own copy hyperlink.

Related: Wez did already think about unifying hyperlink configs in 2021 (https://github.com/wez/wezterm/issues/1362#issuecomment-1000457693).

fabian-thomas avatar Sep 30 '23 14:09 fabian-thomas

Did you find https://wezfurlong.org/wezterm/config/lua/window-events/open-uri.html ? I think you can probably implement what you want by implementing that event handler, together with hyperlink rules that generate a custom URI prefix that you can match on in the handler

wez avatar Oct 01 '23 17:10 wez

I already have some custom code there. I got a little bit closer to what I would want now by using the following in the handler:

local mods, _ = window:keyboard_modifiers()
if string.find(mods, "ALT") then

With that, altough a little hacky, I can assign different actions to different modifiers. But the big thing that I'm still missing here is that I can have different regexes when holding different modifier keys. For example ip addr prints the following 10.0.1.1/24. In alacritty, I have two different regexs, one that matches everything here (since it looks like a file path), and one that only matches the ip address. Like that I can just click the IP address while holding ctrl and the ip is in my clipboard.

fabian-thomas avatar Oct 01 '23 21:10 fabian-thomas

I had a quick look at quick select mode again and basically I'm in search for quickselect mode but with the mouse. Best case it would look like the following:

  • One can bind an action quickselectmousestart and quickselectmouseend to e.g. CTRL down and up.
  • During this mode all matched texts are underligned and are clickable like in (keyboard) quick select mode.
  • On click the text is copied to clipboard (or an alternative action is executed).

fabian-thomas avatar Oct 05 '23 08:10 fabian-thomas

@wez I'm not really understanding how this couldn't be done easily with a supported key assignment. Wezterm already can recognize hyperlinks since we have the action OpenLinkAtMouseCursor. So how hard could it be to have a CopyLinkAtMouseCursor ?

I'm even willing to try my hand at making a PR for this if you would be kind enough to point me in the right direction :)

adamency avatar Oct 22 '23 00:10 adamency

Without looking at the code, I would agree that this should be rather straightforward. That would indeed be a step in the right direction, whilst only providing a subset of the functionality I'm in search for.

fabian-thomas avatar Oct 22 '23 09:10 fabian-thomas

Not sure if I want what @fabian-thomas is describing here, but I'm looking at how to make clicking on links not open it, and I'd have to Ctrl+click to open a link (because I click on links accidentally too often).

Using the snippet mentioned in the comment above https://github.com/wez/wezterm/issues/4371#issuecomment-1742203328

local mods, _ = window:keyboard_modifiers()
if string.find(mods, "ALT") then

It doesn't seem to work. I tried to add some log and it seems Ctrl+Click doesn't trigger open link at all, and there's only log when mods is NONE or ENHANCED_KEY, which I'm not sure is which key. Either Ctrl+click sometimes (as in, inconsistently) appears as ENHANCED_KEY or it just doesn't appear in the log (but it rather looks like normal click is the one inconsistently appearing with ENHANCED_KEY here).

Edit: tried again with Super instead of Ctrl or Alt and it works, but I'd want to avoid that key as I'm on Windows.

Edit 2: Sorry for the noise, never mind, I found the guide for mouse binding at https://wezfurlong.org/wezterm/config/mouse.html#configuring-mouse-assignments

Huy-Ngo avatar Aug 19 '24 04:08 Huy-Ngo

If anyone landed on this page as I did while looking for this feature i.e. copy on click, the answer provided by @wez above https://github.com/wez/wezterm/issues/4371#issuecomment-1742139881 does that exactly. Thanks @wez .

Did you find https://wezfurlong.org/wezterm/config/lua/window-events/open-uri.html ? I think you can probably implement what you want by implementing that event handler, together with hyperlink rules that generate a custom URI prefix that you can match on in the handler

Below is a simple handler that will fallback to the default handlers if it's a web/mail URI, otherwise will copy to clipboard.

wezterm.on('open-uri', function(window, pane, uri)
    if not uri:match('^mailto://') and
        not uri:match('^http://') and
        not uri:match('^https://') and
        not uri:match('^www') then

        window:copy_to_clipboard(uri)
        -- prevent the default action from opening in a browser
        return false
    end
        -- otherwise, by not specifying a return value, we allow later
        -- handlers and ultimately the default action to caused the
        -- URI to be opened in the browser
end)

damnskippy avatar Dec 11 '24 20:12 damnskippy