Best Way to Open URLs in Your Terminal via Tmux
Tags: tmux, fzf, linux
Published: 2024-07-07 19:18:56

Efficently open URLs by only using the keyboard. Let me show you the script I made.

## Motivation
I have been using [tmux](https://github.com/tmux/tmux/wiki) for a while now. It was really worth it, especially after I started using [neovim](https://neovim.io/). One thing was really missing though compared to my previous setup and that was opening URLs. I always used my mouse to do that, but now I couldn't even do that because I am using the good old [xterm](https://invisible-island.net/xterm/) as a terminal which doesn't have a built in feature like that.

I looked at some xterm solutions for this problem, but I knew I had to do something in tmux because it has lots of commands and such. Then I found [`tmux-urlview`](https://github.com/tmux-plugins/tmux-urlview), so I was sure I can make something cool with tmux.

## The script
The full script can be found [on my GitHub in my `.dotfiles` repository's `scripts` directory named `tmux-select-url`](https://github.com/11Firefox11/.dotfiles/blob/84f80130b9f5c5b21ebfceb4cc9b3b7b232b6e51/bin/.local/scripts/tmux-select-url).

First I had to understand the basics of the upper mentioned `tmux-urlview`. It used a basic logic: save the current tmux pane's text content (buffer) and then parse out the URLs and show a choosing menu by which the URL will be opened. So I implemented the same logic.

Starting with saving the current buffer:

```zsh
tmux capture-pane
tmux save-buffer "/tmp/tmuxsave"
tmux delete-buffer
```

Now comes some basic Linux command knowledge: get the URLs out of the file (`/tmp/tmuxsave`). That means we have to use some regex, but thankfully there are plenty out there on the internet, so we don't have to write our own. Just so duplicates are removed I also used `uniq`.

```zsh
urls=$(grep -Eoi "(http|https)://[a-zA-Z0-9+./?=_%:-]+" /tmp/$buffer_file_name | uniq)
```

We have the URLs in a variable. I had to figure out a cool way to select from them. It had to be quick and easy. My first thought was to use [`fzf`](https://github.com/junegunn/fzf) because I [already used it many times](https://tomoviktor.com/posts/tmux-useful-keybinds) with tmux, but then I also stumbled up on tmux's [`display-menu`](https://man7.org/linux/man-pages/man1/tmux.1.html#STATUS_LINE) which you can see in this post's thumbnail. 

I decided to use both. The menu is good to display few links and it's really nice because it also provides a way to assign keybinds to items. In the menu I also made it so the `http` or `https` is cut off so it is better for my eyes. For more than 5 items I decided to use `fzf` opened in a new pane.

```zsh
url_count=$(echo "$urls" | wc -l)
if [ $url_count -gt 5 ]; then
  tmux neww -n "url-select" "printf '%s\n' '$urls' | fzf --exit-0 --print-query | xargs -I {} sh -c 'xdg-open {} > /dev/null 2>&1 && tmux display-message \"#[bold]$name: Opened {}#[bold]\"'"
else
  tmux_menu="tmux display-menu -t 1 -T 'url-select'"
  index=1
  for url in ${(f)urls}; do
    clean_url=${url#*//}

    tmux_menu="$tmux_menu '$clean_url' $index 'run-shell \"xdg-open $url > /dev/null 2>&1; tmux display-message '\''#[bold]$name: Opened $url#[bold]'\''\"'"

    ((index++))
    if [ $index -gt 9 ]; then
      break
    fi
  done

  eval $tmux_menu
fi
```

The code upper isn't hard to understand, it's just dense. If you don't understand something I recommend you to read the manuals via [`man`](https://man7.org/linux/man-pages/man1/man.1.html).

I added some useful things to the script too. For example if there are no URLs don't show anything or if only one is available just open it right away.

By default `capture-buffer` only captures the currently visible parts of the pane, but by setting `S` to `-` the whole history is saved. So in the final version of the script I added that if `"full"` is passed as an argument then it will capture the full history. The full script can be found [on my GitHub in my `.dotfiles` repository's `scripts` directory named `tmux-select-url`](https://github.com/11Firefox11/.dotfiles/blob/84f80130b9f5c5b21ebfceb4cc9b3b7b232b6e51/bin/.local/scripts/tmux-select-url). Feel free to use my script.

To make it easily accessable I [binded it to `o` and `O` in my `.tmux.conf`](https://github.com/11Firefox11/.dotfiles/blob/84f80130b9f5c5b21ebfceb4cc9b3b7b232b6e51/tmux/.tmux.conf#L5-L6) (NOTE: I also added executable permission to the script and put it in my `$PATH`):

```
bind-key o run-shell -b "tmux-select-url"
bind-key O run-shell -b "tmux-select-url full"
```

<br/>

I hope that this post encourages you to make your own tmux related scripts. 

If you are interested in more of this type of content then I suggest you to read posts from [my series about improving my setup and developer productivity](https://tomoviktor.com/series/developer-productivity/page/1/).