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

Example for "Questions" #367

Closed
pquerner opened this Issue Feb 15, 2018 · 10 comments

Comments

Projects
None yet
2 participants
@pquerner

pquerner commented Feb 15, 2018

Is it possible to have this example added:

<motd>
Current time <current datetime> (maybe not just print, but self updating)
> Name: <wait for input>
(next)
> Github: <wait for input>
(next)
//> ...
> Information valid?
> <output information from above>
> Confirm (y|n): <wait for input>

Afterwards I want to use that user given information for ie. a HTTP form.

@pquerner

This comment has been minimized.

pquerner commented Feb 15, 2018

Its almost the same code for the comment box on the website.

@jcubic

This comment has been minimized.

Owner

jcubic commented Feb 15, 2018

If you have just 2 questions (user and github) you can do nested push, if you have more it would probably be better to do something like in comments, where you have list of prompts in array and you construct the object:

var init = true;
$('body').terminal(function(command, term) {
    term.echo(new Date(), {
         finalize: function(node) {
             if (init) {
                 // node is jquery object and html have data-index attribute
                 var index = node.data('index'); 
                 setInterval(function() {
                     term.update(index, new Date());
                 }, 1000);
                 init = false;
             }
         }
     });
     term.push(function(username) {
         term.push(function(github) {
             term.pause();
             // do some async processing like ajax call
             setTimeout(function() {
                 term.echo('Some data').resume().push(function(yn) {
                     if (yn.match(/^(y|n)$/i)) {
                         if (yn.match(/y/i)) {
                             // YES
                         } else {
                             // NO
                         }
                         term.pop().pop().pop(); // exit from all pushed interpreters
                         // if you will want to enable some different commands to github
                         // you can do term.push here
                     } else {
                         // invalid, you can ignore, it will ask again 
                         // or you can do term.pop() x 3 if you don't want that
                     }
                 }, {
                     prompt: 'Confirm (y|n): '
                 });
             }, 1000);
         }, {
             prompt: 'github: '
         });
     }, {
         prompt: 'username: '
     });
});

if you want this to be on init you can move the code from inside terminal to onInit or after terminal is created.

@jcubic

This comment has been minimized.

Owner

jcubic commented Feb 15, 2018

If you want to ask multiple questions you can take a look at leash-src.js#L705 there is array of specs and it process all questions and options and create a single object with all the settings.

@pquerner

This comment has been minimized.

pquerner commented Feb 16, 2018

Wow, one can really tell you love your project !
One thing I dont get is, how am I suppose to restart the process if everything is in anonymous functions?
Like the given data is wrong and in the confirmation step the user declines the confirmation.

@jcubic

This comment has been minimized.

Owner

jcubic commented Feb 17, 2018

I came up with something like this:

var init = true;
term.echo(new Date(), {
    finalize: function(node) {
        if (init) {
            var index = node.data('index');
            setInterval(function() {
                term.update(index, new Date());
            }, 1000);
            init = false;
        }
    }
});
var mask = ['root_password', 'password'];
var settings = {};
var questions = [
    {
        name: "root_password",
        text: 'Enter your administration password',
        prompt: "root password: "
    },
    {
        name: "server",
        text: "Type your server name"
    },
    {
        name: "username",
        text: "Your normal username"
    },
    {
        name: "home",
        text: "Home directory"
    },
    {
        name: 'guest',
        text: 'Allow guest sessions (Y)es/(N)o',
        boolean: true
    },
    {
        name: 'sudo',
        text: 'Execute sudo for user accounts (Y)es/(N)o',
        boolean: true
    },
    {
        name: "password"
    }
];
function ask_questions(step) {
    var question = questions[step];
    if (question) {
        if (question.text) {
            term.echo('[[b;#fff;]' + question.text + ']');
        }
        var show_mask = mask.indexOf(question.name) != -1;
        term.push(function(command) {
            if (show_mask) {
                term.set_mask(false);
            }
            if (question.boolean) {
                var value;
                if (command.match(/^Y(es)?/i)) {
                    value = true;
                } else if (command.match(/^N(o)?/i)) {
                    value = false;
                }
                if (typeof value != 'undefined') {
                    settings[question.name] = value;
                    term.pop();
                    ask_questions(step+1);
                }
            } else {
                settings[question.name] = command;
                term.pop();
                ask_questions(step+1);
            }
        }, {
            prompt: question.prompt || question.name + ": "
        });
        // set command and mask need to called after push
        // otherwise they will not work
        if (show_mask) {
            term.set_mask(true);
        }
        if (typeof settings[question.name] != 'undefined') {
            if (typeof settings[question.name] == 'boolean') {
                term.set_command(settings[question.name] ? 'y' : 'n');
            } else {
                term.set_command(settings[question.name]);
            }
        }
    } else {
        finish();
    }
}
function finish() {
    term.echo('Your settings:');
    var str = Object.keys(settings).map(function(key) {
        var value = settings[key];
        if (mask.indexOf(key) != -1) {
           // mask everything except first and last character
            var split = value.match(/^(.)(.*)(.)$/, '*');
            value = split[1] + split[2].replace(/./g, '*') + split[3];
        }
        return '[[b;#fff;]' + key + ']: ' + value;
    }).join('\n');
    term.echo(str);
    term.push(function(command) {
        if (command.match(/^y$/i)) {
            term.echo(JSON.stringify(settings));
            term.pop().history().enable();
        } else if (command.match(/^n$/i)) {
            term.pop();
            ask_questions(0);
        }
    }, {
        prompt: 'Are those correct (y|n): '
    });
}
term.history().disable();
ask_questions(0);
@pquerner

This comment has been minimized.

pquerner commented Feb 20, 2018

Here's my solution

function greetings(term) {
        if (init) {
            term.echo("Type in your application here.\n");
            term.echo(new Date(), {
                finalize: function (node) {
                    if (init) {
                        // node is jquery object and html have data-index attribute
                        var index = node.data('index');
                        setInterval(function () {
                            term.update(index, new Date());
                        }, 1000);
                        init = false;
                    }
                }
            });
        }
    }

var init = true;
    $('#cud_cmd').terminal(function (command, term) {
            (function install(step, finish) {
                var question = questions[step];
                if (question) {
                    if (question.text) {
                        term.echo('[[b;#fff;]' + question.text + ']');
                    }
                    term.push(function (command) {
                        term.pop();
                        settings[question.name] = command;
                        install(step + 1, finish);
                    }, {
                        prompt: question.prompt || question.name + ": "
                    });
                } else {
                    finish();
                }
            })(0, function () {
                term.set_prompt("\n");
                setTimeout(function () {
                    term.echo('Confirming data .......').resume().push(function (yn) {
                        if (yn.match(/^(y|n)$/i)) {
                            if (yn.match(/y/i)) {
                                // YES
                                term.pause();
//Do stuff
                            } else {
                                // NO
                                term.echo("Press enter");
                                term.set_prompt(">");
                                settings = {}; //Reset
                                term.pop();
                            }
                        }
                    }, {
                        prompt: 'Confirm (y|n): '
                    });
                }, 1000);
            });
        },
        {
            greetings: null,
            onInit: function (term) {
                greetings(term);
            },
            height: 600,
            prompt: "> Press enter.",
            enabled: true,
            history: false
        });

settings and questions are build like you proposed, so I removed them from the example.

@pquerner

This comment has been minimized.

pquerner commented Feb 20, 2018

Works fine by me. That could be added to the example page, if you are fine with that.

@jcubic

This comment has been minimized.

Owner

jcubic commented Feb 20, 2018

My code that I've posted in previous comment show settings you have so far and allow to edit them so if I'll put it in examples it will be my updated code.

Did you see it?

@pquerner

This comment has been minimized.

pquerner commented Feb 20, 2018

Yes I saw it, but I havent tested it. I'm sorry.

Sure, you can add your example as it seems its more advanced. Maybe add a link to this issue talk as a backlink?

I'm gonna test your script, but I have not the time right now.

@jcubic

This comment has been minimized.

Owner

jcubic commented Feb 24, 2018

I've added my updated code to the examples.

@jcubic jcubic closed this Feb 24, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment