Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .DS_Store
Binary file not shown.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
out/
result
*/.DS_Store
result
199 changes: 110 additions & 89 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,151 +1,172 @@
# About
# Autobrowser

Automatically choosing web-browser depends on environment context rules.
Automatically selects web browsers based on context rules.

## Features

- suckless solution with no redundant dependencies
- fast single binary
- simple rule engine with custom interpretable DSL
- cross-platform
- Fast single binary with minimal dependencies
- Simple rule engine
- Cross-platform (Linux, macOS)

# Configuration
## Configuration

## Example
Save as `~/.config/autobrowser/config.toml` or use `-config` flag.

```
work:=firefox -p job {}:url.regex='.*jira.*'

work:app.class=Slack # Open all jira links from slack with job firefox profile
work:app.class=org.telegram.desktop # Open all links from the telegram app using Isolated firefox container
### Example

# Default fallback
firefox {}:fallback
```
```toml
# Default when no rules match
default_command = "personal"

Other examples can be found in `examples` folder
# Define commands
[command.work]
cmd = ["firefox", "-p", "work", "{}"]
query_escape = true

## Configuration syntax
[command.personal]
cmd = "firefox {}"

The application just evaluates configuration rules 1 by 1 and applies url to a first matched command. Syntax can be described as:
# Define rules
[[rules]]
command = "work"
[[rules.matchers]]
type = "app"
class = "Slack"
[[rules.matchers]]
type = "url"
regex = ".*jira.*"

[[rules]]
command = "work"
[[rules.matchers]]
type = "app"
class = "org.telegram.desktop"
```
<browser_command>:<matcher_knd>.<prop_name>=<prop_value>[;<matcher_knd>.<prop_name>=<prop_value>]
```

Browser command is a sequence of words, divided by spaces. The first word is an executable name and the others are arguments. `{}` char sequence will be replaced with a clicked URL.

You can escape spaces or other _non-word characters_ can be escaped by a single-quote string.

To avoid repeating of same browser command you can user assignment syntax `command_name:=your command {}` for further use.

## Matchers

### fallback

This matcher always succeeds. Use it at the end of a configuration to specify the default browser.

### app

Matches by source application.

Currently supported desktop environments: _hyprland_, _gnome_, _sway_, _macos_.
More examples in the `examples` folder.

Hyprland/Sway/Gnome Properties:
### Matchers

- _title_: match by source window title with regex
- _class_: match by window class
#### app

MacOS Properties:
Match by source application.

- _display_name_ - match by app display name (ex: `Slack`)
- _bundle_id_ - match by App Bundle ID (ex: `com.tinyspeck.slackmacgap`)
- _bundle_path_ - match by App Bundle path (ex: `/Applications/Slack.app`)
- _executable_path_ - match by app executable path (ex: `/Applications/Slack.app/Contents/MacOS/Slack`)
Supported environments: _hyprland_, _gnome_, _sway_, _macos_

### url
```toml
[[rules.matchers]]
type = "app"
class = "Slack"
```

Match by a clicked URL.
**Linux Properties:**
- `title`: window title (regex)
- `class`: window class

Properties:
**macOS Properties:**
- `display_name`: app name
- `bundle_id`: App Bundle ID
- `bundle_path`: App Bundle path
- `executable_path`: app executable path

- _host_: match URL by host
- _scheme_: match URL by scheme
- _regex_: match full URL by regex
#### url

# Setup
Match by clicked URL.

## Linux
```toml
[[rules.matchers]]
type = "url"
host = "github.com"
```

### Gnome
**Properties:**
- `host`: match by host
- `scheme`: match by scheme
- `regex`: match full URL by regex

Due to stupidity of Gonme shell interface there is no legal way to recieve focused winow for Gnome with wayland: https://www.reddit.com/r/gnome/comments/pneza1/gdbus_call_for_moving_windows_not_working_in/
## Setup

To be able to use the `app` matcher, please [install the extenions](https://extensions.gnome.org/extension/5592/focused-window-d-bus/), that exposes currently focused window via dbus interface: https://github.com/flexagoon/focused-window-dbus
### Linux

### Prebuilt packages
#### Gnome

You can find `.rpm`, `.deb`, `.apk` and `.zst` packages on the release page.
Install [focused-window-dbus extension](https://github.com/flexagoon/focused-window-dbus) to expose the focused window.

### Linux manual
#### Installation

Clone the repository and run, you can find a result binary in the `out` directory.
**Prebuilt packages:**
Download `.rpm`, `.deb`, `.apk` or `.zst` from releases.

**Manual build:**
```sh
make build-linux
```

Create config at `~/.config/autobrowser.config`.
Then add the following .desktop file to `~/.local/share/applications/` and set it as the default browser.
Change paths for your setup if needed.
Create this `.desktop` file in `~/.local/share/applications/` and set as default browser:

```ini
[Desktop Entry]
Categories=Network;WebBrowser
Exec=~/go/bin/autobrowser -config ~/.config/autobrowser.config -url %u
Exec=/path/to/autobrowser -config ~/.config/autobrowser/config.toml -url %u
Icon=browser
MimeType=x-scheme-handler/http;x-scheme-handler/https
Name=Autobrowser: select browser by contextual rules
Name=Autobrowser
Terminal=false
Type=Application
```

## Nix home-manager

This setup works booth for linux and darwin environments.
### Nix home-manager

Actual flakes provides overlay (`overlays.default`) and module for home-manager (`autobrowser.homeModules.default`).
Works for both Linux and macOS. The flake provides an overlay and a home-manager module.

Example of home-manager module configuration:
Example configuration:

```nix
{
inputs,
...
}: {
programs.autobrowser = {
package = inputs.autobrowser.packages.x86_64-linux.default;
enable = true;
variables = {
work = "firefox 'ext+container:name=Work&url={}'";
home = "firefox {}";

# Example for darwin (MacOS) configuration
work-darwin = "open -a 'Zen' 'ext+container:name=Work&url={}'";
defaultCommand = "personal";

commands = {
work = {
cmd = ["firefox", "ext+container:name=Work&url={}"];
queryEscape = true;
};
personal = {
cmd = "firefox {}";
};
};

rules = [
"work:app.class=Slack"
"work:app.class=org.telegram.desktop;app.title='.*Work related group name.*'"

# Example for darwin (MacOS) configuration
"work-darwin:app.bundle_id='com.tinyspeck.slackmacgap'"
{
command = "work";
matchers = [
{
type = "app";
class = "Slack";
}
{
type = "url";
regex = ".*jira.*";
}
];
}
];
default = "home";
};
}
```

# Acknowledgements
## Debugging

### macOS

Monitor logs:

```
log stream --predicate 'subsystem == "dev.pltanton.autobrowser"' --style compact --level debug
```

## Acknowledgements

- [b-r-o-w-s-e](https://github.com/BlakeWilliams/b-r-o-w-s-e) project and [related article](https://blakewilliams.me/posts/handling-macos-url-schemes-with-go): great example of handling URLs with Golang on macOS
- [Finicky](https://github.com/johnste/finicky) project: inspiration for Autobrowser, good example of handling more complex URL events
- [Finicky](https://github.com/johnste/finicky) project: inspiration for Autobrowser, good example of handling more complex URL events
2 changes: 2 additions & 0 deletions common/go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/pltanton/autobrowser/common

go 1.22.1

require github.com/BurntSushi/toml v1.5.0
2 changes: 2 additions & 0 deletions common/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
Loading
Loading