brianstrauch/cobra-shell

Persistent History

cmprmsd opened this issue · 2 comments

Hey!

I'm trying to get a persistent history working. However, the struggle is real :D
Maybe you have an idea and better understanding of cobra.

The command has the following additional argument

...
PreRun:            WriteHistory,

The following function does write the history line and append it to the file:

func WriteHistory(cmd *cobra.Command, args []string) {
	enabledFlags = nil

	// Open history file
	f, err := os.OpenFile(".fry_history",
		os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Println(err)
	}
	defer f.Close()

	// Parse flags
	cmd.Flags().SortFlags = false
	cmd.Flags().Visit(checkFlags)
	log.Print()
	// Join flags and arguments
	cmdLine := cmd.Parent().Use + " " + cmd.Use + " " + strings.Join(enabledFlags, " ") + " " + strings.Join(args, " ")
	if _, err := f.WriteString(cmdLine + "\n"); err != nil {
		log.Println(err)
	}
}

Reading the history does happen at the start of the program execution:

func init...
hist := prompt.OptionHistory(readHistory())
	myShell := shell.New(rootCmd, keyBinds, codeBinds, number, hist)
func readHistory() []string {
	data, err := os.ReadFile(".fry_history")
	if err != nil {
		log.Println("No history yet. Nothing to parse")
	}
	history := strings.Split(string(data), "\n")
	return history
}

Build the flag strings (this is super weird and I look for a better solution).

func checkFlags(f *pflag.Flag) {
	if f.Value.Type() == "bool" {
		//fmt.Println(f.Value.String())
		enabledFlags = append(enabledFlags, "--"+f.Name)
	} else {
		enabledFlags = append(enabledFlags, "--"+f.Name+" \""+f.Value.String()+"\"")
	}
	fmt.Printf("Flags: %v\n", enabledFlags)
}

This approach works fine for the first execution of a command.
However, the flags do not reset after each command execution. Thus the flags add up when running multiple times in one shell.

image

By any chance. Do you have experience how to parse the flags correctly in order to write them to a file?

Thanks for doing this, can't wait to see the PR! 😄 It looks like the problem might be due to enabledFlags being a global variable? Maybe instead it should be created in the WriteHistory() function and passed directly into the functions that need it? Feel free to push this code to a branch and I can check it out if you need help.

In WriteHistory Ireset this variable each call:
enabledFlags = nil

The flags command seems to be the cause.
Walking the flags seems to also walk the parent commands' flags. On the other side you see that args work fine, as I have direct access to it.