diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..35ad4b0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*~ +terminal-url-open diff --git a/Makefile b/Makefile index 98fd166..e8a22e2 100644 --- a/Makefile +++ b/Makefile @@ -9,18 +9,17 @@ default: help help: @echo " - help - this text" @echo " - user-install - install the 'terminal://' handler for only $(USER)" - @echo " - lint - run shellcheck" @echo " - get-default - see the xdg-settings default handler for 'terminal://' scheme" -user-install: +user-install: terminal-url-open mkdir -p ~/.local/bin && \ ln -sf $(shell realpath $(SCRIPT_FILE)) ~/.local/bin && \ mkdir -p ~/.local/share/applications && \ ln -sf $(shell realpath $(DESKTOP_FILE)) ~/.local/share/applications/ && \ update-desktop-database ~/.local/share/applications -lint: - shellcheck $(SCRIPT_FILE) +terminal-url-open: terminal-url-open.go + go build -o $@ ./$< get-default: xdg-settings get default-url-scheme-handler terminal diff --git a/README.md b/README.md index 17762cb..4760ec4 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ Something simple like a [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Ide ## install +This requires a golang compiler. + ```shell git clone https://github.com/vbatts/terminal-url-handler cd terminal-url-handler @@ -29,18 +31,45 @@ i.e. [terminal-url-handler](terminal://~/src/terminal-url-handler) terminal-url-handler ``` +## Types of URIs + +multiple cases of URIs, and we are not dealing with query parameters. +No shell execution. + +- terminal:///home/user +- terminal://host:/home/user +- terminal://host/home/user +- terminal://user@host:/home/user +- terminal://user@host:port/home/user + +## default terminal? + +On most Linux desktops, the `x-terminal-emulator` is an [`update-alternatives`](https://www.man7.org/linux/man-pages/man1/update-alternatives.1.html) symlink to a Terminal app like `gnome-terminal` or whatever. + +To see alternatives for `x-terminal-emulator`, run: + +```shell +$ update-alternatives --list x-terminal-emulator +/usr/bin/gnome-terminal.wrapper +/usr/bin/koi8rxterm +/usr/bin/lxterm +/usr/bin/uxterm +/usr/bin/xfce4-terminal.wrapper +/usr/bin/xterm +``` + +To change this, say to `xfce4-terminal`, run: + +```shell +sudo update-alternatives --set x-terminal-emulator /usr/bin/xfce4-terminal.wrapper +``` + ## development happy to take contributions or enhancements. This seems like something that ought to be built-in for most desktops. -### lint - -```shell -make lint -``` - ### XDG all this business of `x-scheme-handlers` and desktop files, I am surprised there isn't a simple GUI that can help creating and indexing them. diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..cc5cf4b --- /dev/null +++ b/go.mod @@ -0,0 +1,7 @@ +module github.com/vbatts/terminal-url-handler + +go 1.22.1 + +require github.com/sirupsen/logrus v1.9.3 + +require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..21f9bfb --- /dev/null +++ b/go.sum @@ -0,0 +1,15 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/terminal-url-open b/terminal-url-open deleted file mode 100755 index 5fe2654..0000000 --- a/terminal-url-open +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -set -ue - -dir="${1#terminal://}" - -x-terminal-emulator -e "sh -c 'cd "${dir}" && \$SHELL'" diff --git a/terminal-url-open.go b/terminal-url-open.go new file mode 100644 index 0000000..2389c8e --- /dev/null +++ b/terminal-url-open.go @@ -0,0 +1,82 @@ +package main + +// multiple cases of URIs, and we are not dealing with query parameters. +// No shell execution. +// - terminal:///home/user +// - terminal://host:/home/user +// - terminal://host/home/user +// - terminal://user@host:/home/user +// - terminal://user@host:port/home/user + +import ( + "flag" + "fmt" + "net/url" + "os" + "os/exec" + "strings" + + "github.com/sirupsen/logrus" +) + +var defaultTerminal string = "x-terminal-emulator" + +func main() { + flag.Parse() + if flag.NArg() == 0 { + logrus.Fatal("no URI provided!") + } + + u, err := url.Parse(flag.Args()[0]) + if err != nil { + logrus.Fatalf("failed to parse %q: %s", flag.Args()[0], err) + } + logrus.Infof("%#v", u) + + if u.Host != "" { + logrus.Infof("need to use ssh to connect to %q", u.Host) + var user string + if u.User != nil && u.User.Username() != "" { + user = u.User.Username() + } else { + var ok bool + user, ok = os.LookupEnv("USER") + if !ok { + logrus.Fatal("could not determine username to ssh as") + } + } + + host := u.Host + port := "22" + if strings.Contains(host, ":") { + args := strings.Split(host, ":") + host = args[0] + if args[1] != "" { + port = args[1] + } + } + + cmd := exec.Command(defaultTerminal, + "-e", + fmt.Sprintf(`sh -c 'ssh -p %s -t %s@%s -- "cd %s && $SHELL -l"'`, port, user, host, u.Path), + ) + logrus.Infof("local path shell command(simple): %s", cmd.String()) + logrus.Infof("local path shell command(struct): %#v", cmd) + if err := cmd.Run(); err != nil { + logrus.Fatalf("failed to run the terminal in a local path: %s", err) + } + } else { + cmd := exec.Command(defaultTerminal, + "-e", + fmt.Sprintf(`sh -c 'if [ -d %q ] ; then cd %q && $SHELL ; else echo "WARNING: %q not found" && $SHELL ; fi'`, u.Path, u.Path, u.Path), + ) + logrus.Infof("local path shell command(simple): %s", cmd.String()) + logrus.Infof("local path shell command(struct): %#v", cmd) + if err := cmd.Run(); err != nil { + logrus.Fatalf("failed to run the terminal in a local path: %s", err) + } + } + +} + +// TODO maybe not _all_ terminals accept the same flags as gnome and xfce terminal. May need a case statement for generic situations.