Code Monkey home page Code Monkey logo

Comments (8)

SBoudrias avatar SBoudrias commented on June 3, 2024 2

How can I best share this in case other's want to use it? I figure someone else may want this functionality too.

You could put the code in a Github repo, and release it as a new package to npm 😄

from inquirer.js.

SBoudrias avatar SBoudrias commented on June 3, 2024 1

@pgibler if you want something out of the box, the expand prompt is your best bet. Otherwise, you could fork the code from the expand prompt and customize it (with the new core API, the prompt is just ~100 lines of code - so cheap to copy-paste in your project or publish your own custom prompt package).

I think there might be an option to expand the default prompt by default (but I wrote that years ago, so I'm not 100% sure anymore 😅)

from inquirer.js.

SBoudrias avatar SBoudrias commented on June 3, 2024 1

@pgibler you can add your prompt here https://github.com/SBoudrias/Inquirer.js/blob/master/packages/prompts/README.md#community-prompts if you want to advertise it! I'm planning to switch this README to the repo homepage next weekend (more on that).

from inquirer.js.

SBoudrias avatar SBoudrias commented on June 3, 2024

Hi, this isn't something we support in the base API. I would recommend you to create a custom prompt to handle this use case.

I'd recommend you to use the new API to do so. Maybe replicating the new select prompt code and looking into useKeypress().

Hope this helps!

from inquirer.js.

pgibler avatar pgibler commented on June 3, 2024

@SBoudrias I have a similar question, not sure if the useKeyPress will work for this or not, but do let me know.

I have this as my output list:

? Choose an option:
❯ Run all commands (A)
Run setup commands (S)
Run main command (M)
Quit (Q)

I want it such that the user can either use the arrow keys + Enter to make a selection, or just hit the key corresponding to the option.

Is there a way to achieve this with the new API?

from inquirer.js.

pgibler avatar pgibler commented on June 3, 2024

I've followed your instructions and I almost have it done, but I've run into one bug that I'm wondering if you may remember the code well enough to know a solution. I'm going to try and figure it out myself so if I discover the fix I'll followup to help out anyone else who runs into the same thing.

It occurs when the prompt constructor is picked based on the question.type. There is a key / value pair for my customList in the configured prompts in PromptUI, but the value that comes back - which is supposed to be a constructor - results in an error when used like a constructor.

Here's what I'm seeing for the data that's being set in the fetchAnswer function in prompt.js (in Inquirer.js)

image

And indeed on moving to the next line, the Prompt field is assigned to the value at the customList prompt key.

image

But when this.activePrompt = new Prompt(question, this.rl, this.answers); is executed, I get this error:

These were the parameters passed into it:

image

Would you know what might be causing this? I can make a repo to allow you to reproduce if it would help.

Ultimately, I get this error:

image

Extra information below:

This is the getCustomMenuChoice function I have:

async function getCustomMenuChoice(nonInteractive, setupCommands) {
  const options = [
    {
      name: 'Run main command (M)',
      value: 'm',
    },
    {
      name: 'Quit (Q)',
      value: 'q',
    },
  ];

  const defaultOption = !nonInteractive ? 'c' : (
    nonInteractive && setupCommands.length > 0 ? 'a' : 'm'
  );

  if (setupCommands.length > 0) {
    options.unshift({ name: 'Run setup commands (S)', value: 's' })
    options.unshift({ name: 'Run all commands (A)', value: 'a' });
  }
  if (!nonInteractive) {
    const spliceIndex = options.findIndex(option => option.value === 'm')
    options.splice(spliceIndex, 0, {
      name: 'Copy command to clipboard (C)',
      value: 'c',
    });
  }

  const answers = await inquirer.prompt([
    {
      type: 'customList',
      name: 'choice',
      message: 'Choose an option:',
      choices: options,
      default: defaultOption,
    },
  ]);

  return answers.choice;
}

This is my customListPrompt.mjs

import {
  createPrompt,
  useState,
  useKeypress,
  usePrefix,
  isEnterKey,
  isUpKey,
  isDownKey,
} from '@inquirer/core';
import chalk from 'chalk';

export default createPrompt((config, done) => {
  const { choices, default: defaultKey = 'm' } = config;
  const [status, setStatus] = useState('pending');
  const [index, setIndex] = useState(choices.findIndex((choice) => choice.value === defaultKey));
  const prefix = usePrefix();

  useKeypress((key, rl) => {
    if (isEnterKey(key)) {
      const selectedChoice = choices[index];
      if (selectedChoice) {
        setStatus('done');
        done(selectedChoice.value);
      }
    } else if (isUpKey) {
      setIndex((prevIndex) => (prevIndex > 0 ? prevIndex - 1 : choices.length - 1));
    } else if (isDownKey) {
      setIndex((prevIndex) => (prevIndex < choices.length - 1 ? prevIndex + 1 : 0));
    } else {
      const foundIndex = choices.findIndex((choice) => choice.value.toLowerCase() === key.name.toLowerCase());
      if (foundIndex !== -1) {
        setIndex(foundIndex);
      }
    }
  });

  const message = chalk.bold(config.message);

  if (status === 'done') {
    return `${prefix} ${message} ${chalk.cyan(choices[index].name)}`;
  }

  const renderedChoices = choices
    .map((choice, i) => {
      const line = `  ${choice.name}`;
      if (i === index) {
        return chalk.cyan(`> ${line}`);
      }

      return `  ${line}`;
    })
    .join('\n');

  return [`${prefix} ${message}`, renderedChoices];
});

I appreciate the help with this! I'm really liking this library.

from inquirer.js.

pgibler avatar pgibler commented on June 3, 2024

Figured it out myself after going through your code again @SBoudrias

Here's a working implementation of a list prompt controllable by both up/down + Enter & keypress.

quickSelectPrompt.mjs

import {
  createPrompt,
  useState,
  useKeypress,
  usePrefix,
  isEnterKey,
  isUpKey,
  isDownKey,
} from '@inquirer/core';
import chalk from 'chalk';

export default createPrompt((config, done) => {
  const { choices, default: defaultKey = 'm' } = config;
  const [status, setStatus] = useState('pending');
  const [index, setIndex] = useState(choices.findIndex((choice) => choice.value === defaultKey));
  const prefix = usePrefix();

  useKeypress((key, _rl) => {
    if (isEnterKey(key)) {
      const selectedChoice = choices[index];
      if (selectedChoice) {
        setStatus('done');
        done(selectedChoice.value);
      }
    } else if (isUpKey(key)) {
      setIndex(index > 0 ? index - 1 : 0);
    } else if (isDownKey(key)) {
      setIndex(index < choices.length - 1 ? index + 1 : choices.length - 1);
    } else {
      const foundIndex = choices.findIndex((choice) => choice.value.toLowerCase() === key.name.toLowerCase());
      if (foundIndex !== -1) {
        setIndex(foundIndex);
        // This automatically finishes the prompt. Remove this if you don't want that.
        setStatus('done');
        done(choices[foundIndex].value);
      }
    }
  });

  const message = chalk.bold(config.message);

  if (status === 'done') {
    return `${prefix} ${message} ${chalk.cyan(choices[index].name)}`;
  }

  const renderedChoices = choices
    .map((choice, i) => {
      const line = `  ${choice.name}`;
      if (i === index) {
        return chalk.cyan(`> ${line}`);
      }

      return `  ${line}`;
    })
    .join('\n');

  return [`${prefix} ${message}`, renderedChoices];
});

Then to use it

const answer = await quickSelectPrompt({
  message: 'Choose an option:',
  choices: options,
  default: defaultOption,
});

return answer;

How can I best share this in case other's want to use it? I figure someone else may want this functionality too.

from inquirer.js.

pgibler avatar pgibler commented on June 3, 2024

Just got a repo up with the code now. Thanks for all the help getting this going @SBoudrias.

https://github.com/pgibler/inquirer-interactive-list-prompt

from inquirer.js.

Related Issues (20)

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.