Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
terkelg committed Feb 24, 2018
0 parents commit 69b3761
Show file tree
Hide file tree
Showing 35 changed files with 1,909 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.DS_Store
node_modules
81 changes: 81 additions & 0 deletions example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
'use strict';

const { prompt } = require('./lib');

(async function(){
const questions = [
{
type: 'text',
name: 'twitter',
message: `What's your twitter handle?`
},
{
type: 'password',
name: 'secret',
message: 'Tell me a secret'
},
{
type: 'invisible',
name: 'password',
message: `Enter password`
},
{
type: 'number',
name: 'age',
message: 'How old are you?'
},
{
type: 'confirm',
name: 'confirmed',
message: 'Can you confirm?'
},
{
type: 'list',
name: 'keywords',
message: 'Enter keywords'
},
{
type: 'toggle',
name: 'confirmtoggle',
message: 'Can you confirm?',
active: 'yes',
inactive: 'no'
},
{
type: 'select',
name: 'color',
message: 'Pick a color',
choices: [
{ title: 'Red', value: '#ff0000' },
{ title: 'Green', value: '#00ff00' },
{ title: 'Blue', value: '#0000ff' }
]
},
{
type: 'multiselect',
name: 'multicolor',
message: 'Pick colors',
choices: [
{ title: 'Red', value: '#ff0000' },
{ title: 'Green', value: '#00ff00' },
{ title: 'Blue', value: '#0000ff' }
]
},
{
type: 'autocomplete',
name: 'actor',
message: 'Pick your favorite color',
choices: [
{ title: 'Brad Pitt' },
{ title: 'George Clooney', value: 'silver-fox' },
{ title: 'Ana de Armas' },
{ title: 'Arnold' },
{ title: 'Felicity Jones' },
]
}
];

const answers = await prompt(questions);
console.log(answers);

})();
144 changes: 144 additions & 0 deletions lib/elements/autocomplete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
'use strict';

const util = require('../util');
const color = require('clorox');
const Prompt = require('./prompt');
const { cursor } = require('sisteransi');

// Get value, with fallback to title
const getVal = (arr, i) => arr[i].value || arr[i].title || arr[i];

/**
* A command line prompt with autocompletion
*/
class AutocompletePrompt extends Prompt {
constructor({ message, suggest, choices, cursor = 0, limit = 10, style = 'default' }) {
super();
this.msg = message;
this.suggest = suggest;
this.choices = choices;
this.suggestions = [];
this.input = '';
this.limit = limit;
this.cursor = cursor;
this.transform = util.style.render(style);
this.render = this.render.bind(this);
this.complete = this.complete.bind(this);
this.clear = util.clear('');
this.complete(this.render);
this.render(true);
}

moveCursor(i) {
this.cursor = i;
if (this.suggestions.length > 0) this.value = getVal(this.suggestions, i);
else this.value = null;
this.fire();
}

async complete(cb) {
const p = (this.completing = this.suggest(this.input, this.choices));
const suggestions = await p;

if (this.completing !== p) return;

this.suggestions = suggestions.slice(0, this.limit).map(s => util.strip(s));
this.completing = false;

const l = Math.max(suggestions.length - 1, 0);
this.moveCursor(Math.min(l, this.cursor));

cb && cb();
}

reset() {
this.input = '';
this.complete(() => {
this.moveCursor(0);
this.render();
});
this.render();
}

abort() {
this.done = this.aborted = true;
this.fire();
this.render();
this.out.write('\n');
this.close();
}

submit() {
this.done = true;
this.aborted = false;
this.fire();
this.render();
this.out.write('\n');
this.close();
}

_(c, key) {
this.input += c;
this.complete(this.render);
this.render();
}

delete() {
if (this.input.length === 0) return this.bell();
this.input = this.input.slice(0, -1);
this.complete(this.render);
this.render();
}

first() {
this.moveCursor(0);
this.render();
}

last() {
this.moveCursor(this.suggestions.length - 1);
this.render();
}

up() {
if (this.cursor <= 0) return this.bell();
this.moveCursor(this.cursor - 1);
this.render();
}

down() {
if (this.cursor >= this.suggestions.length - 1) return this.bell();
this.moveCursor(this.cursor + 1);
this.render();
}

next() {
this.moveCursor((this.cursor + 1) % this.suggestions.length);
this.render();
}

render(first) {
if (first) this.out.write(cursor.hide);

let prompt = [
util.style.symbol(this.done, this.aborted),
this.msg,
util.style.delimiter(this.completing),
this.done && this.suggestions[this.cursor]
? this.suggestions[this.cursor].title
: this.transform(this.input)
].join(' ');

if (!this.done) {
for (let i = 0; i < this.suggestions.length; i++) {
const s = this.suggestions[i];
prompt += '\n' + (i === this.cursor ? color.cyan(s.title) : s.title);
}
}

this.out.write(this.clear + prompt);
this.clear = util.clear(prompt);
}
}

module.exports = AutocompletePrompt;
70 changes: 70 additions & 0 deletions lib/elements/confirm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const color = require('clorox');
const Prompt = require('./prompt');
const { style, clear } = require('../util');
const { erase, cursor } = require('sisteransi');

/**
* A CLI classic confirm prompt
*/
class ConfirmPrompt extends Prompt {
constructor({ message, initial = false }) {
super();
this.msg = message;
this.value = initial;
this.initialValue = initial;
this.render(true);
}

reset() {
this.value = this.initialValue;
this.fire();
this.render();
}

abort() {
this.done = this.aborted = true;
this.fire();
this.render();
this.out.write('\n');
this.close();
}

submit() {
this.done = true;
this.aborted = false;
this.fire();
this.render();
this.out.write('\n');
this.close();
}

_(c, key) {
if (c.toLowerCase() === 'y') {
this.value = true;
return this.submit();
}
if (c.toLowerCase() === 'n') {
this.value = false;
return this.submit();
}
return this.bell();
}

render(first) {
if (first) this.out.write(cursor.hide);
this.out.write(
erase.line +
cursor.to(0) +
[
style.symbol(this.done, this.aborted),
color.bold(this.msg),
style.delimiter(this.done),
this.done
? this.value ? 'yes' : 'no'
: color.gray(this.initialValue ? '(Y/n)' : '(y/N)')
].join(' ')
);
}
}

module.exports = ConfirmPrompt;
11 changes: 11 additions & 0 deletions lib/elements/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use strict';

module.exports = {
TextPrompt: require('./text'),
SelectPrompt: require('./select'),
TogglePrompt: require('./toggle'),
NumberPrompt: require('./number'),
MultiselectPrompt: require('./multiselect'),
AutocompletePrompt: require('./autocomplete'),
ConfirmPrompt: require('./confirm')
};
Loading

0 comments on commit 69b3761

Please sign in to comment.