URL detection #14

Closed
opened 2 years ago by dnkl · 28 comments
dnkl commented 2 years ago
Owner

Is this something foot should support? I.e. some kind of regex-based URL auto-detection, that turns URLs into something the user can click.

It should be noted that no matter how this is implemented, it is likely to have a performance impact. I think doing the detection when rendering (as opposed to doing it in the parser) will have the smallest performance impact.

Related: #13. Perhaps it is enough to support OSC 8 hyperlinks only?

Is this something foot should support? I.e. some kind of regex-based URL auto-detection, that turns URLs into something the user can click. It should be noted that no matter how this is implemented, it is likely to have a performance impact. I _think_ doing the detection when _rendering_ (as opposed to doing it in the parser) will have the smallest performance impact. Related: https://codeberg.org/dnkl/foot/issues/13. Perhaps it is enough to support OSC 8 hyperlinks only?
dnkl added the
enhancement
performance
labels 1 year ago

An alternative with smaller performance impact is to only detect URLs on request, e.g. pressing a keybinding to pipe the current visible text to xurls and select a URL with bemenu if there are multiple. This also has the advantage that you do not need the mouse 😄.

Alternatively, implement Ctrl+Shift+f to add jump markers to each visible URL to allow the user to choose one qutebrowser style. Kitty has this feature, it is called hints.

An alternative with smaller performance impact is to only detect URLs on request, e.g. pressing a keybinding to pipe the current visible text to [xurls][1] and select a URL with [bemenu][2] if there are multiple. This also has the advantage that you do not need the mouse :smile:. Alternatively, implement <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>f</kbd> to add jump markers to each visible URL to allow the user to choose one [qutebrowser style][3]. Kitty has this feature, it is called [hints][4]. [1]: https://github.com/mvdan/xurls [2]: https://github.com/Cloudef/bemenu [3]: https://github.com/qutebrowser/qutebrowser/blob/master/doc/img/hints.png [4]: https://github.com/kovidgoyal/kitty/tree/master/kittens/hints
dnkl commented 1 year ago
Poster
Owner

Thanks for the input! I hadn't thought of not making the URLs immediately visible, or highlighted. That certainly opens up more alternatives.

I do think highlighting all of the visible URLs, e.g. when pressing a key binding makes sense, for the visual feedback it gives the user.

Regardless, the feature must be keyboard accessable. And I wouldn't mind the design being for keyboard primarily, and mouse secondary.

Jump markers seems like a good idea to me.

Thanks for the input! I hadn't thought of _not_ making the URLs immediately visible, or highlighted. That certainly opens up more alternatives. I do think highlighting all of the visible URLs, e.g. when pressing a key binding makes sense, for the visual feedback it gives the user. Regardless, the feature **must** be keyboard accessable. And I wouldn't mind the design being for keyboard primarily, and mouse secondary. Jump markers seems like a good idea to me.
dnkl commented 1 year ago
Poster
Owner

I think I'm going to take an iterative approach to this; first version will likely be along the lines "detect all currently visible URLs and send them to a dmenu/bemenu/fuzzel-like tool".

We could of course use xurls, as mentioned, to avoid doing the parsing ourselves. But at least I envision the end result to be more integrated with foot, to maybe also support #13.

However, pipe:ing visible text, or the entire scrollback, to an external tool sounds like a really useful thing to have, in general.

I think I'm going to take an iterative approach to this; first version will likely be along the lines "detect all currently visible URLs and send them to a dmenu/bemenu/fuzzel-like tool". We could of course use xurls, as mentioned, to avoid doing the parsing ourselves. But at least I envision the end result to be more integrated with foot, to maybe also support #13. However, pipe:ing visible text, or the entire scrollback, to an external tool sounds like a really useful thing to have, in general.
dnkl commented 1 year ago
Poster
Owner

However, pipe:ing visible text, or the entire scrollback, to an external tool sounds like a really useful thing to have, in general.

This is now #29.

I think I’m going to take an iterative approach to this; first version will likely be along the lines “detect all currently visible URLs and send them to a dmenu/bemenu/fuzzel-like tool”.

Most likely, I will implement #29 first. That would allow users to go the xurls route. After that we can experiment with this one.

> However, pipe:ing visible text, or the entire scrollback, to an external tool sounds like a really useful thing to have, in general. This is now #29. > I think I’m going to take an iterative approach to this; first version will likely be along the lines “detect all currently visible URLs and send them to a dmenu/bemenu/fuzzel-like tool”. Most likely, I will implement #29 first. That would allow users to go the `xurls` route. After that we can experiment with this one.
dnkl commented 1 year ago
Poster
Owner

Using PR #40, one can now do something like this:

footrc

pipe-visible=[sh -c "xurls | fuzzel --dmenu --width=75 | xargs -r firefox"] Control+Print
Using PR https://codeberg.org/dnkl/foot/pulls/40, one can now do something like this: **footrc** ```config pipe-visible=[sh -c "xurls | fuzzel --dmenu --width=75 | xargs -r firefox"] Control+Print ```

For me, the trick to making this really comfortable to use was reversing the order of the urls in the menu so that hitting enter right away opened the most recent url:

pipe-visible=[sh -c "xurls | tac | fuzzel.sh -d | xargs -r firefox"] Control+Shift+U

For what it's worth, I personally don't feel a need for any url support beyond this.

For me, the trick to making this really comfortable to use was reversing the order of the urls in the menu so that hitting enter right away opened the most recent url: ``` pipe-visible=[sh -c "xurls | tac | fuzzel.sh -d | xargs -r firefox"] Control+Shift+U ``` For what it's worth, I personally don't feel a need for any url support beyond this.
dnkl commented 1 year ago
Poster
Owner

@ifreund

For me, the trick to making this really comfortable to use was reversing the order of the urls in the menu so that hitting enter right away opened the most recent url

That was a nice touch! I'm going to steal that, and add tac | uniq to the example in the man page.

For what it’s worth, I personally don’t feel a need for any url support beyond this.

Since implementing pipe-visible I've started to feel the same way. It is in fact much easier to get an overview of the URLs this way, than having to scan the terminal output.

I'm putting this on hold for now.

@ifreund > For me, the trick to making this really comfortable to use was reversing the order of the urls in the menu so that hitting enter right away opened the most recent url That was a nice touch! I'm going to steal that, and add `tac | uniq` to the example in the man page. > For what it’s worth, I personally don’t feel a need for any url support beyond this. Since implementing `pipe-visible` I've started to feel the same way. It is in fact much easier to get an overview of the URLs this way, than having to scan the terminal output. I'm putting this on hold for now.

Hi,

For what it’s worth, I personally don’t feel a need for any url support beyond this.

Since implementing pipe-visible I've started to feel the same way. It is in fact much easier to get an overview of the URLs this way, than having to scan the terminal output.

I think having clickable URLs would be great. My usecase are mostly IRC channels where people drop a lot of URLs in combination with short descriptions.

But I played a bit with pipe-visible and I was wondering if it was possible to also pipe the hightlight status of the visible part of the terminal? That way I could highlight an URL and run a script that extracts the highlighted part and opens that URL.

Hi, > > > For what it’s worth, I personally don’t feel a need for any url support beyond this. > > Since implementing `pipe-visible` I've started to feel the same way. It is in fact much easier to get an overview of the URLs this way, than having to scan the terminal output. > I think having clickable URLs would be great. My usecase are mostly IRC channels where people drop a lot of URLs in combination with short descriptions. But I played a bit with `pipe-visible` and I was wondering if it was possible to also pipe the *hightlight* status of the visible part of the terminal? That way I could highlight an URL and run a script that extracts the highlighted part and opens that URL.
dnkl commented 1 year ago
Poster
Owner

I think having clickable URLs would be great.

And I don't think you're alone :)

I've been thinking about this a bit, and realized that there are really two different problems: detecting URLs, and highlighting them.

I'm now pretty sure that at least I personally do not want all URLs to be highlighted as soon as they are printed by the application. First, because it would be distracting, and second, because that's not how the application that printed them wanted them to look (it could easily underline them itself, for example).

Given that "limitation", the problem becomes easier. What follows is a technical description of a possible implementation, to help me, or someone else, in the future.

We can detect URLs in mouse motion events. I.e. when the user moves the mouse, we match the text beneath it against an URL regexp. We can store the grid coordinates and use them in the button event.

We can also use one of the remaining bits in the cell structure to indicate the cell should be highlighted in some way (underlined, for example). The mouse motion event could modify the cells it matched and set this bit. This would make rendering easy and there would be zero performance impact in both the VT parser and when rendering.

But I played a bit with pipe-visible and I was wondering if it was possible to also pipe the hightlight status of the visible part of the terminal.

By highlight, do you mean selected text? I.e. text you selected with the mouse (or using the scrollback search feature)?

If so, yes, why not. It's technically very easy to implement. And I can see it being useful for other things as well.

> I think having clickable URLs would be great. And I don't think you're alone :) I've been thinking about this a bit, and realized that there are really two different problems: **detecting** URLs, and **highlighting** them. I'm now pretty sure that at least I personally do **not** want all URLs to be highlighted as soon as they are printed by the application. First, because it would be distracting, and second, because that's not how the application that printed them wanted them to look (it could easily underline them itself, for example). Given that "limitation", the problem becomes easier. What follows is a technical description of a possible implementation, to help me, or someone else, in the future. We can detect URLs in mouse motion events. I.e. when the user moves the mouse, we match the text beneath it against an URL regexp. We can store the grid coordinates and use them in the button event. We can also use one of the remaining bits in the cell structure to indicate the cell should be highlighted in some way (underlined, for example). The mouse motion event could modify the cells it matched and set this bit. This would make rendering easy and there would be zero performance impact in both the VT parser and when rendering. > But I played a bit with pipe-visible and I was wondering if it was possible to also pipe the hightlight status of the visible part of the terminal. By **highlight**, do you mean selected text? I.e. text you selected with the mouse (or using the scrollback search feature)? If so, yes, why not. It's technically very easy to implement. And I can see it being useful for other things as well.
dnkl commented 1 year ago
Poster
Owner

@birger

By highlight, do you mean selected text? I.e. text you selected with the mouse (or using the scrollback search feature)?

Or did you mean to include the escape sequences with the pipe:d text?

If you did mean selected text, then that would simply be a new key binding, pipe-selected.

If not, then it'd still be possible. Hardest part is to figure out to configure it. A global option whether to include escape sequences in pipe-visible (and pipe-scrollback), or somehow encode this in each key binding?

@birger > By highlight, do you mean selected text? I.e. text you selected with the mouse (or using the scrollback search feature)? Or did you mean to include the escape sequences with the pipe:d text? If you did mean selected text, then that would simply be a new key binding, `pipe-selected`. If not, then it'd still be possible. Hardest part is to figure out to configure it. A global option whether to include escape sequences in `pipe-visible` (and `pipe-scrollback`), or somehow encode this in each key binding?

By highlight, do you mean selected text? I.e. text you selected with the mouse (or using the scrollback search feature)?

Yes, I meant text I selected by double clicking on a text portion using the left mouse button.

Or did you mean to include the escape sequences with the pipe:d text?

If you did mean selected text, then that would simply be a new key binding, pipe-selected.

Well, I was thinking about searching for the escape sequences using a python script and extracting the selected text, but having a pipe-selected feature sounds way better!

> > > By highlight, do you mean selected text? I.e. text you selected with the mouse (or using the scrollback search feature)? Yes, I meant text I selected by double clicking on a text portion using the left mouse button. > Or did you mean to include the escape sequences with the pipe:d text? > > If you did mean selected text, then that would simply be a new key binding, `pipe-selected`. Well, I was thinking about searching for the escape sequences using a python script and extracting the selected text, but having a `pipe-selected` feature sounds way better!
dnkl commented 1 year ago
Poster
Owner

Well, I was thinking about searching for the escape sequences using a python script and extracting the selected text, but having a pipe-selected feature sounds way better!

#51

> Well, I was thinking about searching for the escape sequences using a python script and extracting the selected text, but having a pipe-selected feature sounds way better! https://codeberg.org/dnkl/foot/issues/51

Worth noting that tmux has a few solutions to this. My favorite two are
tmux-hints and
tmux-fzf-url.

I’m not saying these features shouldn’t be implemented (quite the contrary), but I
think they should be toggled with a pref and/or compile flag for
tmux/screen/dvtm/scroll users and people who prefer using the existing pipe-select
functionality.

Worth noting that tmux has a few solutions to this. My favorite two are [tmux-hints](https://github.com/Roger/tmux-hints) and [tmux-fzf-url](https://github.com/wfxr/tmux-fzf-url). I’m not saying these features shouldn’t be implemented (quite the contrary), but I think they should be toggled with a pref and/or compile flag for tmux/screen/dvtm/scroll users and people who prefer using the existing pipe-select functionality.

@dnkl I like the plan9/acme way of:

  1. select text
  2. right click the selection to send it to the "plumber" (middle click to execute)
  3. do whatever you want within the "plumber" application

In plan9/acme, the plumbing action also provided with context around the selection, such as the current working directory.

This is much more simple and powerful than just highlighting clickable URL:

  1. no custom code to detect URL (http:, ftp:, file: and how about gemini: ?)
  2. no custom code to make text clickable
  3. possibility to "plumb" any text: phone number, UPS tracking code, debugger output and react accordingly (go to file at :line:column for instance)
  4. it makes the mouse actually useful :)

Foot could allow for that, but as of now, the "pipe-selected" config doesn't allow an button press to trigger the action.

@dnkl I like the plan9/acme way of: 1. select text 2. right click the selection to send it to the "plumber" (middle click to execute) 3. do whatever you want within the "plumber" application In plan9/acme, the plumbing action also provided with context around the selection, such as the current working directory. This is much more simple and powerful than just highlighting clickable URL: 1. no custom code to detect URL (http:, ftp:, file: and how about gemini: ?) 2. no custom code to make text clickable 3. possibility to "plumb" any text: phone number, UPS tracking code, debugger output and react accordingly (go to file at :line:column for instance) 4. it makes the mouse actually useful :) Foot could allow for that, but as of now, the "pipe-selected" config doesn't allow an button press to trigger the action.
Poster
Owner

Foot could allow for that, but as of now, the “pipe-selected” config doesn’t allow an button press to trigger the action.

True, but can easily be added. All regular key binding actions can already be used in mouse bindings too. The only thing missing is the associated "plumber" action.

But yeah... the more time passes, I personally prefer the current way of handling URLs in foot. I still wouldn't be against a PR that adds visual highlighting and/or clickable URLs, as long as the implementation is simple enough, and doesn't affect performance in a negative way.

> Foot could allow for that, but as of now, the “pipe-selected” config doesn’t allow an button press to trigger the action. True, but can easily be added. All regular key binding actions can already be used in mouse bindings too. The only thing missing is the associated "plumber" action. But yeah... the more time passes, I personally prefer the current way of handling URLs in foot. I still wouldn't be against a PR that adds visual highlighting and/or clickable URLs, as long as the implementation is simple enough, and doesn't affect performance in a negative way.
Poster
Owner

The only thing missing is the associated “plumber” action.

#183

> The only thing missing is the associated “plumber” action. https://codeberg.org/dnkl/foot/issues/183

But yeah... the more time passes, I personally prefer the current way of handling URLs in foot. I still wouldn’t be against a PR that adds visual highlighting and/or clickable URLs, as long as the implementation is simple enough, and doesn’t affect performance in a negative way.

People are usually obsessing over keyboard efficiency because the tools they use don't provide great mouse features.

Clickable URL are not a bad feature per se, but the implementations are usually limited to http(s) and I rarely need to open a link from my terminal. However, I often need to sed some path:line:column to my editor. Or just open a pdf, image, etc. It makes sense to me.

> But yeah... the more time passes, I personally prefer the current way of handling URLs in foot. I still wouldn’t be against a PR that adds visual highlighting and/or clickable URLs, as long as the implementation is simple enough, and doesn’t affect performance in a negative way. People are usually obsessing over keyboard efficiency because the tools they use don't provide great mouse features. Clickable URL are not a bad feature per se, but the implementations are usually limited to http(s) and I rarely need to open a link from my terminal. However, I often need to sed some path:line:column to my editor. Or just open a pdf, image, etc. It makes sense to me.
Poster
Owner

I've decided to not implement this. At least for the time being.

One can easily adjust default.word-delimiters to better match URIs, or just use ctrl+double click, and then add one (or more) pipe-selected key/mouse bindings to open it, or send it wherever you want.

While it is slightly less efficient, in terms of number of mouse clicks, it is more flexible.

I've decided to **not** implement this. At least for the time being. One can easily adjust `default.word-delimiters` to better match URIs, or just use <kbd>ctrl</kbd>+double click, and then add one (or more) `pipe-selected` key/mouse bindings to open it, or send it wherever you want. While it is slightly less efficient, in terms of number of mouse clicks, it is more flexible.
dnkl closed this issue 12 months ago

Please consider revisiting this problem. Being able to click URLs is a feature which today is expected to be among the base acceptance criteria for a terminal emulator. Sometimes features are complicated, and sometimes they're necessary regardless.

Something which could help with the complexity cost would be waiting for the user to e.g. ctrl+click, then using the location they clicked to help inform the search for matching URLs (rather than scanning the whole term). How is this supposed to be performance intensive, by the way? My largest terminals have a whopping 11 KiB of text on screen at any given time.

A feature like qutebrowser's link follow would be a great solution, but piping links to xurls is a really poor UI as a workaround. Link following would be better than clicking, therefore would be an acceptable alternative; xurls+bemenu is worse than clicking, and therefore this issue shouldn't be closed because it's available.

Please consider revisiting this problem. Being able to click URLs is a feature which today is expected to be among the base acceptance criteria for a terminal emulator. Sometimes features are complicated, and sometimes they're necessary regardless. Something which could help with the complexity cost would be waiting for the user to e.g. ctrl+click, then using the location they clicked to help inform the search for matching URLs (rather than scanning the whole term). How is this supposed to be performance intensive, by the way? My largest terminals have a whopping 11 KiB of text on screen at any given time. A feature like qutebrowser's link follow would be a great solution, but piping links to xurls is a really poor UI as a workaround. Link following would be *better* than clicking, therefore would be an acceptable alternative; xurls+bemenu is *worse* than clicking, and therefore this issue shouldn't be closed because it's available.

@ddevault I was under the assumption that foot users would use something like tmux to use certain classes of features; however, I can see that this assumption is probably flawed. Speaking only for myself, I do prefer the tmux approach: it lets me select URLs (and do at least 10 other things) the same way in any terminal, including "dumb" terminals like virtual consoles.

Personally (once again, speaking only for myself), I use tmux-hints and a modified version of wfxr's tmux-fzf-url that can match more schemes (e.g. gemini://) and copies them to the clipboard instead of opening them with xdg-open; I have a keybinding to xdg-open my clipboard contents.

While my approach is certainly not normal, the flexibility gained from delegating these features to other programs is powerful enough to enable many different abnormal workflows.


Since the world does not revolve around me, I see two paths forward:

  1. Implement this change, but make it easy to disable.
  2. Don't implement this change, and document alternatives (e.g. the tmux approach)

In the case of path 2 being chosen, I can help document alternative approaches.

@ddevault I was under the assumption that foot users would use something like tmux to use certain classes of features; however, I can see that this assumption is probably flawed. Speaking *only for myself,* I do prefer the tmux approach: it lets me select URLs (and do at least 10 other things) the same way in any terminal, including "dumb" terminals like virtual consoles. Personally (once again, speaking only for myself), I use tmux-hints and a modified version of wfxr's tmux-fzf-url that can match more schemes (e.g. `gemini://`) and copies them to the clipboard instead of opening them with `xdg-open`; I have a keybinding to `xdg-open` my clipboard contents. While my approach is certainly not normal, the flexibility gained from delegating these features to other programs is powerful enough to enable many different abnormal workflows. ------ Since the world does not revolve around me, I see two paths forward: 1. Implement this change, but make it easy to disable. 2. Don't implement this change, and document alternatives (e.g. the tmux approach) In the case of path 2 being chosen, I can help document alternative approaches.

A feature like qutebrowser's link follow would be a great solution

@ddevault you might be interested in some of these projects that seem similar:

If those languages are a turn-off, I could try my hand at a Go implementation.

> A feature like qutebrowser's link follow would be a great solution @ddevault you might be interested in some of these projects that seem similar: - [tmux-url-select](https://github.com/dequis/tmux-url-select), written in perl - [tmux-hints](https://github.com/Roger/tmux-hints), written in rust. Basically gives the same style of hinting as qutebrowser. If those languages are a turn-off, I could try my hand at a Go implementation.

I don't want to use tmux :) I use a tiling window manager for multiplexing, not my terminal emulator. I would use at most two or three tmux features, which does not justify the additional bloat. Nor would implementing each feature independently, and wrapping my terminal session in $N$ wrappers, present a compelling alternative.

I don't want to use tmux :) I use a tiling window manager for multiplexing, not my terminal emulator. I would use at most two or three tmux features, which does not justify the additional bloat. Nor would implementing each feature independently, and wrapping my terminal session in $N$ wrappers, present a compelling alternative.

Understandable. I completely forgot that tmux allows multiplexing since I also delegate that to my WM.

Understandable. I completely forgot that tmux allows multiplexing since I also delegate that to my WM.

@ddevault have you tried the pipe-selected bound to right-click approach? URL are "clickable" if they are selected. Just like any other arbitrary piece of text.

I am happy that foot implements the mouse features that makes plan9/acme great. This makes any text "plumb-able" not just URLs, like log and debuggers output, even the actual "ls" shell output. You know, to click on pdf in the terminal to open them, or jump to your editor at file:line:col.

On the other hand, I understand that URL highlighting is a common feature to many terminal emulators, so it may be important to include it at some point. Acme or vim for than matter have some helpers to easily select some predefined patterns with a double click, for words, file path, URLs, ...

@ddevault have you tried the `pipe-selected` bound to right-click approach? URL are "clickable" if they are selected. Just like any other arbitrary piece of text. I am happy that foot implements the mouse features that makes plan9/acme great. This makes any text "plumb-able" not just URLs, like log and debuggers output, even the actual "ls" shell output. You know, to click on pdf in the terminal to open them, or jump to your editor at `file:line:col`. On the other hand, I understand that URL highlighting is a common feature to many terminal emulators, so it may be important to include it at some point. Acme or vim for than matter have some helpers to easily select some predefined patterns with a double click, for words, file path, URLs, ...

I have done something similar to that, yes, but I find it cumbersome. I simply moved back to alacritty, which already behaves the way I want.

I have done something similar to that, yes, but I find it cumbersome. I simply moved back to alacritty, which already behaves the way I want.
Poster
Owner

I did say "for now", so re-opening seems fair.

I'm happy to see a discussion about this. I think it's clear that there are foot users that prefer foot to stay out of their way, and let them use their own tools instead.

At the same time, @ddevault is right - people expect this. There's also #13 to consider.

If possible, I'd like both variants to be handled in the same way, visually. Jump labels seems like a solution that can be used for both auto-detected URLs, and OSC8 URLs (in which case the label could include the URL, which otherwise wouldn't be visible).

It would also mean URLs stay out of the way until the user triggers the show-jump-labels action (and, being a key/mouse binding, it can be unbound by users not wanting this feature).

Top it off with a url-launcher option to let users choose how to open the URLs.

I did say "for now", so re-opening seems fair. I'm happy to see a discussion about this. I think it's clear that there are foot users that prefer foot to stay out of their way, and let them use their own tools instead. At the same time, @ddevault is right - people expect this. There's also https://codeberg.org/dnkl/foot/issues/13 to consider. If possible, I'd like both variants to be handled in the same way, visually. Jump labels seems like a solution that can be used for both auto-detected URLs, and OSC8 URLs (in which case the label could include the URL, which otherwise wouldn't be visible). It would also mean URLs stay out of the way until the user triggers the show-jump-labels action (and, being a key/mouse binding, it can be unbound by users not wanting this feature). Top it off with a `url-launcher` option to let users choose how to open the URLs.
dnkl reopened this issue 10 months ago
dnkl added this to the 1.7.0 milestone 9 months ago
dnkl added a new dependency 9 months ago
Poster
Owner

Merged: 63a50afc8e

Merged: https://codeberg.org/dnkl/foot/commit/63a50afc8e7d2b315e896f4469112f4240a1592e
dnkl closed this issue 9 months ago

Thanks!

Thanks!
Sign in to join this conversation.
No Milestone
No Assignees
7 Participants
Notifications
Due Date

No due date set.

Blocks
#286 1.7.0
dnkl/foot
Loading…
There is no content yet.