Coder Social home page Coder Social logo

question-deno's Introduction

Question

This is a module that can handle CLI questions/inquiries that can be resolved in a CLI. This module requires the use of --unstable flag since the raw reader API is not finalized yet.

import question from 'https://raw.githubusercontent.com/ocpu/question-deno/master/mod.ts'

const result = await question('confirm', 'Confirm removal of X?', true)
if (result === undefined) console.log('Prompt was canceled')
else if (result) console.log('I will now remove X')
else console.log('X will not be removed')

Each input type is documented in the overload list for the question function, it describes the use, the parameters, and controls.

Test the different question types: deno run --unstable https://raw.githubusercontent.com/ocpu/question-deno/master/demo.ts

TOC

Question Types

Current question types:

  • input: Ask the user for a free form text answer.
  • confirm: Ask for a confirmation about an action.
  • list: Provide a list from which the user can chose one option.
  • checkbox: Provide a list of options from which the user can mark the options they want.
  • password: Provide a free form password input with substitution text.

Input

Create a generic text input question requesting the user to input text in a free form format. A default value can be provided and if the free form text input is blank that value will be used instead.

Controls:

  • Ctrl+c will have the question canceled and return undefined.
  • Ctrl+d will exit the whole script no questions asked with a Deno.exit().
  • Up arrow or Home key will move the cursor to the start of the prompt text.
  • Down arrow or End key will move the cursor to the end of the prompt text.
  • Left arrow will move the cursor one step to the left once if able.
  • Right arrow will move the cursor one step to the right once if able.
  • Enter will return the test inputted or the provided default value.

Confirm

Create a confirmation question that resolves to a true or false based on user input. It takes an undefined, true, or false value as the default value. Each of the default value types has an effect on how the prompt looks like.

  • undefined will suffix the prompt with [y/n]
  • true will suffix the prompt with [Y/n]
  • false will suffix the prompt with [y/N]

The only valid values are anything starting with y or n uppercase or lowercase. The y and n is derived from the positive and negative labels. You can customize the labels in the options object The prompt can be canceled and will then return undefined.

Controls:

  • Ctrl+c will have the question canceled and return undefined.
  • Ctrl+d will exit the whole script no questions asked with a Deno.exit().
  • Up arrow or Home key will move the cursor to the start of the prompt text.
  • Down arrow or End key will move the cursor to the end of the prompt text.
  • Left arrow will move the cursor one step to the left once if able.
  • Right arrow will move the cursor one step to the right once if able.
  • Enter will return the parsed result of the text.

List

Creates a list of selectable items from which one item can be chosen. If no items are available to be selected this will return undefined without a question prompt.

Controls:

  • Ctrl+c will have the question canceled and return undefined.
  • Ctrl+d will exit the whole script no questions asked with a Deno.exit().
  • Up arrow will move the selected item up once if able.
  • Down arrow will move the selected item down once if able.
  • Home will move the selected item up to the start if able.
  • End will move the selected item down to the end if able.
  • PageUp will move the selected item up by the actual list window size if able.
  • PageDown will move the selected item down by the actual list window size if able.
  • Enter will return the currently selected item.

The options can either be a list of strings or an object describing the different options.

This control supports filtering by the label set by the option. To get started with the default configuration set the filtering list option to true. It will try to match the characters input with the label values.

The filtering has support to be able to search by exact label value, highlight the sections on the label that is matching the string, only sort the options by the string instead to removing the non matching options, and sort the options by specificity rank or the specified manual sorting.

import question from 'https://raw.githubusercontent.com/ocpu/question-deno/master/mod.ts'

await question('list', 'Select groceries?', ['Cheese', 'Milk', 'Tofu'])
await question('list', 'Select groceries?', {
  // <Label>: <value> - value can be anything
  'Cheese': 'cheese',
  'Milk': 'milk',
  'Tofu': 'tofu',
})

Checkbox

Creates a list of selectable items from which one item will be chosen. If no items are available to be selected this will return undefined without a question prompt.

Controls:

  • Ctrl+c will have the question canceled and return undefined.
  • Ctrl+d will exit the whole script no questions asked with a Deno.exit().
  • Ctrl+a will select/deselect all options.
  • Up arrow will move the selected item up once if able.
  • Down arrow will move the selected item down once if able.
  • Home will move the selected item up to the start if able.
  • End will move the selected item down to the end if able.
  • PageUp will move the selected item up by the actual list window size if able.
  • PageDown will move the selected item down by the actual list window size if able.
  • Space will mark/unmark the selected item.
  • Enter will return all marked items in a list.

The options can either be a list of strings or an object describing the different options.

If the options parameter is a plain object where the key is the label and the value is a object definition how the option is represented in the list and with a value. The representation keys are:

  • dependencies: This is a value that takes a index, label, or a list of indices and labels to express the reliance of a different option. So whenever any dependant option is select this one is too. Same for deselects.
  • selected: This makes the option selected by default. If the option depends on any other options They will also be selected.

This control supports filtering by the label set by the option. To get started with the default configuration set the filtering checkbox option to true. It will try to match the characters input with the label values.

The filtering has support to be able to search by exact label value, highlight the sections on the label that is matching the string, only sort the options by the string instead to removing the non matching options, and sort the options by specificity rank or the specified manual sorting.

import question from 'https://raw.githubusercontent.com/ocpu/question-deno/master/mod.ts'

await question('checkbox', 'Select toppings?', ['Cheese', 'Garlic', 'Salami'])
await question('checkbox', 'Select toppings?', {
  // <Label>: <Options> - value can be anything
  'Cheese': { value: 'cheese', selected: true },
  'Garlic': { value: 'garlic' },
  'Salami': { value: 'salami' },
})

Password

Creates a free form text input that does not print the characters normally printed by the input prompt. The characters are substituted for a substitute string you can provide. If the substitute parameter is a boolean false no substitute characters will be printed.

The substitute string if longer than 1 character can be called a pattern and will also be printed in that pattern. So if you have a pattern of <> and that length of the text i 5 the substitution will look like <><><.

Controls:

  • Ctrl+c will have the question canceled and return undefined.
  • Ctrl+d will exit the whole script no questions asked with a Deno.exit().
  • Up arrow or Home key will move the cursor to the start of the prompt text.
  • Down arrow or End key will move the cursor to the end of the prompt text.
  • Left arrow will move the cursor one step to the left once if able.
  • Right arrow will move the cursor one step to the right once if able.
  • Enter will return the test inputted or the provided default value.

Config

The project currently supports these configuration options:

  • keypressReader: A way of specifying from where the input characters will be read from. Default is Deno.stdin.
  • writer: A way of specifying from where to output the option rendering. Default is Deno.stdout.

These options mostly come in handy when you want use the program you are writing as a start, end, and/or in between step of linux pipes.

Config option keypressReader

You can config keypress reader to prevent "Keypress can be read only under TTY" error if you try to use piped input on Linux:

import question, { questionConfig as questionConfig } from 'https://raw.githubusercontent.com/ocpu/question-deno/master/mod.ts'

try {
  // requires --allow-read on the file specified.
  const tty = await Deno.open("/dev/tty");
  if (Deno.isatty(tty.rid)) {
    questionConfig.keypressReader = tty;
  }
} catch(e) {}

Config option writer

This config option lets you direct the output flow of the prompts supported by the library. It is most useful when you want your program to output something for a different program in a pipe chain.

import question, { questionConfig as questionConfig } from 'https://raw.githubusercontent.com/ocpu/question-deno/master/mod.ts'

try {
  // requires --allow-write on the file specified.
  const tty = await Deno.open("/dev/tty", { write: true });
  if (Deno.isatty(tty.rid)) {
    questionConfig.writer = tty;
  }
} catch(e) {}

question-deno's People

Contributors

d9k avatar ocpu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

question-deno's Issues

Filtering

That would be very convenient if letters and digits press would filter options and highlight matched letters with different color.

Also counter of matched lines would be great, example:

(3/18 items match "report")

Filtering may be non-default config option.

Built-in cli client

I made wrapper script for simple everyday cli Linux tasks:

https://github.com/d9k/cli_select

Example usage:

tac todo.txt | cli-select -m "What do you plan to do today?" > todo-today.txt 

My code can be adopted to make some default cli.ts client.

Using piped input: Keypress can be read only under TTY

Cool and convenient library! Thanks!

In my simple cli app I want to read input from pipe, something like

cat myfile.txt | tac | deno run --allow-read --unstable --name myapp.ts

Then I read input with:

  for await (const l of readLines(Deno.stdin)) {
    console.log(l)
  }

But after that I got error 'Keypress can be read only under TTY.' which comes from createRenderer():

keys:for await (const keypress of readKeypress()) {

which calls readKeypress()

    if (!Deno.isatty(reader.rid)) {
        throw new Error('Keypress can be read only under TTY.')
    }

in https://github.com/dmitriytat/keypress/blob/0.0.7/mod.ts#L399

I tried to patched your modified/question-deno/util.ts to fix that:

export async function createRenderer<R>(options: CreateRendererOptions<R>): Promise<R | undefined> {
  const cancelKeyCombo = KeyCombo.parse('Ctrl+c')
  const exitKeyCombo = KeyCombo.parse('Ctrl+d')

  // D9K MOD BEGIN
  let keypressReader = Deno.stdin;
  try {
    const tty = Deno.openSync("/dev/tty");
    if (Deno.isatty(tty.rid)) {
      keypressReader = tty;
    }
  } catch(e) {}
  // END d9k MOD

  options.prompt()

  // D9K MOD BEGIN
  keys:for await (const keypress of readKeypress(keypressReader)) {
  // END d9k MOD

and it works.

I propose to add something like

question.config.keypressReader

option

deno.land/x ?

Love it!
why is not publish in deno.land/x ?
I was lookinh for it for a long time!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.