Skip to content

Commit 781059a

Browse files
committed
Initial commit
0 parents  commit 781059a

File tree

10 files changed

+349
-0
lines changed

10 files changed

+349
-0
lines changed

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright © 2024 Luís Guimarães
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

Makefile

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
BINARY_NAME = rofi-browser
2+
3+
build:
4+
go build -v
5+
6+
run: build
7+
./$(BINARY_NAME)
8+
9+
install: build
10+
sudo cp ./$(BINARY_NAME) /usr/bin/

README.md

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# rofi-browser
2+
3+
rofi-browser is a simple profile launcher for Mozilla Firefox-based browsers,
4+
enabling you to quickly launch a new profile instance from a [rofi](https://github.com/davatorium/rofi) menu.
5+
6+
## Compatibility
7+
8+
Currently works with Mozilla Firefox and LibreWolf. I'll gladly accept PR's to integrate with other browsers.
9+
10+
## Installation
11+
12+
### Arch Linux (AUR)
13+
14+
Using your favorite AUR helper, install `rofi-browser`.
15+
16+
### Binaries
17+
18+
Get a binary directly from the [Github Releases](https://github.com/obvionaoe/rofi-browser/releases)
19+
20+
### Go
21+
22+
Install using go:
23+
24+
```bash
25+
go install github.com/obvionaoe/rofi-browser
26+
```
27+
28+
## Build from source
29+
30+
To build from source, simply run:
31+
32+
```bash
33+
make install
34+
```
35+
36+
## Usage
37+
38+
```bash
39+
rofi-browser
40+
```
41+
A [rofi](https://github.com/davatorium/rofi) menu will appear, allowing you to select and launch your desired browser
42+
(by default, Firefox) profile.

cmd/browser.go

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"github.com/Wing924/shellwords"
6+
"gopkg.in/ini.v1"
7+
"log"
8+
"os"
9+
"os/exec"
10+
"strings"
11+
"syscall"
12+
)
13+
14+
const args = "--new-instance -P"
15+
16+
func getProfiles(path string) ([]string, error) {
17+
cfg, err := ini.Load(path)
18+
if err != nil {
19+
fmt.Println("test")
20+
return nil, err
21+
}
22+
23+
var profiles []string
24+
25+
for _, sec := range cfg.Sections() {
26+
if strings.Contains(sec.Name(), "Profile") {
27+
profiles = append(profiles, sec.Key("Name").String())
28+
}
29+
}
30+
31+
return profiles, nil
32+
}
33+
34+
func runBrowser(profile string) {
35+
args := strings.Join([]string{args, profile}, " ")
36+
escapedArgs, err := shellwords.Split(args)
37+
if err != nil {
38+
return
39+
}
40+
41+
executable, err := exec.LookPath(browser)
42+
if err != nil {
43+
44+
log.Fatal(err)
45+
}
46+
err = syscall.Exec(executable, escapedArgs, os.Environ())
47+
if err != nil {
48+
49+
log.Fatal(err)
50+
}
51+
}

cmd/rofi.go

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package cmd
2+
3+
import (
4+
"github.com/Wing924/shellwords"
5+
"io"
6+
"log"
7+
"os/exec"
8+
"strings"
9+
)
10+
11+
func runRofi(profiles []string) (string, error) {
12+
rofiArgs, err := shellwords.Split(rofiCmd)
13+
if err != nil {
14+
log.Fatal(err)
15+
}
16+
17+
rofi := exec.Command(rofiArgs[0], rofiArgs[1:]...)
18+
stdin, err := rofi.StdinPipe()
19+
if err != nil {
20+
log.Fatal(err)
21+
}
22+
23+
go func() {
24+
defer func(stdin io.WriteCloser) {
25+
err := stdin.Close()
26+
if err != nil {
27+
log.Fatal(err)
28+
}
29+
}(stdin)
30+
for _, s := range profiles {
31+
_, err := io.WriteString(stdin, s+"\n")
32+
if err != nil {
33+
log.Fatal(err)
34+
}
35+
}
36+
}()
37+
38+
out, err := rofi.CombinedOutput()
39+
if err != nil {
40+
log.Fatal(err)
41+
}
42+
43+
return strings.TrimSpace(string(out)), nil
44+
}

cmd/root.go

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
Copyright © 2024 Luís Guimarães
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in
12+
all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
THE SOFTWARE.
21+
*/
22+
package cmd
23+
24+
import (
25+
"github.com/spf13/cobra"
26+
"log"
27+
"os"
28+
)
29+
30+
var (
31+
browser string
32+
browserProfilesFile string
33+
sort bool
34+
rofiCmd string
35+
)
36+
37+
// rootCmd represents the base command when called without any subcommands
38+
var rootCmd = &cobra.Command{
39+
Use: "rofi-browser",
40+
Short: "A simple profile picker for Mozilla Firefox based web browsers. Uses rofi.",
41+
Long: `rofi-browser is a rofi wrapper that provides a simple way to launch
42+
specific profiles in Mozilla Firefox and some of its forks.`,
43+
Run: run,
44+
}
45+
46+
// Execute adds all child commands to the root command and sets flags appropriately.
47+
// This is called by main.main(). It only needs to happen once to the rootCmd.
48+
func Execute() {
49+
err := rootCmd.Execute()
50+
if err != nil {
51+
os.Exit(1)
52+
}
53+
}
54+
55+
func init() {
56+
rootCmd.Flags().StringVarP(
57+
&browser,
58+
"browser",
59+
"b",
60+
"firefox",
61+
"The browser to use",
62+
)
63+
rootCmd.Flags().BoolVarP(
64+
&sort,
65+
"sort",
66+
"s",
67+
true,
68+
"Sort the profiles alphabetically",
69+
)
70+
rootCmd.Flags().StringVarP(
71+
&rofiCmd,
72+
"rofi",
73+
"r",
74+
"rofi -dmenu -p \"Profile\" -no-custom",
75+
"Command to launch rofi, including flags",
76+
)
77+
}
78+
79+
func run(cmd *cobra.Command, args []string) {
80+
profilesFile := ""
81+
if browser == "firefox" {
82+
profilesFile = "~/.mozilla/firefox/profiles.ini"
83+
} else {
84+
profilesFile = "~/.librewolf/profiles.ini"
85+
}
86+
87+
profilesFile, err := expandTilde(profilesFile)
88+
profiles, err := getProfiles(profilesFile)
89+
if err != nil {
90+
log.Fatal(err)
91+
}
92+
93+
selectedProfile, err := runRofi(profiles)
94+
if err != nil {
95+
log.Fatal(err)
96+
}
97+
98+
runBrowser(selectedProfile)
99+
}

cmd/util.go

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package cmd
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"strings"
7+
)
8+
9+
func expandTilde(path string) (string, error) {
10+
dir, err := os.UserHomeDir()
11+
if err != nil {
12+
return "", err
13+
}
14+
if strings.HasPrefix(path, "~/") {
15+
return filepath.Join(dir, (path)[1:]), nil
16+
}
17+
return path, nil
18+
}

go.mod

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module github.com/obvionaoe/rofi-browser
2+
3+
go 1.22.0
4+
5+
require (
6+
github.com/Wing924/shellwords v1.1.0
7+
github.com/spf13/cobra v1.8.0
8+
gopkg.in/ini.v1 v1.67.0
9+
)
10+
11+
require (
12+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
13+
github.com/spf13/pflag v1.0.5 // indirect
14+
github.com/stretchr/testify v1.9.0 // indirect
15+
)

go.sum

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
github.com/Wing924/shellwords v1.1.0 h1:dSiaG54kIH5pP636vlQSnRFhnSrFBrDPokMUj1CwySU=
2+
github.com/Wing924/shellwords v1.1.0/go.mod h1:VWXBb1GU2vKj0ts/tn+TkAIs/uTn60rYcclSv02wSQg=
3+
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
4+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
5+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6+
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
7+
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
8+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
9+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
10+
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
11+
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
12+
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
13+
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
14+
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
15+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
16+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
17+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
18+
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
19+
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
20+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
21+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

main.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
Copyright © 2024 Luís Guimarães
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in
12+
all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
THE SOFTWARE.
21+
*/
22+
package main
23+
24+
import "github.com/obvionaoe/rofi-browser/cmd"
25+
26+
func main() {
27+
cmd.Execute()
28+
}

0 commit comments

Comments
 (0)