aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2025-10-24 17:18:35 -0700
committerRose Hogenson <rosehogenson@posteo.net>2025-10-24 17:18:35 -0700
commit22300a4ed7e0d36c2fd749df2e70ed3f3bfff1c7 (patch)
treeee18d1b611804ec9ab379b75333191384ffdf78e
parent0cd822566776eddf8e47e61b7279aff4fa5481d7 (diff)
downloadsym-22300a4ed7e0d36c2fd749df2e70ed3f3bfff1c7.tar.zst
Add in-tool documentation
-rw-r--r--dec.go17
-rw-r--r--enc.go15
-rw-r--r--sym.go38
3 files changed, 60 insertions, 10 deletions
diff --git a/dec.go b/dec.go
index e67f4b3..d1404b7 100644
--- a/dec.go
+++ b/dec.go
@@ -22,6 +22,23 @@ type decryptFlags struct {
func (f *decryptFlags) registerFlags(fs *flag.FlagSet) {
fs.StringVar(&f.password, "p", "", "use the specified password; if not provided, dec will prompt for a password")
fs.BoolVar(&f.force, "f", false, "overwrite output files even if they already exist")
+ fs.Usage = func() {
+ fmt.Fprintf(fs.Output(), `usage: %s [OPTION]... [FILE]...
+Decrypt files, or stdin if no files are provided.
+
+`,
+ fs.Name())
+ fs.PrintDefaults()
+ fmt.Fprintf(fs.Output(), `-p is required when reading from stdin.
+
+For example,
+ %s my-encrypted-file.txt.enc
+would decrypt my-encrypted-file.txt.enc and write the result to
+my-encrypted-file.txt. If a filename does not end with .enc, the name
+will be appended with a .dec extension.
+`,
+ fs.Name())
+ }
}
type decryptOptions struct {
diff --git a/enc.go b/enc.go
index 1217606..fc54756 100644
--- a/enc.go
+++ b/enc.go
@@ -23,6 +23,21 @@ func (f *encryptFlags) registerFlags(fs *flag.FlagSet) {
fs.BoolVar(&f.generatePassword, "g", false, "generate a secure password automatically (password will be printed to stderr)")
fs.StringVar(&f.password, "p", "", "use the specified password; if not provided, enc will prompt for a password")
fs.BoolVar(&f.force, "f", false, "overwrite output files even if they already exist")
+ fs.Usage = func() {
+ fmt.Fprintf(fs.Output(), `usage: %s [OPTION]... [FILE]...
+Encrypt files, or stdin if no files are provided.
+
+`,
+ fs.Name())
+ fs.PrintDefaults()
+ fmt.Fprintf(fs.Output(), `
+One of -g or -p must be used when reading from stdin. When encrypting to
+stdout, consider redirecting the result since binary output can mess up
+your terminal. Example:
+ echo test | %s -p 'my super secure password' | base64
+`,
+ fs.Name())
+ }
}
type encryptOptions struct {
diff --git a/sym.go b/sym.go
index e9eef94..c83ecbc 100644
--- a/sym.go
+++ b/sym.go
@@ -13,7 +13,7 @@ type subcommand interface {
}
func whichSubcommand(name string) (subcommand, bool) {
- switch filepath.Base(name) {
+ switch name {
case "enc":
return &encryptOptions{
passwordIn: termReadPassword,
@@ -33,20 +33,38 @@ func whichSubcommand(name string) (subcommand, bool) {
}
func run(args []string) error {
- cmd, ok := whichSubcommand(args[0])
+ name := filepath.Base(args[0])
+ cmd, ok := whichSubcommand(name)
if !ok {
- if len(args) < 2 {
- return fmt.Errorf("missing subcommand")
+ flag.Usage = func() {
+ fmt.Fprintf(os.Stderr, `usage: sym <subcommand> [OPTION]... [FILE]...
+Encrypt or decrypt files using a password.
+
+Subcommands:
+ enc encrypt
+ dec decrypt
+
+Try sym <subcommand> -h for command-specific help.
+
+Pro tip: use "ln sym enc" or "ln sym dec" to create shortcuts for each subcommand.
+`)
+ }
+ flag.CommandLine.Parse(args[1:])
+ args = flag.Args()
+ if len(args) == 0 {
+ return fmt.Errorf("missing subcommand (use sym -h for help)")
}
- cmd, ok = whichSubcommand(args[1])
+ subcommand := filepath.Base(args[0])
+ name = "sym " + subcommand
+ cmd, ok = whichSubcommand(subcommand)
if !ok {
- return fmt.Errorf("invalid subcommand %q", args[1])
+ return fmt.Errorf("invalid subcommand %q", args[0])
}
- args = args[1:]
}
- cmd.registerFlags(flag.CommandLine)
- flag.CommandLine.Parse(args[1:])
- return cmd.run(flag.Args()...)
+ fs := flag.NewFlagSet(name, flag.ExitOnError)
+ cmd.registerFlags(fs)
+ fs.Parse(args[1:])
+ return cmd.run(fs.Args()...)
}
func main() {