Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passing arguments #9

Open
Wulfheart opened this issue Apr 30, 2020 · 16 comments
Open

Passing arguments #9

Wulfheart opened this issue Apr 30, 2020 · 16 comments

Comments

@Wulfheart
Copy link

Is it possible to pass arguments to the cli?
E.g. I have a command like cli create test and I'd like the create cmd know that it has to create something named e.g. test.

@deranjer
Copy link
Contributor

I'm in the same boat, not sure how to parse the supplied args.

@leaanthony
Copy link
Owner

leaanthony commented May 16, 2020

Clir supports subcommands and named arguments. The docs have all the examples as well as the examples directory.

In your example, you'd create a subcommand called create and pass in the name using a StringFlag, say -n.
EG:

package main

import (
	"github.com/leaanthony/clir"
)

func main() {

	// Create new cli
	cli := clir.NewCli("mycli", "My CLI app", "v0.0.1")

	// Add a create subcommand
	create := cli.NewSubCommand("create", "Create a thing")
        thingToCreate := "my default thing"
        create.StringFlag("n", "Name of thing to create", &thingToCreate)
	create.Action(func() error {
		println("I am creating a thing called: " + thingToCreate)
		return nil
	})

	// Run!
	cli.Run()

}

Now you can mycli create -n test

@deranjer
Copy link
Contributor

Yes, we were hoping to do mycli create test not mycli create -n test.
Or in my example, was hoping to do mycli add -all or mycli add <file> (kind of like git add <file> and git add --all)

@Wulfheart
Copy link
Author

This would be 🔥.

@deranjer
Copy link
Contributor

deranjer commented May 16, 2020

Alright, after some testing have realized we can directly call os.Args[], so as long as we know the position (which could be a major issue), you can fulfill the requirements. If you don't know the position, then you will need to do some string searching and cutting.

cli := clir.NewCli("gvcc", "Version control client for GVC", version)
addCmd := cli.NewSubCommand("add", "adds file(s)/folder(s) (recursively for folder) to repo")
//File/Folder/Wildcard adding
addCmd.Action(func() error {
		fmt.Println("File/Folder to add", os.Args[2])
		return nil

})
//Add all files recursively to repo
addall := addCmd.NewSubCommand("all", "add all of the file(s)/folders(s) recursively to repo")
addall.Action(func() error {
	fmt.Println("Adding ALL files recursively")
	return nil
})
err := cli.Run()
	if err != nil {
		log.Fatal(err)
	}
}
go run client.go add file.txt
File/Folder to add file.txt
go run client.go add all
Adding ALL files recursively

@deranjer
Copy link
Contributor

So maybe something to add to the library that stores all args supplied after the subcommand? Although all of my actions are functions in another library, so either global or you could implement the changes by amichael7 and their "CustomAction" implementation to pass them, or some other method.

@leaanthony
Copy link
Owner

I'll implement something better than accessing os.Args today 👍

@leaanthony
Copy link
Owner

I've pushed an update that addresses this. There's an example in examples/otherags. I'll update the docs today. Please let me know if this addresses your needs.

@leaanthony
Copy link
Owner

Now tagged as v1.0.3.

@deranjer
Copy link
Contributor

That was fast! Unfortunately it doesn't work for my use case. Consider this example:

func main() {

   // Create new cli
   cli := clir.NewCli("Other Args", "A basic example", "v0.0.1")

   // Set long description
   cli.LongDescription("This app shows positional arguments")

   name := cli.NewSubCommand("name", "Shows your name!")
   name.Action(func() error {
   	fmt.Printf("The remaining arguments were: %+v\n", cli.OtherArgs())
   	fmt.Println("Show args manually: ", os.Args[1:])
   	fmt.Println("Show arg we are interested in: ", os.Args[2])
   	return nil
   })
   // Run!
   cli.Run()
}

And the output:

>go run test.go name deranjer
The remaining arguments were: []
Show args manually:  [name deranjer]
Show arg we are interested in:  deranjer

@leaanthony
Copy link
Owner

Ah, subcommands.... yes.... I can sort that out.

@deranjer
Copy link
Contributor

deranjer commented May 17, 2020

Opened a pull request in case you haven't done it yet. Was curious if you were planning on adding "required" tags or not to the library? That is about the only other thing I need (well can do this other ways, but would be nice to have) at this time.

@deranjer
Copy link
Contributor

Hmm, looking at it you wrap the flagset from the main library... adding a required tag wouldn't be simple, I'm no expert but you might have to abandon the flagset method unless somehow you had a metastructure to add data onto flagset.. well I might mess around with it a little bit.

@leaanthony
Copy link
Owner

To be honest I didn't want to overly complicate the library. It's just meant to be for quick'n'easy clis. Adding required might be tricky. I'm happy to consider any PRs 👍

@Wulfheart - does this sort your problem out now?

@Wulfheart
Copy link
Author

Wulfheart commented May 17, 2020

@leaanthony Somehow yes.

Even though something like a required number of arguments would really be helpful. 😉
Maybe with some helpers. Let's take the git example.

git add <file>

In this case I'd like the cli to define required arguments (in this case file) and reference them in the help. As far as I know no cli-library in go can do this yet. This would be an advantage for clir.
If you are willing to merge such a PR I will provide one (maybe 😂) today.

@deranjer
Copy link
Contributor

@Wulfheart IDK, after some experimentation I think @leaanthony might be right that required is best handled elsewhere. If you look at your case something like this would be simple and effective:

if len(nameCommand.OtherArgs()) == 0 {
	nameCommand.PrintHelp()
	fmt.Println("ERROR: No file/folder name supplied!")
	os.Exit(1)
}

This kind of thing requires the flags to be first, but I think that is good practice anyway. I do have required working on my current git branch, but not sure how much I like it.

However @leaanthony I do have a pull request for shorcuts which I do think are very useful and nice. Does require a lot of changes though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants