| Josh Bleecher Snyder | 78707d6 | 2025-04-30 21:06:49 +0000 | [diff] [blame] | 1 | // Package browser provides functions for opening URLs in a web browser. |
| 2 | package browser |
| 3 | |
| 4 | import ( |
| Josh Bleecher Snyder | d0a3cd6 | 2025-05-03 15:46:45 -0700 | [diff] [blame] | 5 | "log/slog" |
| Philip Zeyliger | cecba06 | 2025-06-06 18:40:16 +0000 | [diff] [blame] | 6 | "os" |
| Josh Bleecher Snyder | 78707d6 | 2025-04-30 21:06:49 +0000 | [diff] [blame] | 7 | "os/exec" |
| 8 | "runtime" |
| Josh Bleecher Snyder | 11c97f2 | 2025-05-02 16:36:46 -0700 | [diff] [blame] | 9 | "strings" |
| Josh Bleecher Snyder | 78707d6 | 2025-04-30 21:06:49 +0000 | [diff] [blame] | 10 | ) |
| 11 | |
| 12 | // Open opens the specified URL in the system's default browser. |
| 13 | // It detects the OS and uses the appropriate command: |
| Philip Zeyliger | cecba06 | 2025-06-06 18:40:16 +0000 | [diff] [blame] | 14 | // - 'open' for macOS (with optional -a flag if SKETCH_BROWSER is set) |
| 15 | // - 'cmd /c start' for Windows (or direct browser executable if SKETCH_BROWSER is set) |
| 16 | // - 'xdg-open' for Linux and other Unix-like systems (or direct browser executable if SKETCH_BROWSER is set) |
| 17 | // |
| 18 | // If SKETCH_BROWSER environment variable is set, it will be used as the browser application: |
| 19 | // - On macOS: passed to 'open -a' |
| 20 | // - On Windows/Linux: used as direct executable |
| Josh Bleecher Snyder | e54b00a | 2025-04-30 16:48:02 -0700 | [diff] [blame] | 21 | func Open(url string) { |
| Josh Bleecher Snyder | 11c97f2 | 2025-05-02 16:36:46 -0700 | [diff] [blame] | 22 | if strings.TrimSpace(url) == "" { |
| 23 | return |
| 24 | } |
| Philip Zeyliger | cecba06 | 2025-06-06 18:40:16 +0000 | [diff] [blame] | 25 | |
| 26 | browser := os.Getenv("SKETCH_BROWSER") |
| Josh Bleecher Snyder | 78707d6 | 2025-04-30 21:06:49 +0000 | [diff] [blame] | 27 | var cmd *exec.Cmd |
| Philip Zeyliger | cecba06 | 2025-06-06 18:40:16 +0000 | [diff] [blame] | 28 | |
| Josh Bleecher Snyder | 78707d6 | 2025-04-30 21:06:49 +0000 | [diff] [blame] | 29 | switch runtime.GOOS { |
| 30 | case "darwin": |
| Philip Zeyliger | cecba06 | 2025-06-06 18:40:16 +0000 | [diff] [blame] | 31 | if browser != "" { |
| 32 | cmd = exec.Command("open", "-a", browser, url) |
| 33 | } else { |
| 34 | cmd = exec.Command("open", url) |
| 35 | } |
| Josh Bleecher Snyder | 78707d6 | 2025-04-30 21:06:49 +0000 | [diff] [blame] | 36 | case "windows": |
| Philip Zeyliger | cecba06 | 2025-06-06 18:40:16 +0000 | [diff] [blame] | 37 | if browser != "" { |
| 38 | cmd = exec.Command(browser, url) |
| 39 | } else { |
| 40 | cmd = exec.Command("cmd", "/c", "start", url) |
| 41 | } |
| Josh Bleecher Snyder | 78707d6 | 2025-04-30 21:06:49 +0000 | [diff] [blame] | 42 | default: // Linux and other Unix-like systems |
| Philip Zeyliger | cecba06 | 2025-06-06 18:40:16 +0000 | [diff] [blame] | 43 | if browser != "" { |
| 44 | cmd = exec.Command(browser, url) |
| 45 | } else { |
| 46 | cmd = exec.Command("xdg-open", url) |
| 47 | } |
| Josh Bleecher Snyder | 78707d6 | 2025-04-30 21:06:49 +0000 | [diff] [blame] | 48 | } |
| Philip Zeyliger | cecba06 | 2025-06-06 18:40:16 +0000 | [diff] [blame] | 49 | |
| Josh Bleecher Snyder | 78707d6 | 2025-04-30 21:06:49 +0000 | [diff] [blame] | 50 | if b, err := cmd.CombinedOutput(); err != nil { |
| Philip Zeyliger | cecba06 | 2025-06-06 18:40:16 +0000 | [diff] [blame] | 51 | slog.Debug("failed to open browser", "err", err, "url", url, "output", string(b), "browser", browser) |
| Josh Bleecher Snyder | 78707d6 | 2025-04-30 21:06:49 +0000 | [diff] [blame] | 52 | } |
| 53 | } |