feat: include summary of omitted binary data

This commit is contained in:
Lewis Wynne 2026-02-11 13:17:23 +00:00
parent d63c1fd77b
commit 07330be10b
9 changed files with 57 additions and 30 deletions

View file

@ -563,15 +563,15 @@ pda get logo > output.png
<p align="center"></p><!-- spacer --> <p align="center"></p><!-- spacer -->
`list` and `get` will omit binary data whenever it's a human reading it. If it's being piped somewhere or ran outside of a TTY, it'll output the whole data. `list` and `get` will show a summary for binary data on a TTY. If it's being piped somewhere or ran outside of a TTY, it'll output the raw bytes.
`include-binary` to show the full binary data regardless. `--base64`/`-b` to view binary data as base64 on a TTY.
```bash ```bash
pda get logo pda get logo
# (omitted binary data) # (binary: 4.2 KB, image/png)
pda get logo --include-binary pda get logo --base64
# 89504E470D0A1A0A0000000D4948445200000001000000010802000000 # iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADklEQVQI12...
``` ```
<p align="center"></p><!-- spacer --> <p align="center"></p><!-- spacer -->

View file

@ -100,7 +100,7 @@ func get(cmd *cobra.Command, args []string) error {
} }
v := entry.Value v := entry.Value
binary, err := cmd.Flags().GetBool("include-binary") binary, err := cmd.Flags().GetBool("base64")
if err != nil { if err != nil {
return fmt.Errorf("cannot get '%s': %v", args[0], err) return fmt.Errorf("cannot get '%s': %v", args[0], err)
} }
@ -235,12 +235,12 @@ func run(cmd *cobra.Command, args []string) error {
var runFlag bool var runFlag bool
func init() { func init() {
getCmd.Flags().BoolP("include-binary", "b", false, "include binary data in text output") getCmd.Flags().BoolP("base64", "b", false, "view binary data as base64")
getCmd.Flags().BoolVarP(&runFlag, "run", "c", false, "execute the result as a shell command") getCmd.Flags().BoolVarP(&runFlag, "run", "c", false, "execute the result as a shell command")
getCmd.Flags().Bool("no-template", false, "directly output template syntax") getCmd.Flags().Bool("no-template", false, "directly output template syntax")
rootCmd.AddCommand(getCmd) rootCmd.AddCommand(getCmd)
runCmd.Flags().BoolP("include-binary", "b", false, "include binary data in text output") runCmd.Flags().BoolP("base64", "b", false, "view binary data as base64")
runCmd.Flags().Bool("no-template", false, "directly output template syntax") runCmd.Flags().Bool("no-template", false, "directly output template syntax")
rootCmd.AddCommand(runCmd) rootCmd.AddCommand(runCmd)
} }

View file

@ -55,7 +55,7 @@ func (e *formatEnum) Set(v string) error {
func (e *formatEnum) Type() string { return "format" } func (e *formatEnum) Type() string { return "format" }
var ( var (
listBinary bool listBase64 bool
listNoKeys bool listNoKeys bool
listNoValues bool listNoValues bool
listTTL bool listTTL bool
@ -194,7 +194,7 @@ func list(cmd *cobra.Command, args []string) error {
if e.Locked { if e.Locked {
valueStr = "locked (identity file missing)" valueStr = "locked (identity file missing)"
} else { } else {
valueStr = store.FormatBytes(listBinary, e.Value) valueStr = store.FormatBytes(listBase64, e.Value)
} }
} }
row := make(table.Row, 0, len(columns)) row := make(table.Row, 0, len(columns))
@ -315,7 +315,7 @@ func renderTable(tw table.Writer) {
} }
func init() { func init() {
listCmd.Flags().BoolVarP(&listBinary, "binary", "b", false, "include binary data in text output") listCmd.Flags().BoolVarP(&listBase64, "base64", "b", false, "view binary data as base64")
listCmd.Flags().BoolVar(&listNoKeys, "no-keys", false, "suppress the key column") listCmd.Flags().BoolVar(&listNoKeys, "no-keys", false, "suppress the key column")
listCmd.Flags().BoolVar(&listNoValues, "no-values", false, "suppress the value column") listCmd.Flags().BoolVar(&listNoValues, "no-values", false, "suppress the value column")
listCmd.Flags().BoolVarP(&listTTL, "ttl", "t", false, "append a TTL column when entries expire") listCmd.Flags().BoolVarP(&listTTL, "ttl", "t", false, "append a TTL column when entries expire")

View file

@ -23,8 +23,10 @@ THE SOFTWARE.
package cmd package cmd
import ( import (
"encoding/base64"
"fmt" "fmt"
"io" "io"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -67,14 +69,39 @@ func (s *Store) FormatBytes(includeBinary bool, v []byte) string {
return s.formatBytes(includeBinary, v) return s.formatBytes(includeBinary, v)
} }
func (s *Store) formatBytes(includeBinary bool, v []byte) string { func (s *Store) formatBytes(base64Flag bool, v []byte) string {
tty := term.IsTerminal(int(os.Stdout.Fd())) if !utf8.Valid(v) {
if tty && !includeBinary && !utf8.Valid(v) { tty := term.IsTerminal(int(os.Stdout.Fd()))
return "(omitted binary data)" if !tty {
return string(v)
}
if base64Flag {
return base64.StdEncoding.EncodeToString(v)
}
mime := http.DetectContentType(v)
return fmt.Sprintf("(binary: %s, %s)", formatSize(len(v)), mime)
} }
return string(v) return string(v)
} }
func formatSize(n int) string {
const (
kb = 1024
mb = 1024 * kb
gb = 1024 * mb
)
switch {
case n < kb:
return fmt.Sprintf("%d B", n)
case n < mb:
return fmt.Sprintf("%.1f KB", float64(n)/float64(kb))
case n < gb:
return fmt.Sprintf("%.1f MB", float64(n)/float64(mb))
default:
return fmt.Sprintf("%.1f GB", float64(n)/float64(gb))
}
}
func (s *Store) storePath(name string) (string, error) { func (s *Store) storePath(name string) (string, error) {
if name == "" { if name == "" {
name = config.Store.DefaultStoreName name = config.Store.DefaultStoreName

View file

@ -1,7 +1,7 @@
$ pda get foobar --> FAIL $ pda get foobar --> FAIL
$ pda get foobar --include-binary --> FAIL $ pda get foobar --base64 --> FAIL
$ pda get foobar --include-binary --run --> FAIL $ pda get foobar --base64 --run --> FAIL
$ pda get foobar --include-binary --run --secret --> FAIL $ pda get foobar --base64 --run --secret --> FAIL
$ pda get foobar --run --> FAIL $ pda get foobar --run --> FAIL
$ pda get foobar --run --secret --> FAIL $ pda get foobar --run --secret --> FAIL
$ pda get foobar --secret --> FAIL $ pda get foobar --secret --> FAIL

View file

@ -1,3 +1,3 @@
$ pda set a b $ pda set a b
$ pda get a --include-binary $ pda get a --base64
b b

View file

@ -1,4 +1,4 @@
$ fecho cmd echo hello $ fecho cmd echo hello
$ pda set foo < cmd $ pda set foo < cmd
$ pda get foo --include-binary --run $ pda get foo --base64 --run
hello hello

View file

@ -16,10 +16,10 @@ Aliases:
get, g get, g
Flags: Flags:
-h, --help help for get -b, --base64 view binary data as base64
-b, --include-binary include binary data in text output -h, --help help for get
--no-template directly output template syntax --no-template directly output template syntax
-c, --run execute the result as a shell command -c, --run execute the result as a shell command
Get the value of a key. Optionally specify a store. Get the value of a key. Optionally specify a store.
{{ .TEMPLATES }} can be filled by passing TEMPLATE=VALUE as an {{ .TEMPLATES }} can be filled by passing TEMPLATE=VALUE as an
@ -36,7 +36,7 @@ Aliases:
get, g get, g
Flags: Flags:
-h, --help help for get -b, --base64 view binary data as base64
-b, --include-binary include binary data in text output -h, --help help for get
--no-template directly output template syntax --no-template directly output template syntax
-c, --run execute the result as a shell command -c, --run execute the result as a shell command

View file

@ -9,7 +9,7 @@ Aliases:
list, ls list, ls
Flags: Flags:
-b, --binary include binary data in text output -b, --base64 view binary data as base64
-o, --format format output format (table|tsv|csv|markdown|html|ndjson) (default table) -o, --format format output format (table|tsv|csv|markdown|html|ndjson) (default table)
-g, --glob strings Filter keys with glob pattern (repeatable) -g, --glob strings Filter keys with glob pattern (repeatable)
--glob-sep string Characters treated as separators for globbing (default '/-_.@: ') --glob-sep string Characters treated as separators for globbing (default '/-_.@: ')
@ -27,7 +27,7 @@ Aliases:
list, ls list, ls
Flags: Flags:
-b, --binary include binary data in text output -b, --base64 view binary data as base64
-o, --format format output format (table|tsv|csv|markdown|html|ndjson) (default table) -o, --format format output format (table|tsv|csv|markdown|html|ndjson) (default table)
-g, --glob strings Filter keys with glob pattern (repeatable) -g, --glob strings Filter keys with glob pattern (repeatable)
--glob-sep string Characters treated as separators for globbing (default '/-_.@: ') --glob-sep string Characters treated as separators for globbing (default '/-_.@: ')