Add standalone Go build alongside VSCode extension

Ports all five tools to a single 7.5 MB Windows exe with an embedded
WebView2 window, file-based config, single-instance focus, and clean
shutdown. Adds build.ps1 to build both targets from one command.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-12 01:15:39 +08:00
parent 859c7d9e7c
commit f123cbfc4a
17 changed files with 2156 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
package main
import (
"bytes"
"fmt"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"time"
)
func lockFilePath() string {
return filepath.Join(appDir(), ".hpltoolbox.lock")
}
// focusExistingInstance returns true if another instance was found and
// successfully asked to focus its window. In that case the caller should exit.
// Returns false if no live instance exists (and clears any stale lock).
func focusExistingInstance() bool {
data, err := os.ReadFile(lockFilePath())
if err != nil {
return false
}
parts := strings.Split(strings.TrimSpace(string(data)), "\n")
if len(parts) != 2 {
_ = os.Remove(lockFilePath())
return false
}
pid, errPid := strconv.Atoi(strings.TrimSpace(parts[0]))
port, errPort := strconv.Atoi(strings.TrimSpace(parts[1]))
if errPid != nil || errPort != nil {
_ = os.Remove(lockFilePath())
return false
}
// Quick liveness check: PID must exist.
if proc, err := os.FindProcess(pid); err != nil || proc == nil {
_ = os.Remove(lockFilePath())
return false
}
// Ask the running instance to focus its window.
client := &http.Client{Timeout: 1500 * time.Millisecond}
url := fmt.Sprintf("http://127.0.0.1:%d/api/focus", port)
resp, err := client.Post(url, "application/json", bytes.NewReader(nil))
if err != nil {
// Lock file is stale (process died but didn't clean up).
_ = os.Remove(lockFilePath())
return false
}
_ = resp.Body.Close()
if resp.StatusCode != http.StatusOK {
_ = os.Remove(lockFilePath())
return false
}
return true
}
func writeLockFile(port int) error {
content := fmt.Sprintf("%d\n%d\n", os.Getpid(), port)
return os.WriteFile(lockFilePath(), []byte(content), 0644)
}
func removeLockFile() {
_ = os.Remove(lockFilePath())
}