# 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'
  }
})

masking

# 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)}!`
  }
})

choices

# 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)}!`
  }
})

multiple choice

# 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)
  }
})

conditional

# 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'
  }
})

manual prompts