refactor: tidy the command's setup, the update command and instance reach
CI / Checks (pull_request) Successful in 39s
PR title / Conventional title (pull_request) Successful in 2s

- main: the subcommand is a name rather than nil-or-empty argument slices; the cache file and start directory are worked out once; config values with a default go through one valueOr helper.
- The link handler's --config argument comes from one configArgs helper.
- lazysecrets update parses its flags like the other subcommands, so -check and --check=true work too, and tells a development build by its dev version.
- Instance reach is named (unreachable, switchable, inView), tmux client activity is compared as a number, and the best client loop starts from the first.
- update: serverTimeout (it bounds the checksums request too), and parentheses in the platform check.
This commit is contained in:
keb committed 2026-10-15 08:51:56 +02:00
1 parent b1eda53d5d
commit 386af66565
7 files changed
+105 -114

No files matched your search

+8 -5
View File
@@ -36,15 +36,18 @@ func Dir(stateDir string) string {
type Status struct {
PID int `json:"pid"`
LastActive time.Time `json:"lastActive"` // last key press or focus
// Reach is how readily it can be shown: 2 in view (outside tmux, or
// in a tmux session a client shows), 1 in a tmux session that a tmux
// client can be switched to, 0 not at all.
Reach int `json:"reach"`
Reach int `json:"reach"` // how readily it can be shown: unreachable, switchable or inView
// App is the terminal app it would show in (macOS), preferring the
// app the link was clicked in.
App string `json:"app,omitempty"`
}
const (
unreachable = 0
switchable = 1 // in a tmux session that a tmux client can be switched to
inView = 2 // outside tmux, or in a tmux session a client shows
)
type request struct {
Op string `json:"op"` // "status" or "open"
Link string `json:"link,omitempty"`
@@ -188,7 +191,7 @@ func Best(found []Found, front string, terminal bool) (Found, bool) {
best = f
}
}
return best, best.Reach > 0
return best, best.Reach > unreachable
}
// Open hands link, clicked in front, to f.
+24 -25
View File
@@ -1,6 +1,7 @@
package instance
import (
"cmp"
"os"
"os/exec"
"slices"
@@ -25,9 +26,10 @@ func tmux(args ...string) (string, error) {
func inTmux() bool { return os.Getenv("TMUX") != "" && os.Getenv("TMUX_PANE") != "" }
type client struct {
name, session, activity string // activity: Unix seconds
pid int
app string
name, session string
activity int // Unix seconds
pid int
app string
}
// clients lists the tmux server's clients, the one last typed in first.
@@ -42,30 +44,31 @@ func clients() []client {
if len(f) < 4 {
continue
}
pid, err := strconv.Atoi(f[1])
if err != nil {
activity, err1 := strconv.Atoi(f[0])
pid, err2 := strconv.Atoi(f[1])
if err1 != nil || err2 != nil {
continue
}
cs = append(cs, client{name: f[2], session: f[3], activity: f[0], pid: pid, app: linkhandler.HostApp(pid)})
cs = append(cs, client{name: f[2], session: f[3], activity: activity, pid: pid, app: linkhandler.HostApp(pid)})
}
// Activity has the same width for centuries: strings compare like
// numbers.
slices.SortStableFunc(cs, func(a, b client) int { return strings.Compare(b.activity, a.activity) })
slices.SortStableFunc(cs, func(a, b client) int { return cmp.Compare(b.activity, a.activity) })
return cs
}
// place is where this instance would show: the tmux client (zero outside
// tmux), the app, and reach: 2 already on screen there (outside tmux, or
// a client on its session), 1 after switching a client, 0 nowhere.
// tmux), the app, and its reach.
func place(front string) (client, string, int) {
if !inTmux() {
return client{}, linkhandler.HostApp(os.Getpid()), 2
return client{}, linkhandler.HostApp(os.Getpid()), inView
}
session, err := tmux("display-message", "-p", "-t", os.Getenv("TMUX_PANE"), "#{session_name}")
if err != nil {
return client{}, "", 0
return client{}, "", unreachable
}
cs := clients()
if len(cs) == 0 {
return client{}, "", unreachable
}
// Best first: in the front app on its session, in the front app,
// on its session, any.
rank := func(c client) int {
@@ -78,20 +81,16 @@ func place(front string) (client, string, int) {
}
return r
}
var best client
found := false
for _, c := range cs {
if !found || rank(c) > rank(best) {
best, found = c, true
best := cs[0]
for _, c := range cs[1:] {
if rank(c) > rank(best) {
best = c
}
}
if !found {
return client{}, "", 0
}
if best.session == session {
return best, best.app, 2
return best, best.app, inView
}
return best, best.app, 1
return best, best.app, switchable
}
// Raise brings this instance into view for a link clicked in front: in
@@ -99,14 +98,14 @@ func place(front string) (client, string, int) {
// then its app to the front, showing a hidden dropdown terminal.
func Raise(front string) {
c, app, reach := place(front)
if reach == 0 {
if reach == unreachable {
return
}
if inTmux() {
pane := os.Getenv("TMUX_PANE")
_, _ = tmux("select-window", "-t", pane)
_, _ = tmux("select-pane", "-t", pane)
if reach == 1 {
if reach == switchable {
_, _ = tmux("switch-client", "-c", c.name, "-t", pane)
}
}
+6 -6
View File
@@ -45,9 +45,9 @@ const (
// DefaultServers are where releases are looked for, in order.
var DefaultServers = []string{GitHubRepo, DefaultRepo}
// latestTimeout bounds asking one server for the latest release, so a
// server that's down leaves time for the next.
const latestTimeout = 5 * time.Second
// serverTimeout bounds asking one server for the latest release or its
// checksums, so a server that's down leaves time for the next.
const serverTimeout = 5 * time.Second
// maxDownload bounds what's read from the server.
const maxDownload = 200 << 20
@@ -153,7 +153,7 @@ func (c *Client) latest(ctx context.Context, repo string) (Release, error) {
if err != nil {
return Release{}, err
}
ctx, cancel := context.WithTimeout(ctx, latestTimeout)
ctx, cancel := context.WithTimeout(ctx, serverTimeout)
defer cancel()
// The recent releases in one request (per_page on GitHub, limit on
// Gitea), for their changelogs.
@@ -222,7 +222,7 @@ func (c *Client) Install(ctx context.Context, r Release, exe string) error {
if m := Managed(exe); m != "" {
return fmt.Errorf("%s is managed by %s: update it there", exe, m)
}
if runtime.GOOS != "darwin" && runtime.GOOS != "linux" || runtime.GOARCH != "amd64" && runtime.GOARCH != "arm64" {
if (runtime.GOOS != "darwin" && runtime.GOOS != "linux") || (runtime.GOARCH != "amd64" && runtime.GOARCH != "arm64") {
return fmt.Errorf("no release build for %s/%s", runtime.GOOS, runtime.GOARCH)
}
version := strings.TrimPrefix(r.Tag, "v")
@@ -272,7 +272,7 @@ func (c *Client) download(ctx context.Context, tag, file string) ([]byte, error)
var errs []error
for _, repo := range c.servers() {
base := strings.TrimSuffix(repo, "/") + "/releases/download/" + tag + "/"
sctx, cancel := context.WithTimeout(ctx, latestTimeout)
sctx, cancel := context.WithTimeout(ctx, serverTimeout)
sums, err := c.get(sctx, base+"checksums.txt", 1<<20)
cancel()
if err != nil {