Socket
Socket
Sign inDemoInstall

enquirer

Package Overview
Dependencies
Maintainers
2
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

enquirer - npm Package Compare versions

Comparing version 2.0.4 to 2.0.5

lib/prompts/hmultiselect.js

17

CHANGELOG.md

@@ -38,16 +38,21 @@ # Release history

**What changed in Enquirer 2.0?**
Enquire 2.0 is a bottom-up complete re-write:
- Several prompts that were previously published as individual packages will be included in Enquirer itself.
- Why? - As users, we didn't like having to add commonly-used prompts as plugins. Enquirer 2.0 will still support custom prompts as plugins, but many prompts will also be built-in.
- Enquirer will only have a single dependency, https://github.com/doowb/ansi-colors, which itself has no other dependencies). This will make Enquirer easier to maintain and faster for users.
- Methods for registering "questions" have been removed. While it was nice to be able to preregister questions that could be called upon later, this is something that is better left to implementors, as it's relatively trivial to do with custom code.
### Changed
todo
- `options.default` is now `options.initial`
### Added
todo
- Many prompts that were previously separate packages are now bundled into Enquirer itself.
## 1.0.0
todo
[Unreleased]: https://github.com/enquirer/enquirer/compare/2.0.2...HEAD
[keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog

@@ -33,2 +33,3 @@ 'use strict';

this.result = (this.options.result || this.result).bind(this);
this.render = (this.options.render || this.render).bind(this);
this.setMaxListeners(0);

@@ -188,3 +189,6 @@ }

let value = options[name] || state[name] || symbols[name];
let val = choice && choice[name] != null ? choice[name] : value;
if (val === '') return val;
let res = await utils.resolve(state, val, state, choice, i);

@@ -241,7 +245,7 @@ if (!res && choice && choice[name]) {

let styles = this.styles;
let enabled = this.index === i;
let style = enabled ? styles.primary : val => val;
let ele = await this.resolve(val[enabled ? 'on' : 'off'] || val, this.state);
let focused = this.index === i;
let style = focused ? styles.primary : val => val;
let ele = await this.resolve(val[focused ? 'on' : 'off'] || val, this.state);
let styled = !utils.hasColor(ele) ? style(ele) : ele;
return enabled ? styled : ' '.repeat(ele.length);
return focused ? styled : ' '.repeat(ele.length);
}

@@ -264,2 +268,4 @@ }

}
return '';
}

@@ -310,3 +316,3 @@

isValue(value) {
return !!value;
return value != null && value !== '';
}

@@ -313,0 +319,0 @@

@@ -12,2 +12,4 @@ 'use strict';

define('Form', () => require('./form'));
define('hMultiSelect', () => require('./hmultiselect'));
define('hSelect', () => require('./hselect'));
define('Input', () => require('./input'));

@@ -17,3 +19,3 @@ define('Invisible', () => require('./invisible'));

define('MultiSelect', () => require('./multiselect'));
define('Number', () => require('./number'));
define('Numeral', () => require('./numeral'));
define('Password', () => require('./password'));

@@ -20,0 +22,0 @@ define('Select', () => require('./select'));

@@ -23,2 +23,7 @@ 'use strict';

separator() {
let sep = this.styles.muted(this.symbols.ellipsis);
return this.state.submitted ? super.separator() : sep;
}
pointer(item, i) {

@@ -33,3 +38,3 @@ return (!this.multiple || this.options.pointer) ? super.pointer(item, i) : '';

async renderChoice(item, i) {
// await this.onChoice(item, i);
await this.onChoice(item, i);

@@ -71,3 +76,3 @@ let focused = this.index === i;

if (!visible.length) visible.push(this.styles.danger('No matching choices'));
return visible.join('\n');
return '\n' + visible.join('\n');
}

@@ -92,3 +97,3 @@

if (this.options.promptLine !== false) {
prompt = [prefix, message, separator].filter(Boolean).join(' ');
prompt = [prefix, message, separator, ''].join(' ');
this.state.prompt = prompt;

@@ -103,6 +108,6 @@ }

if (output || !help) prompt += ' ' + output;
if (output) prompt += output;
if (help && !prompt.includes(help)) prompt += ' ' + help;
if (submitted && !output && !body && this.multiple && this.emptyError != null) {
if (submitted && !output && !body.trim() && this.multiple && this.emptyError != null) {
prompt += this.styles.danger(this.emptyError);

@@ -112,3 +117,3 @@ }

this.clear(size);
this.write([header, prompt, body, footer].filter(Boolean).join('\n'));
this.write([header, prompt + body, footer].filter(Boolean).join('\n'));
this.restore();

@@ -115,0 +120,0 @@ }

@@ -6,4 +6,5 @@ 'use strict';

class Survey extends ArrayPrompt {
constructor(options) {
constructor(options = {}) {
super(options);
this.emptyError = options.emptyError || 'No items were selected';
this.pos = { h: 0, get v() { return this.index; } };

@@ -140,3 +141,3 @@ this.term = process.TERM_PROGRAM;

if (submitted && !output && !body && this.multiple && this.type !== 'form') {
prompt += this.styles.danger('No items were selected');
prompt += this.styles.danger(this.emptyError);
}

@@ -143,0 +144,0 @@

@@ -228,3 +228,3 @@ 'use strict';

}
};
}

@@ -231,0 +231,0 @@ this.index = this.choices.indexOf(choice);

{
"name": "enquirer",
"description": "Stylish, intuitive and user-friendly prompt system. Fast and lightweight enough for small projects, powerful and extensible enough for the most advanced use cases.",
"version": "2.0.4",
"version": "2.0.5",
"homepage": "https://github.com/enquirer/enquirer",

@@ -51,5 +51,7 @@ "author": "Jon Schlinkert (https://github.com/jonschlinkert)",

"command-line",
"confirm",
"enquirer",
"Enquirer",
"enquirerprompt",
"generator",
"generate",
"hyper",
"input",

@@ -59,7 +61,14 @@ "inquire",

"interface",
"menu",
"iterm",
"javascript",
"node",
"nodejs",
"prompt",
"prompts",
"promptly",
"question",
"readline",
"scaffold",
"scaffolding",
"scaffolder",
"stdin",

@@ -69,3 +78,6 @@ "stdout",

"tty",
"ui"
"ui",
"yeoman",
"yo",
"zsh"
],

@@ -72,0 +84,0 @@ "lintDeps": {

@@ -36,11 +36,12 @@ <h1 align="center">Enquirer</h1>

* **Lightweight** - Only [one dependency](https://github.com/doowb/ansi-colors).
* **Easy to use** - Uses promises and async/await to make prompts easy to create and use.
* **Intuitive** - Navigating around input and choices is a breeze. Advanced keypress combos are available to simplify usage. You can even create [quizzes](recipes/quiz.js), or [record](recipes/record.js) and [playback](recipes/play.js) keypresses to aid with tutorials and videos.
* **Multilingual** - Easily add support for multiple languages.
* **Extensible** - Prompts are easy to create and extend.
* **Easy to implement** - Uses promises and async/await and sensible defaults to make prompts easy to create and implement.
* **Easy to use** - Thrill your users! Navigating around input and choices is a breeze. You can even create [quizzes](recipes/quiz.js), or [record](recipes/record.js) and [playback](recipes/play.js) keypresses to aid with tutorials and videos.
* **Intuitive** - Keypress combos are available to simplify usage.
* **Flexible** - All prompts can be used standalone or chained together.
* **Pluggable** - Add advanced features to Enquirer with plugins.
* **Stylish** - Easily override styles and symbols for any part of the prompt.
* **Stylish** - Easily override semantic styles and symbols for any part of the prompt.
* **Extensible** - Easily create and use custom prompts by extending Enquirer's built-in [prompts](#-prompts).
* **Pluggable** - Add advanced features to Enquirer using plugins.
* **Validation** - Optionally validate user input with any prompt.
* **Well tested** - All prompts are well-tested, and tests are easy to create without having to use brittle, hacky solutions to spy on prompts or "inject" values.
* **Examples** - There are numerous [examples](examples) and [recipes](recipes) available to help you get started.

@@ -56,4 +57,4 @@ <br>

* [Enquirer API](#-enquirer-api)
* [Prompts](#-prompts)
* [Types](#-types)
* [Built-in Prompts](#-prompts)
* [Custom Prompts](#-custom-prompts)
* [Keypresses](#-keypresses)

@@ -79,2 +80,11 @@ * [Options](#-options)

## ❯ Overview
### How does Enquirer work?
Enquirer is a [Node.js](https://nodejs.org/en/) library.
The main export is the `Enquirer` class.
<br>
## ❯ Usage

@@ -123,4 +133,17 @@

**Jump to**: [Getting Started](#-getting-started) · [Prompts](#-prompts) · [Options](#-options) · [Keypresses](#-keypresses)
<br>
## TODO
We're currently working on documentation for the following items. Please star and watch the repository for updates!
* Customizing symbols
* Customizing styles (palette)
* Customizing styles
* Links to recipes
<br>
## ❯ Enquirer API

@@ -256,2 +279,4 @@

**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
### Confirm Prompt

@@ -271,2 +296,19 @@

**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
### Form Prompt
Prompt that allows the user to enter and submit multiple values on a single terminal screen.
<p align="center">
<img src="https://github.com/enquirer/enquirer/raw/master/media/form-prompt.gif" alt="Enquirer Form Prompt" width="750">
</p>
**Related prompts**
* [input prompt](#input-prompt)
* [survey prompt](#number-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
### Input Prompt

@@ -286,2 +328,4 @@

**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
### Invisible Prompt

@@ -300,2 +344,4 @@

**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
### List Prompt

@@ -314,2 +360,4 @@

**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
### Multiselect Prompt

@@ -328,8 +376,10 @@

### Number Prompt
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
### Numeral Prompt
Prompt that takes a number as input.
<p align="center">
<img src="https://github.com/enquirer/enquirer/raw/master/media/number-prompt.gif" alt="Enquirer Number Prompt" width="750">
<img src="https://github.com/enquirer/enquirer/raw/master/media/numeral-prompt.gif" alt="Enquirer Numeral Prompt" width="750">
</p>

@@ -342,2 +392,4 @@

**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
### Password Prompt

@@ -356,2 +408,4 @@

**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
### Select Prompt

@@ -370,2 +424,4 @@

**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
### Snippet Prompt

@@ -384,2 +440,4 @@

**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
### Sort Prompt

@@ -402,2 +460,4 @@

**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
### Survey Prompt

@@ -418,2 +478,4 @@

Enquirer 2.0 introduced the concept of prompt "types", with the goal of making custom prompts easier than ever to create and use. There are 4 (soon to be 5!) type classes:
* [ArrayPrompt](#arrayprompt)

@@ -425,18 +487,192 @@ * [BooleanPrompt](#booleanprompt)

Each type is a low-level class that may be used as a starting point for creating higher level prompts. Continue reading to learn how.
### ArrayPrompt
todo
The `ArrayPrompt` class is used for creating prompts that display a list of choices in the terminal. For example, Enquirer uses this class as the basis for the [Select](#select) and [Survey](#survey) prompts.
#### Options
In addition to the [options](#options) available to all prompts, Array prompts also support the following options.
| **Option** | **Required?** | **Type** | **Description** |
| --- | --- | --- | --- |
| `type` | `Yes` | `string\|function` | Enquirer uses this value to determine the type of prompt to run, but it's optional when prompts are run directly. |
| `name` | `Yes` | `string\|function` | Used as the key for the answer on the returned values (answers) object. |
| `message` | `Yes` | `string\|function` | The message to display when the prompt is rendered in the terminal. |
| `autofocus` | `no` | `string\|number` | The index or name of the choice that should have focus when the prompt loads. Only one choice may have focus at a time. |
| `initial` | `no` | `string\|function` | The default value to return when the user does not supply a value. |
| `format` | `no` | `function` | Function to format user input in the terminal. |
| `result` | `no` | `function` | Function to format the final submitted value before it's returned. |
| `stdin` | `no` | `stream` | The input stream to use for emitting keypress events. Defaults to `process.stdin`. |
| `stdout` | `no` | `stream` | The output stream to use for writing the prompt to the terminal. Defaults to `process.stdout`. |
| `validate` | `no` | `function` | Function to validate the submitted value before it's returned. This function may return a boolean or a string. If a string is returned it will be used as the validation error message. |
#### Properties
Array prompts have the following instance properties and getters.
| **Property name** | **Type** | **Description** |
| --- | --- | --- |
| `choices` | `array` | Array of choices that have been normalized from choices passed on the prompt options. |
| `cursor` | `number` | Position of the cursor relative to the _user input (string)_. |
| `enabled` | `array` | Returns an array of enabled choices. |
| `focused` | `array` | Returns the currently selected choice in the visible list of choices. This is similar to the concept of focus in HTML and CSS. Focused choices are always visible (on-screen). When a list of choices is longer than the list of visible choices, and an off-screen choice is _focused_, the list will scroll to the focused choice and re-render. |
| `focused` | Gets the currently selected choice. Equivalent to `prompt.choices[prompt.index]`. |
| `index` | `number` | Position of the pointer in the _visible list (array) of choices_. |
| `limit` | `number` | The number of choices to display on-screen. |
| `selected` | `array` | Either a list of enabled choices (when `options.multiple` is true) or the currently focused choice. |
| `visible` | `string` | |
#### Methods
| **Method** | **Description** |
| --- | --- |
| `pointer()` | Returns the visual symbol to use to identify the choice that currently has focus. The `❯` symbol is often used for this. The pointer is not always visible, as with the `autocomplete` prompt. |
| `indicator()` | Returns the visual symbol that indicates whether or not a choice is checked/enabled. |
| `focus()` | Sets focus on a choice, if it can be focused. |
#### Choices
Array prompts support the `choices` option, which is the array of choices you want to allow the user to select from. Choices may be defined as strings or objects.
**Choice objects**
Choices are normalized to the following interface:
```js
{
name: string;
message: string | undefined;
value: string | undefined;
hint: string | undefined;
disabled: boolean | string | undefined;
}
```
**Choice properties**
| **Option** | **Type** | **Description** |
| --- | --- | --- |
| `name` | `string` | The unique key to identify a choice |
| `message` | `string` | The message to display in the terminal. `name` is used when this is undefined. |
| `value` | `string` | Value to associate with the choice. Useful for creating key-value pairs from user choices. `name` is used when this is undefined. |
| `choices` | `array` | Array of "child" choices. |
| `hint` | `string` | Help message to display next to a choice. |
| `role` | `string` | Determines how the choice will be displayed. Currently the only role supported is `separator`. Additional roles may be added in the future (like `heading`, etc). Please create a [feature request] |
| `enabled` | `boolean` | Enabled a choice by default. This is only supported when `options.multiple` is true or on prompts that support multiple choices, like [MultiSelect](#-multiselect). |
| `disabled` | `boolean\|string` | Disable a choice so that it cannot be selected. This value may either be `true`, `false`, or a message to display. |
| `indicator` | `string\|function` | Custom indicator to render for a choice (like a check or radio button). |
**Example usage**
```js
const { prompt } = require('enquirer');
const question = {
type: 'select',
name: 'color',
message: 'Favorite color?',
initial: 1,
choices: [
{ name: 'red', message: 'Red', value: '#ff0000' },
{ name: 'green', message: 'Green', value: '#00ff00' },
{ name: 'blue', message: 'Blue', value: '#0000ff' }
]
};
prompt(question)
.then(answer => console.log('Answer:', answer))
.catch(console.error);
```
#### Related prompts
* [autocomplete prompt](#autocomplete-prompt)
* [form prompt](#form-prompt)
* [multiselect prompt](#multiselect-prompt)
* [select prompt](#select-prompt)
* [survey prompt](#survey-prompt)
### BooleanPrompt
todo
The `BooleanPrompt` class is used for creating prompts that display and return a boolean value.
**Returns**: `boolean`
### NumberPrompt
todo
The `NumberPrompt` class is used for creating prompts that display and return a numerical value.
**Returns**: `string|number` (number, or number formatted as a string)
### StringPrompt
todo
The `StringPrompt` class is used for creating prompts that display and return a string value.
<br>
## ❯ Custom prompts
With Enquirer 2.0, custom prompts are easier than ever to create and use.
**How do I create a custom prompt?**
Custom prompts are created by extending Enquirer's `Prompt` class, or one of the built-in [prompts](#-prompts) or low-level [types](#-types).
```js
const { Prompt } = require('enquirer');
class HaiKarate extends Prompt {
constructor(options = {}) {
super(options);
this.value = options.sprays || 0;
this.cursorHide();
}
up() {
this.value++;
this.render();
}
down() {
this.value--;
this.render();
}
render() {
this.clear(); // clear previously rendered prompt from the terminal
this.write(`${this.state.message}: ${this.value}`);
}
}
```
To register a custom prompt, you must first instantiate `Enquirer`.
```js
const Enquirer = require('enquirer');
const enquirer = new Enquirer();
```
Then use the `.register()` method to add your custom prompt.
```js
enquirer.register('haikarate', HaiKarate);
```
Now you can do the following when defining "questions".
```js
let spritzer = require('cologne-drone');
let answers = await enquirer.prompt([
{
type: 'haikarate',
name: 'cologne',
message: 'How many sprays do you need?',
initial: 10,
async onSubmit(name, value) {
await spritzer.activate(value); //<= activate drone
return value;
}
}
]);
```
## ❯ Keypresses

@@ -505,4 +741,2 @@

### Prompt options
Each prompt takes an options object (aka "question" object), that implements the following interface:

@@ -512,5 +746,8 @@

{
// required
type: string | function,
name: string | function,
message: string | function | async function,
// optional
initial: string | function | async function

@@ -523,50 +760,32 @@ format: function | async function,

| **Property** | **Type** | **Description** |
| --- | --- | --- |
| `type` | `string\|function` | Enquirer uses this value to determine the type of prompt to run, but it's optional when prompts are run directly. |
| `name` | `string\|function` | Used as the key for the answer on the returned values (answers) object. |
| `message` | `string\|function` | The message to display when the prompt is rendered in the terminal. |
| `initial` | `string\|function` | The default value to return if the user does not supply a value. |
| `format` | `function` | Function to format user input in the terminal. |
| `result` | `function` | Function to format the final submitted value before it's returned. |
| `validate` | `function` | Function to validate the submitted value before it's returned. This function may return a boolean or a string. If a string is returned it will be used as the validation error message. |
### General options
_(`type`, `name` and `message` are required)._
All prompts take the following options.
**Example**
| **Property** | **Required?** | **Type** | **Description** |
| --- | --- | --- | --- |
| `type` | Yes | `string\|function` | Enquirer uses this value to determine the type of prompt to run, but it's optional when prompts are run directly. |
| `name` | Yes | `string\|function` | Used as the key for the answer on the returned values (answers) object. |
| `message` | Yes | `string\|function` | The message to display when the prompt is rendered in the terminal. |
| `initial` | no | `string\|function` | The default value to return if the user does not supply a value. |
| `format` | no | `function` | Function to format user input in the terminal. |
| `result` | no | `function` | Function to format the final submitted value before it's returned. |
| `validate` | no | `function` | Function to validate the submitted value before it's returned. This function may return a boolean or a string. If a string is returned it will be used as the validation error message. |
**Example usage**
```js
const { prompt } = require('enquirer');
const question = {
type: 'select',
name: 'color',
message: 'Favorite color?',
initial: 1,
choices: [
{ name: 'red', message: 'Red', value: '#ff0000' },
{ name: 'green', message: 'Green', value: '#00ff00' },
{ name: 'blue', message: 'Blue', value: '#0000ff' }
]
type: 'input',
name: 'username',
message: 'What is your username?'
};
```
### Choice objects
```js
Choice {
name: string;
message: string | undefined;
value: string | undefined;
hint: string | undefined;
disabled: boolean | string | undefined;
}
prompt(question)
.then(answer => console.log('Answer:', answer))
.catch(console.error);
```
| **Property** | **Type** | **Description** |
| --- | --- | --- |
| `name` | `string` | The unique key to identify a choice |
| `message` | `string` | The message to display in the terminal |
| `value` | `string` | An optional value to associate with the choice. This is useful for creating key-value pairs from user choices. |
| `hint` | `string` | Value to display to provide user help next to a choice. |
| `disabled` | `boolean\|string` | Disable a choice so that it cannot be selected. This value may either be `true`, `false`, or a message to display. |
<br>

@@ -589,3 +808,2 @@

inquirer: 286.717ms
prompts: 17.010ms
```

@@ -592,0 +810,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc