file_picker.go

 1package macos
 2
 3import (
 4	_ "embed"
 5	"fmt"
 6	"os"
 7	"os/exec"
 8	"path/filepath"
 9	"runtime"
10	"strings"
11)
12
13//go:embed file_picker.swift
14var filePickerSwift string
15
16// OpenFilePicker launches the native macOS file picker.
17// It returns a list of selected absolute file paths.
18func OpenFilePicker(initialPath string) ([]string, error) {
19	if runtime.GOOS != "darwin" {
20		return nil, fmt.Errorf("OpenFilePicker is only supported on macOS")
21	}
22
23	tmpDir, err := os.MkdirTemp("", "matcha-filepicker")
24	if err != nil {
25		return nil, err
26	}
27	defer os.RemoveAll(tmpDir) //nolint:errcheck
28
29	swiftFile := filepath.Join(tmpDir, "file_picker.swift")
30	if err := os.WriteFile(swiftFile, []byte(filePickerSwift), 0644); err != nil {
31		return nil, err
32	}
33
34	binFile := filepath.Join(tmpDir, "file_picker")
35
36	// Compile
37	cmd := exec.Command("swiftc", swiftFile, "-o", binFile) //nolint:noctx
38	if out, err := cmd.CombinedOutput(); err != nil {
39		return nil, fmt.Errorf("failed to compile file picker helper: %w\n%s", err, string(out))
40	}
41
42	// Run
43	args := []string{}
44	if initialPath != "" {
45		args = append(args, initialPath)
46	}
47	out, err := exec.Command(binFile, args...).Output() //nolint:noctx
48	if err != nil {
49		// Exit code 1 usually means user cancelled
50		return nil, nil
51	}
52
53	trimmed := strings.TrimSpace(string(out))
54	if trimmed == "" {
55		return nil, nil
56	}
57
58	paths := strings.Split(trimmed, "\n")
59	return paths, nil
60}