# Interactive Commands
One of the major features of seeli is that commands are inherently interactive. By default, all commands translate any flags into inquirer (opens new window) prompts.
# Advanced Flag Features
Command flags expose a number of options that allow you to customize the interactive experience.
# Selective Interactivity
It is possible to disable the built-in interactive behavior by simply setting
the interactive
option to false when creating a new command
'use strict'
const {Command} = require('seeli')
module.exports = new Command({
name: 'sample'
, interactive: false
, description: 'This command disables interactive behavior'
, run: async function() {
return 'hello world'
}
})
Alternatively, each flag may opt-out of the interactive work flow by setting a similar option
'use strict'
const {Command} = require('seeli')
module.exports = new Command({
name: 'sample'
, interactive: true
, description: 'This command disable interactivity on a single flag'
, flags: {
foo: {
type: Boolean
, interactive: false
, description: 'Including more foo'
}
, bar: {
type: Boolean
, description: 'Including more bar'
}
}
, run: async function(_, data) {
return {foo: data.for, bar: data.bar, message: 'hello world'}
}
})
# Input Masking
String flags can make the input being typed to hide sensitive information by
setting the mask
property to true
.
'use strict'
const {Command} = require('seeli')
module.exports = new Command({
name: 'mask'
, description: 'Input masking'
, flags: {
password: {
type: String
, mask: true
, description: 'user password'
}
, confirm: {
type: String
, mask: true
, description: 'confirm password'
}
}
, run: async function(_, data) {
if (data.confirm) {
return data.password == data.confirm
? 'password confirmed'
: 'passwords do not match'
}
return 'no password entered'
}
})
# Choice Lists
Choice lists provide a fixed set of allowable input values forcing users to pick a single value. The experience is similar in non-interactive situations in that passing a value that is not specified in the choice list will result in an error being thrown.
'use strict'
const {Command, colorize} = require('seeli')
module.exports = new Command({
name: 'choices'
, description: 'prompts for a specific value'
, flags: {
direction: {
type: String
, required: true
, description: 'The desired direction to travel'
, choices: ['north', 'south', 'east', 'west']
}
}
, run: async function(_, data) {
return `you selected ${colorize(data.direction)}!`
}
})
# Multi Select
By defining your flag input type as an Array
, the interactive input will
be presented as a multi-select allowing users to pick multiple values.
The result will be passed to the command as a single array just as it would from
non-interactive input.
'use strict'
const {Command, colorize} = require('seeli')
module.exports = new Command({
name: 'multi'
, description: 'prompts for a specific value'
, flags: {
direction: {
type: [String, Array]
, required: true
, description: 'The desired direction to travel'
, choices: ['north', 'south', 'east', 'west']
}
}
, run: async function(_, data) {
return `you selected ${colorize(data.direction)}!`
}
})
# Conditional Flags
There are situations when triggering an input prompt is logically dependent on
the input of a different flag. It is possible to define these dependencies by
specifing a when
function. This function accepts the accumulated input from
the flags that were defined before it. The when function should return a boolean
value which indicates if the prompt should be presented or not. An added benefit
is that you do need to implement the logic of executing the prompts.
'use strict'
const {Command} = require('seeli')
module.exports = new Command({
name: 'condition'
, description: 'Conditional flags'
, flags: {
one: {
type: String
, description: 'first value'
, default: null
}
, two: {
type: String
, description: 'second value'
, default: null
, when: (input) => {
return !!input.one
}
}
, three: {
type: String
, description: 'third value'
, default: null
, when: (input) => {
return !!(input.one && input.two)
}
}
, four: {
type: String
, description: 'fourth value'
, default: null
, when: (input) => {
return !!(input.two)
}
}
}
, run: async function(_, data) {
console.dir(data)
}
})
# Dynamic Prompting
For situations when the automatic interactive behavior isn't enough to express
complex logic, you can use the prompt
to implement any kind of prompting logic.
The Prompt function is a direct pass through to the inquirer (opens new window) prompt function.
'use strict'
const {Command} = require('seeli')
module.exports = new Command({
name: 'manual'
, description: 'Manual prompting'
, flags: {
foo: {
type: Boolean
, description: 'Including more foo'
}
}
, run: async function(_, data) {
if (data.foo) {
var {bar} = await this.prompt({
name: 'bar'
, type: 'input'
, message: 'include more bar'
, validate: (value) => {
if (!value) return 'bar is required'
return true
}
})
}
return bar ? 'we need more bar' : 'we have no bar'
}
})