summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Carr <[email protected]>2025-10-25 01:24:29 -0500
committerJeff Carr <[email protected]>2025-10-25 01:24:29 -0500
commit27e0ddeaf127f561ca7fd5a8083ab52eba6ca2fb (patch)
tree432ed35a59d85782153993ccc4c8932171eac65a
parentf7a1de79b1c115bddbf3d323a6fd7786d878efd9 (diff)
first stab at making an argv binary
-rw-r--r--argv.Print.go10
-rw-r--r--argv.SendStrings.go8
-rw-r--r--argv.parseOsArgs.go2
-rw-r--r--argv.proto53
-rw-r--r--gui.go1
-rw-r--r--makeAutocompleteFiles.bash.go1
-rw-r--r--structs.go3
-rw-r--r--theMagicOfAutocomplete.go68
-rw-r--r--verifyApplication.go10
9 files changed, 93 insertions, 63 deletions
diff --git a/argv.Print.go b/argv.Print.go
index 7cfbcff..ceab8a6 100644
--- a/argv.Print.go
+++ b/argv.Print.go
@@ -67,7 +67,17 @@ func (pb *Argv) PrintStderr() {
}
}
+func (pb *Argv) PrintStdout() {
+ fmt.Fprintf(os.Stdout, "%s\n", pb.Stdout)
+}
+
func (pb *Argv) PrintStderrExit() {
pb.PrintStderr()
+ pb.PrintStdout()
+ os.Exit(0)
+}
+
+func (pb *Argv) PrintStdoutExit() {
+ pb.PrintStdout()
os.Exit(0)
}
diff --git a/argv.SendStrings.go b/argv.SendStrings.go
index b523120..c890608 100644
--- a/argv.SendStrings.go
+++ b/argv.SendStrings.go
@@ -50,14 +50,14 @@ func (pb *Argv) SubCommand(cmd ...string) {
}
partial := strings.Trim(pb.Partial, "'")
if me.debug {
- // last working line: me.writeHelpForAutocomplete(os.Stderr, os.Stdout, partial, cmd...)
+ // last working line: me.writeHelpForAutocomplete(Stderr, Stdout, partial, cmd...)
me.writeHelpForAutocompleteDebugFunc(partial, cmd...)
- // me.pp.GetUsageForSubcommand(os.Stdout, os.Stderr, partial, cmd)
- // me.pp.GetUsageForSubcommand(os.Stdout, nil, partial, cmd)
+ // me.pp.GetUsageForSubcommand(Stdout, Stderr, partial, cmd)
+ // me.pp.GetUsageForSubcommand(Stdout, nil, partial, cmd)
} else {
// last working: f, _ := os.OpenFile("/tmp/outlook", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
- // last working: me.writeHelpForAutocomplete(f, os.Stdout, partial, cmd...)
+ // last working: me.writeHelpForAutocomplete(f, Stdout, partial, cmd...)
me.writeHelpForAutocompleteFunc(partial, cmd...)
}
os.Exit(0)
diff --git a/argv.parseOsArgs.go b/argv.parseOsArgs.go
index bf73744..89750c9 100644
--- a/argv.parseOsArgs.go
+++ b/argv.parseOsArgs.go
@@ -47,7 +47,7 @@ func (pb *Argv) getSubSubCmd() string {
func (pb *Argv) parseOsArgs() {
// this shouldn't really happen. OS/POSIX error?
if len(os.Args) == 0 {
- // fmt.Fprintf(os.Stderr, "what OS is this?\n")
+ // fmt.Fprintf(Stderr, "what OS is this?\n")
return
}
diff --git a/argv.proto b/argv.proto
index 23054f6..9a38585 100644
--- a/argv.proto
+++ b/argv.proto
@@ -8,28 +8,41 @@ import "google/protobuf/timestamp.proto"; // Import the well-known type for Time
import "google/protobuf/duration.proto"; // for duration
message App {
- string APPNAME = 1;
- string VERSION = 2;
- string BUILDTIME = 3;
+ string APPNAME = 1;
+ string VERSION = 2;
+ string BUILDTIME = 3;
}
-message Argv { // `autogenpb:marshal` `autogenpb:sort` `autogenpb:nomutex`
- google.protobuf.Timestamp ctime = 1; // when the user tried this autocomplete
- google.protobuf.Duration duration = 2; // time since the last autocomplete
- App appInfo = 3;
- repeated string args = 4; // a copy of os.Args
- repeated string real = 5; // what will really be sent to the application
- string subcmd = 6; // the subcommand being processed. For "git pull <tab>", cmd would be "pull"
- string partial = 7; // if the user has only partially inputed something
- repeated string goargs = 8; // what to send to alex flint's go-args for help
- bool fast = 9; // is autocomplete running quickly?
- string stdout = 10; // all output is loaded here before being sent to the shell
- string stderr = 11; // all output is loaded here before being sent to the shell
+message StructEntry {
+ string structName = 2; // 'Force', 'Verbose', 'SortCmd'
+ string structType = 3; // 'string', 'int', '[]string', '*FindCmd'
+ string defaultVal = 4; // "true"
+ string helpText = 5; // "This will help you"
+ string matchText = 6; // "--help-me
}
-message Argvs { // `autogenpb:marshal` `autogenpb:sort` `autogenpb:nomutex`
- string uuid = 1; // `autogenpb:uuid:1e6e765c-0c77-4c81-a622-0d819bfcce9a`
- string version = 2; // `autogenpb:version:v0.0.3`
- repeated Argv argvs = 3;
- string filename = 4; // `autogenpb:save` -- this enables autogenerated pb.Load() and pb.Save()
+message ArgTree {
+ repeated StructEntry Structs = 1; // a tree of the argv structs in argv.go
+ string mainArgvName = 2; // name to use in main.go
+}
+
+message Argv { // `autogenpb:marshal` `autogenpb:sort` `autogenpb:nomutex`
+ google.protobuf.Timestamp ctime = 1; // when the user tried this autocomplete
+ google.protobuf.Duration duration = 2; // time since the last autocomplete
+ App appInfo = 3;
+ repeated string args = 4; // a copy of os.Args
+ repeated string real = 5; // what will really be sent to the application
+ string subcmd = 6; // the subcommand being processed. For "git pull <tab>", cmd would be "pull"
+ string partial = 7; // if the user has only partially inputed something
+ repeated string goargs = 8; // what to send to alex flint's go-args for help
+ bool fast = 9; // is autocomplete running quickly?
+ string stdout = 10; // all output is loaded here before being sent to the shell
+ string stderr = 11; // all output is loaded here before being sent to the shell
+}
+
+message Argvs { // `autogenpb:marshal` `autogenpb:sort` `autogenpb:nomutex`
+ string uuid = 1; // `autogenpb:uuid:1e6e765c-0c77-4c81-a622-0d819bfcce9a`
+ string version = 2; // `autogenpb:version:v0.0.3`
+ repeated Argv argvs = 3;
+ string filename = 4; // `autogenpb:save` -- this enables autogenerated pb.Load() and pb.Save()
}
diff --git a/gui.go b/gui.go
index 242efa9..8b9ddae 100644
--- a/gui.go
+++ b/gui.go
@@ -36,5 +36,4 @@ func workInProgress() {
fmt.Println(cobol.Time(s) + ": go.wit.com/apps/forge/argv.go")
fmt.Println(cobol.Time(s) + ": go.wit.com/apps/forge/main.go")
fmt.Println(cobol.Time(s) + ":")
- // panic("deprecated")
}
diff --git a/makeAutocompleteFiles.bash.go b/makeAutocompleteFiles.bash.go
index f0cc953..259d795 100644
--- a/makeAutocompleteFiles.bash.go
+++ b/makeAutocompleteFiles.bash.go
@@ -23,7 +23,6 @@ func MakeBashCompleteFiles(argname string) {
filename := filepath.Join(homeDir, ".local/share/bash-completion/completions", argname)
if config.Exists(filename) {
fmt.Fprintln(os.Stderr, "# file already exists", filename)
- // os.Exit(0)
}
basedir, _ := filepath.Split(filename)
if !config.IsDir(basedir) {
diff --git a/structs.go b/structs.go
index 53a2c84..c406e8f 100644
--- a/structs.go
+++ b/structs.go
@@ -6,6 +6,7 @@ var me *AutoArgs
// this is a work in progress
type AutoArgs struct {
pb *Argv // the protobuf for the current process
+ all *Argvs // the protobuf for the current process
last *Argv // the pb from the last time the user tried autocomplete
id int // should be unique
Argv func([]string) // the function for shell autocomplete
@@ -22,7 +23,7 @@ type AutoArgs struct {
buildtime func() (string, string) // some examples
autoFunc func(*Argv) // also a function for autocomplete
guiFunc func() error // enables Gui functions
- err error // store any errors from argv
+ Err error // store any errors from argv
debug bool // is dubugging on?
setupAuto bool // do shell autocomplete setup
isAuto bool // try to do autocomplete
diff --git a/theMagicOfAutocomplete.go b/theMagicOfAutocomplete.go
index b48d1b9..5b5370b 100644
--- a/theMagicOfAutocomplete.go
+++ b/theMagicOfAutocomplete.go
@@ -17,8 +17,11 @@ import (
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
)
+// This function behaves oddly. It works in several different ways. It can:
+// - Initialize a protobuf and returns it to the application
+// - Help a user generate shell completion support & os.Exit
+// - figures out what to print to Stdout & Stderr and then does os.Exit()
func Autocomplete(dest any) *Argv {
- var err error
me = new(AutoArgs) // todo: redo this
me.pb = new(Argv)
@@ -27,7 +30,7 @@ func Autocomplete(dest any) *Argv {
me.pb.Ctime = timestamppb.New(now)
// makes sure the application has the
- // needed functions defined, otherwise panics
+ // needed functions defined, otherwise dies
verifyApplication(dest)
// gets APPNAME, BUILDTIME and VERSION from the application
@@ -40,10 +43,10 @@ func Autocomplete(dest any) *Argv {
env.Init(me.pb.AppInfo.APPNAME, me.pb.AppInfo.VERSION, cobol.Time(me.pb.AppInfo.BUILDTIME), me.pb.Real, GoodExit, BadExit)
// loads the argv autocomplete history file
- all := NewArgvs()
+ me.all = NewArgvs()
fullname := config.MakeCacheFilename("argv", me.pb.AppInfo.APPNAME)
- err = config.LoadFromFilename(all, fullname)
- if err != nil {
+ me.Err = config.LoadFromFilename(me.all, fullname)
+ if me.Err != nil {
// there is no history.
// todo: initialize the history file
// todo: check if this is automatically done already
@@ -76,25 +79,31 @@ func Autocomplete(dest any) *Argv {
}
}
- // not autocompleting. return go-arg & the application
- if !me.isAuto {
- // save the pb & history
- all.Clone(me.pb)
- errors.Join(err, all.Save())
-
- // me.pp = arg.MustParse(dest)
- me.err = me.mustParseFunc()
- return me.pb
+ if me.isAuto {
+ // do autocomplete and exit
+ doAutocomplete()
+ os.Exit(0)
}
- // EVERYTHING PAST HERE IS FOR AUTOCOMPLETE
- // everything sent to STDOUT and STDERR matters past this point
+ // not autocompleting. return to the application
+ // save the pb & history
+ me.all.Clone(me.pb)
+ errors.Join(me.Err, me.all.Save())
+
+ // me.pp = arg.MustParse(dest)
+ me.Err = errors.Join(me.Err, me.mustParseFunc())
+ return me.pb
+}
+// prints what is needed to Stdout & Stderr, then exits
+// EVERYTHING PAST HERE IS FOR AUTOCOMPLETE
+// everything sent to STDOUT and STDERR matters past this point
+func doAutocomplete() {
// set the duration since the last auto complete
// find the last entry. this is dumb way to do it
me.last = new(Argv)
me.last.Ctime = timestamppb.New(time.Now().Add(-time.Second))
- for found := range all.IterAll() {
+ for found := range me.all.IterAll() {
me.last = found
}
dur := time.Since(me.last.Ctime.AsTime())
@@ -103,15 +112,15 @@ func Autocomplete(dest any) *Argv {
if me.debug {
// dump debug info
me.pb.PrintDebug()
- all.PrintHistory()
+ me.all.PrintHistory()
}
// roll the autocomplete file
- if all.Len() > 15 {
- me.pb.Debugf("DEBUG: trim() history is over 100 len=%d vs new=%d", all.Len(), all.Len()-90)
- all.Argvs = all.Argvs[all.Len()-10:]
- // newall.Autos = all.Autos[0:10]
- // for _, found := range all.Autos[0:10] {
+ if me.all.Len() > 15 {
+ me.pb.Debugf("DEBUG: trim() history is over 100 len=%d vs new=%d", me.all.Len(), me.all.Len()-90)
+ me.all.Argvs = me.all.Argvs[me.all.Len()-10:]
+ // newall.Autos = me.all.Autos[0:10]
+ // for _, found := range me.all.Autos[0:10] {
// newall.Append(found)
// }
}
@@ -180,15 +189,15 @@ func Autocomplete(dest any) *Argv {
if len(flags) == 0 {
// error is normal if there are no command line args
} else {
- if err != nil {
+ if me.Err != nil {
// users has command line arguments that won't parse with go-args
- me.pb.Debugf("DEBUG: Parse error: %v flags%v", err, flags)
+ me.pb.Debugf("DEBUG: Parse error: %v flags%v", me.Err, flags)
}
}
// save now. this is near the end probably
- all.Clone(me.pb)
- errors.Join(err, all.Save())
+ me.all.Clone(me.pb)
+ errors.Join(me.Err, me.all.Save())
if me.pb.Fast {
if me.last.Fast {
@@ -197,10 +206,10 @@ func Autocomplete(dest any) *Argv {
} else {
// this means the user is pressing tab. no longer doing stderr
if me.pb.GetCmd() == "" {
- // me.pp.WriteHelp(os.Stderr)
+ // me.pp.WriteHelp(Stderr)
me.writeHelpFunc()
} else {
- // me.pp.WriteHelpForSubcommand(os.Stderr, me.pb.Cmd)
+ // me.pp.WriteHelpForSubcommand(Stderr, me.pb.Cmd)
me.writeHelpForSubcommandFunc(me.pb.GetCmd())
}
}
@@ -218,5 +227,4 @@ func Autocomplete(dest any) *Argv {
// if not, send "reset bash newline\n" to cause bash to redraw PS1 for the user
}
os.Exit(0)
- return nil
}
diff --git a/verifyApplication.go b/verifyApplication.go
index 9eaed32..7c79cd9 100644
--- a/verifyApplication.go
+++ b/verifyApplication.go
@@ -164,7 +164,7 @@ func helpWriteHelpForSubcommand() {
fmt.Println("")
fmt.Println("// add this funcgion: this will print the help")
fmt.Println("func (args) WriteHelpForSubcommand() error {")
- fmt.Println(" me.pp.WriteHelpForSubcommand(os.Stderr, me.argv.Cmd)")
+ fmt.Println(" me.pp.WriteHelpForSubcommand(Stderr, me.argv.Cmd)")
fmt.Println(" return nil")
fmt.Println("}")
fmt.Println("")
@@ -176,7 +176,7 @@ func helpWriteHelp() {
fmt.Println("")
fmt.Println("// add this funcgion: this will print the help")
fmt.Println("func (args) WriteHelp() error {")
- fmt.Println(" me.pp.WriteHelp(os.Stderr)")
+ fmt.Println(" me.pp.WriteHelp(Stderr)")
fmt.Println(" return nil")
fmt.Println("}")
fmt.Println("")
@@ -188,7 +188,7 @@ func helpWriteHelpForAutocompleteDebug() {
fmt.Println("")
fmt.Println("// this will print the help for the subcmd")
fmt.Println("func (args) WriteHelpForAutocompleteDebug(part string, subcmd ...string) error {")
- fmt.Println(" return argvpp.WriteHelpForAutocomplete(f, os.Stdout, part, subcmd...)")
+ fmt.Println(" return argvpp.WriteHelpForAutocomplete(f, Stdout, part, subcmd...)")
fmt.Println("}")
fmt.Println("")
fmt.Println("cp ~/go/src/go.wit.com/apps/forge/argv.template.go .")
@@ -197,12 +197,12 @@ func helpWriteHelpForAutocompleteDebug() {
}
// func (p *Parser) WriteHelpForAutocomplete(stderr io.Writer, stdout io.Writer, partial string, subcommand ...string) error {
-// me.pp.WriteHelpForAutocomplete(os.Stderr, os.Stdout, partial, cmd...)
+// me.pp.WriteHelpForAutocomplete(Stderr, Stdout, partial, cmd...)
func helpWriteHelpForAutocomplete() {
fmt.Println("")
fmt.Println("// this will print the help for the subcmd")
fmt.Println("func (args) WriteHelpForAutocomplete(part string, subcmd ...string) error {")
- fmt.Println(" return argvpp.WriteHelpForAutocomplete(os.Stderr, os.Stdout, part, subcmd...)")
+ fmt.Println(" return argvpp.WriteHelpForAutocomplete(Stderr, Stdout, part, subcmd...)")
fmt.Println("}")
fmt.Println("")
fmt.Println("Just copy the argv.template.go file from forge")