Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upGet user input #51
Get user input #51
Comments
|
Hi @bitfield , I'm quite new to the Open Source Community (read this is my first try) but I have some experience with Go. So I sketched out a couple of the possibilities here. So here are my thoughts, please feel totally free to change anything or everything. Specification on Reading User input for ScriptInput TypesRead from a user input
Protected
Menu Items
Tell a user to pick from a certain set of options Optional parameters
type Options struct {
Required bool
Default interface{}
OnError func(in interface{}) *Pipe //WithError
}
opts := *&Options{
Required : true,
Default : nil,
}
vStr := p.ReadString("Input your name:", opts) //string
vFlt := p.ReadNumber("Input your age:", opts) //float64
vPwd := p.ReadPassword("Password: ", opts) //string
(p *Pipe) ReadString(message string, opts Options) *Pipe {
//Execute read
//Return New Pipe
}
vArr := p.ReadArray("Input cars you like", opts)
items := []string{"1 - Skip", "2 - Continue", "3 - Quit"}
(p *Pipe) DisplayMenu(items []string, opts Options, f func(chosen string)*Pipe) *Pipe {
//Display List
//Read user input
//Call f with item picked
//Return new pipe created on f
}) |
|
Hey @manthantunes, great suggestions, thank you! This looks like a good starting point. Let's see if we can put together an example program which uses the input feature for some real-world application. (This is often a great way to start designing something: use it!) For example, a software installer which needs to get the installation directory from the user. |
|
Hi @bitfield, Thinking about use cases before modeling is a very good idea, thank you. So, I sketched out your example on an installation script, here it is: p := script.Echo("Installation Script for ABCD")
welcome, err := p.String()
fmt.Println(welcome)
dir, _ := p.GetPrompter().Input("Please provide a directory for instalation: ", script.PrompOpts{Default: "/usr/share"}).String()
//Act based on the dir variable
str, _ := script.Exec(fmt.Sprintf("touch %s/install.sh", dir)).String()When trying to sketch it through the script api, it came to me that things could get confusing if we implement all user input methods under the Pipe struct. I researched a bit and took the Prompter API as reference for the implementation. Now instead of having all methods implemented under Pipe, a single method calls a prompter pointer which then implements all different kinds of prompts. |
|
How about something like this: script.Echo("Installation Script for ABCD").Stdout()
script.PromptDefault("Install location", "/usr/local/abcd").ExecForEach("touch {{.}}/install.sh").Stdout() |
|
Makes sense to have the implementation under the package itself, since we can start a pipe and then chain from the user input. So, on the same example, say the script verifies if its binaries have already been installed and gives you a couple of options like: script.Echo("Installation Script for ABCD \n").Stdout()
dir, _ := script.PromptDefault("Install location ", "/usr/local/abcd").String()
choice, _ := script.IfExists(dir+"/install.sh").
PromptMenu("It seems that ABCD is already installed, choose an action: ",
[]string{"0 - Quit", "1 - Repair", "2 - Uninstall"}).String()
//Take actions based on choice.This requires the PromptMenu call from *Pipe though. |
|
It's interesting how, once they've settled into a coherent design concept, libraries more or less design themselves. Here, for example, there's really nothing in It's not clear that something like PromptMenu fits that pattern, because we almost certainly need to take different code paths depending on the user's choice. I can't think of a way to fit that into the |
|
Interesting point of view. A script usually follows a straight flow to its single objective and falls at errors if anything unexpected happens. A PromptMenu is more likely to be seen at a CLI, for example, which might not be the scope of the package. By making a short research, I see there are many other libraries for Menu Prompting. Although I think that not having it limits the scope of the package, a developer that needs it can easily go get specific packages for this. So far we have a signature for: script.PromptDefault("Install location", "/usr/local/abcd")What do you think of the PromptPassword ? (It's basically PromptDefault without Echo) Where a script might have a predefined password for installation or even ask for a password for later use some functionality |
Exactly. Sometimes the hardest design decision is when to leave something out. We might try writing a short install script using one of those menu libraries, to see how it plays with I had imagined script.Prompt("Install location", "/usr/local/abcd").ExecForEach("touch {{.}}/install.sh").Stdout() |
|
It sure is! Yes, I think the basic prompt should always have a default value so it's better named as just Prompt. script.Prompt("Install location", "/usr/local/abcd").ExecForEach("touch {{.}}/install.sh").Stdout()For now, I believe the Thinking of ways we can integrate, I found this really cool interactive prompt package Which I integrated by ...
err := script.IfExists(dir + "/install.sh").Error()
if err == nil {
//Already exists
prompt := promptui.....
} |
|
That looks good! Maybe you'd like to put together a PR with a new |

Formed in 2009, the Archive Team (not to be confused with the archive.org Archive-It Team) is a rogue archivist collective dedicated to saving copies of rapidly dying or deleted websites for the sake of history and digital heritage. The group is 100% composed of volunteers and interested parties, and has expanded into a large amount of related projects for saving online and digital history.


It's common when writing scripts that install or configure things to need input from the user (at a minimum, something like 'Press Enter to continue'; at a maximum, to be able to prompt the user for input, with an optional default value, and return that value).
Let's use this issue to design how that would look, and I invite suggestions!