summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-29 16:02:24 +0300
committerPaul Buetow <paul@buetow.org>2026-04-29 16:02:24 +0300
commit751c82f337f9dc4756846cf7c547d31668d6587d (patch)
treef607ea6bfad096d8e0085ca115d69aab52cccf06
parent3c1523cc7794da059912c70fb82a708047bc6d72 (diff)
Short-circuit `foostore fish` to skip backend initHEADv0.8.1master
The fish subcommand prints a purely static shell-integration script and needs no backend, cipher, store, git, or shell. Previously cli.New ran in main() before dispatch, triggering the KeePass Argon2 KDF and adding ~1.8s to every interactive fish shell startup that sources the script. Export FishIntegrationScript and dispatch `fish` directly from main() before constructing the CLI. Local timing: `foostore fish` drops from ~1.834s to ~0.003s. Bump version to v0.8.1. Amp-Thread-ID: https://ampcode.com/threads/T-019dd950-11ef-77aa-bb92-810f22601023 Co-authored-by: Amp <amp@ampcode.com>
-rw-r--r--cmd/foostore/main.go14
-rw-r--r--internal/cli/cli_fish.go12
-rw-r--r--internal/version/version.go2
3 files changed, 24 insertions, 4 deletions
diff --git a/cmd/foostore/main.go b/cmd/foostore/main.go
index 82283da..1e7a184 100644
--- a/cmd/foostore/main.go
+++ b/cmd/foostore/main.go
@@ -28,6 +28,20 @@ func main() {
os.Exit(0)
}
+ // Short-circuit the "fish" subcommand: it emits a purely static shell
+ // integration script and needs no backend, cipher, store, git, or shell
+ // initialisation. Skipping cli.New avoids the KeePass Argon2 KDF cost
+ // (~1.8s), which makes every interactive fish shell startup that sources
+ // `foostore fish | source` correspondingly faster.
+ if len(args) == 1 && args[0] == "fish" {
+ binaryPath, err := os.Executable()
+ if err != nil {
+ binaryPath = "foostore"
+ }
+ fmt.Print(cli.FishIntegrationScript(binaryPath))
+ os.Exit(0)
+ }
+
// Cancel the context on SIGINT or SIGTERM so that long-running operations
// (fzf, external editors) terminate gracefully rather than being killed hard.
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
diff --git a/internal/cli/cli_fish.go b/internal/cli/cli_fish.go
index b2d3616..0590345 100644
--- a/internal/cli/cli_fish.go
+++ b/internal/cli/cli_fish.go
@@ -28,14 +28,14 @@ func (c *CLI) cmdFish(stdout io.Writer) int {
if err != nil {
binaryPath = "foostore"
}
- script := fishIntegrationScript(binaryPath)
+ script := FishIntegrationScript(binaryPath)
if _, err := io.WriteString(stdout, script); err != nil {
return 1
}
return 0
}
-// fishIntegrationScript returns the complete fish shell integration script for
+// FishIntegrationScript returns the complete fish shell integration script for
// the given binary path. The script combines the foostore completion rules and
// the ge wrapper function so users need only source a single output:
//
@@ -44,7 +44,13 @@ func (c *CLI) cmdFish(stdout io.Writer) int {
// The binary name is extracted from binaryPath (basename without path) and used
// wherever "foostore" appears in complete directives, making the script
// correct even when the binary is renamed.
-func fishIntegrationScript(binaryPath string) string {
+//
+// This function is exported so cmd/foostore/main.go can short-circuit the
+// "fish" subcommand before constructing a CLI — the script is purely static
+// and needs no backend, cipher, store, git, or shell initialisation. Avoiding
+// that init shaves ~1.8s (KeePass Argon2 KDF) off every interactive fish
+// shell startup that sources `foostore fish`.
+func FishIntegrationScript(binaryPath string) string {
bin := filepath.Base(binaryPath)
var b strings.Builder
diff --git a/internal/version/version.go b/internal/version/version.go
index d019841..0a0a258 100644
--- a/internal/version/version.go
+++ b/internal/version/version.go
@@ -2,4 +2,4 @@
package version
// Version is the current release version of foostore.
-const Version = "v0.7.0"
+const Version = "v0.8.1"