FreeAllMedia / stimpak

An easy-to-use system for defining, discovering, and re-using code, text, and workflow patterns
http://stimpak.io
MIT License
8 stars 1 forks source link

Add `.cast` feature #28

Closed dcrockwell closed 8 years ago

dcrockwell commented 8 years ago

Allow a function to be provided which modifies each provided answer

stimpak.cast(answer => parseInt(answer));
dcrockwell commented 8 years ago

Should support multiple .cast calls:

stimpak.cast(answer => parseInt(answer));
stimpak.cast(answer => parseSomeOtherThing(answer));
warang580 commented 8 years ago

Note: it applies to answers after the cast() calls, not previous ones.

warang580 commented 8 years ago

I have started something but I have a problem. When I do this :

stimpak
    .prompt(promptUntouched)
    .cast(callbackA)
    .cast(callbackB)
    .prompt(promptCasted);

And try to display the casts that have been added like this

inquirer
    .prompt(unansweredPrompt)
    .then(questionAnswers => {
        console.log("questionAnswers", questionAnswers);
        console.log("casts", this.cast());
        this.answers(questionAnswers);
        done();
    });

I get this :

? Answer 5 please ! 5
questionAnswers { untouched: '5' }
casts [ [Function: callbackA], [Function: callbackB] ]
? Answer 5 please ! 5
questionAnswers { casted: '5' }
casts [ [Function: callbackA], [Function: callbackB] ]

Meaning that I get all callbacks I register via cast(), even for the first prompt which is meant to be untouched. It is because we are listing all prompts that should be used, and not using them instantly.

You can get all the code here : https://github.com/warang580/stimpak/tree/feat/cast

Maybe I should set the cast on each prompt ? It would be more meaningful, because I don't see lots of usecase where you use the same cast for a bunch of prompts like it is done now. It would look like this :

let promptCasted = {
    type: "input",
    name: "casted",
    message: "Answer 5 please !",
    cast: answer => parseInt(answer) + 2,
    default: "5",
};
dcrockwell commented 8 years ago

The issue is that .then(thenFunction) takes a function that has two optional parameters: stimpak, and an optional done callback in case you need the function to be asynchronous.

So, you'll need to refactor your then statement to this:

stimpak
    .then(() => {
        const questionAnswers = stimpak.answers();
        console.log("questionAnswers", questionAnswers);
        console.log("casts", stimpak.cast());
        this.answers(questionAnswers);
    });
dcrockwell commented 8 years ago

Alternately, you can also do it this way, which illustrates the optional arguments:

stimpak
    .then(doSomething);

function doSomething(stimpak) {
    const questionAnswers = stimpak.answers();
    console.log("questionAnswers", questionAnswers);
    console.log("casts", stimpak.cast());
    this.answers(questionAnswers);
}
dcrockwell commented 8 years ago

Make sure that within casting you're adding it as a step in the _.action.steps chain. Let me know if you'd also like to discuss this over Discord, etc.