Add public external file open API
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
package externalopen
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
type Runner func(name string, args ...string) error
|
||||
|
||||
type Service struct {
|
||||
goos string
|
||||
runner Runner
|
||||
}
|
||||
|
||||
func NewService() *Service {
|
||||
return NewServiceFor(runtime.GOOS, func(name string, args ...string) error {
|
||||
return exec.Command(name, args...).Start()
|
||||
})
|
||||
}
|
||||
|
||||
func NewServiceFor(goos string, runner Runner) *Service {
|
||||
return &Service{goos: goos, runner: runner}
|
||||
}
|
||||
|
||||
func (s *Service) OpenPath(path string) error {
|
||||
name, args := s.openCommand(path)
|
||||
return s.runner(name, args...)
|
||||
}
|
||||
|
||||
func (s *Service) ShowInFolder(path string, isDir bool) error {
|
||||
name, args := s.showCommand(path, isDir)
|
||||
return s.runner(name, args...)
|
||||
}
|
||||
|
||||
func (s *Service) openCommand(path string) (string, []string) {
|
||||
switch s.goos {
|
||||
case "darwin":
|
||||
return "open", []string{path}
|
||||
case "windows":
|
||||
return "rundll32", []string{"url.dll,FileProtocolHandler", path}
|
||||
default:
|
||||
return "xdg-open", []string{path}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) showCommand(path string, isDir bool) (string, []string) {
|
||||
switch s.goos {
|
||||
case "darwin":
|
||||
return "open", []string{"-R", path}
|
||||
case "windows":
|
||||
if isDir {
|
||||
return "explorer", []string{path}
|
||||
}
|
||||
return "explorer", []string{"/select," + path}
|
||||
default:
|
||||
if isDir {
|
||||
return "xdg-open", []string{path}
|
||||
}
|
||||
return "xdg-open", []string{filepath.Dir(path)}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package externalopen
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOpenPathCommands(t *testing.T) {
|
||||
cases := []struct {
|
||||
goos string
|
||||
path string
|
||||
want commandCall
|
||||
}{
|
||||
{goos: "linux", path: "/vault/file.txt", want: commandCall{name: "xdg-open", args: []string{"/vault/file.txt"}}},
|
||||
{goos: "darwin", path: "/vault/file.txt", want: commandCall{name: "open", args: []string{"/vault/file.txt"}}},
|
||||
{goos: "windows", path: `C:\Vault\file.txt`, want: commandCall{name: "rundll32", args: []string{"url.dll,FileProtocolHandler", `C:\Vault\file.txt`}}},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.goos, func(t *testing.T) {
|
||||
var got commandCall
|
||||
svc := NewServiceFor(tc.goos, func(name string, args ...string) error {
|
||||
got = commandCall{name: name, args: args}
|
||||
return nil
|
||||
})
|
||||
if err := svc.OpenPath(tc.path); err != nil {
|
||||
t.Fatalf("OpenPath: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, tc.want) {
|
||||
t.Fatalf("command = %#v, want %#v", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestShowInFolderCommands(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
goos string
|
||||
path string
|
||||
isDir bool
|
||||
want commandCall
|
||||
}{
|
||||
{name: "linux file opens parent", goos: "linux", path: "/vault/Docs/file.txt", want: commandCall{name: "xdg-open", args: []string{"/vault/Docs"}}},
|
||||
{name: "linux dir opens dir", goos: "linux", path: "/vault/Docs", isDir: true, want: commandCall{name: "xdg-open", args: []string{"/vault/Docs"}}},
|
||||
{name: "darwin reveal", goos: "darwin", path: "/vault/file.txt", want: commandCall{name: "open", args: []string{"-R", "/vault/file.txt"}}},
|
||||
{name: "windows select file", goos: "windows", path: `C:\Vault\file.txt`, want: commandCall{name: "explorer", args: []string{`/select,C:\Vault\file.txt`}}},
|
||||
{name: "windows open dir", goos: "windows", path: `C:\Vault\Docs`, isDir: true, want: commandCall{name: "explorer", args: []string{`C:\Vault\Docs`}}},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var got commandCall
|
||||
svc := NewServiceFor(tc.goos, func(name string, args ...string) error {
|
||||
got = commandCall{name: name, args: args}
|
||||
return nil
|
||||
})
|
||||
if err := svc.ShowInFolder(tc.path, tc.isDir); err != nil {
|
||||
t.Fatalf("ShowInFolder: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, tc.want) {
|
||||
t.Fatalf("command = %#v, want %#v", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type commandCall struct {
|
||||
name string
|
||||
args []string
|
||||
}
|
||||
Reference in New Issue
Block a user