Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to set hotkeys for multiselect #234

Open
wants to merge 18 commits into
base: master
Choose a base branch
from

Conversation

NickHeiner
Copy link

@NickHeiner NickHeiner commented Nov 9, 2019

image

I'd like the ability to customize the hotkey options available to the user for multiselect. My dream is to have something like git add -p, where you get hotkeys like:

Stage this hunk [y,n,q,a,d,e,?]?

Example usage:

await prompts({
      // ...
      hotkeys: {
        d: {
          handle() {
            /* handle user action */
          },
          instruction: 'Save current progress and stop answering questions.'
        }
      },
    })

This PR is a draft. If you like the idea, I'll add tests / docs.

@@ -155,6 +156,9 @@ class MultiselectPrompt extends Prompt {
this.handleSpaceToggle();
} else if (c === 'a') {
this.toggleAll();
} else if (Object.keys(this.hotkeys).includes(c)) {
this.hotkeys[c].handle();
this.abort();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For my usecase, aborting was the correct behavior. If you'd like to move forward with this, I'll find a way to give the dev more control over what happens after the handler.

@terkelg
Copy link
Owner

terkelg commented Nov 9, 2019

This is cool – I like the idea a lot. Wonder if this could be a completely new prompt type?

@NickHeiner
Copy link
Author

I think it could be a new prompt type, but at least for my use case, I'd also like to add it to multiselect. I'll add tests / docs to this PR next.

@@ -150,11 +151,27 @@ class MultiselectPrompt extends Prompt {
this.render();
}

_(c, key) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This var was unused.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one!

<img src="https://github.com/terkelg/prompts/raw/master/prompts.png" alt="Prompts" width="500" />
<img src="./prompts.png" alt="Prompts" width="500" />
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change:

  1. Allows offline local rendering.
  2. Improves portability if the repo were ever to move.
  3. Makes the markdown more concise.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one! How does this work with the readme shown on NPM? @lukeed you spent some time researching this right? I would be nice to have these readme updates in their own PR

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The images still work on the npm registry page. For example, see: https://www.npmjs.com/package/list-maintainers.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to split these changes out. I assume you only want the image href updates split out, but the docs for this feature should stay in this PR?

@@ -0,0 +1,125 @@
const child_process = require('child_process');
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To get more confidence than the existing tests provide, I created a test that spawns a child process and interacts with it as a user would.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm looking into how to test the lib for version 3. If you have more ideas for how to do testing, please let me know.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this file is a good test approach, and it can be expanded to the rest of the lib.

@NickHeiner
Copy link
Author

This PR currently isn't passing on Node 6. (And there are a few cases, most notable lack of async/await support, that make supporting Node 6 make the code less readable.)

Node 6 is currently considered to be "end of life". It was released in 2016. How would you feel about dropping support for it?

@NickHeiner
Copy link
Author

@terkelg how does this look to you now?

@terkelg
Copy link
Owner

terkelg commented Nov 13, 2019

@NickHeiner thank you for the PR! I'll have a look at this over the weekend. Quick note: You can use async/await. It's already used quite a few places

- "8"
- "6"
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Node 6 was already unsupported, because async/await was being used.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you revert this please 👍

package.json Outdated
@@ -48,6 +48,6 @@
"tape": "^4.11.0"
},
"engines": {
"node": ">= 6"
"node": ">= 7"
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Node 6 was already unsupported, because async/await was being used. Thus, there's no need for a major version bump here.

Copy link
Owner

@terkelg terkelg Nov 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I didn't realize that. Ok. Well, Node 6 is EOL in any case. How would you feel about dropping support for it? My use of async / await will still require a bit more dev work to make the tests pass in Node 6.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good idea to drop Node 6 support, but I don't think we should do that before v3

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very thought out PR. Thank you for paying attention to things like versioning. - appreciate it. However I have a script that automatically bump version and publish. Would you mind reverting this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, for sure dropping Node 6 support should be behind a major version bump. And I take it you don't want this PR to be v3? 😄 I'll revert.

Copy link
Owner

@terkelg terkelg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late reply. I finally had time to look at your PR

- "8"
- "6"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you revert this please 👍

@@ -150,11 +151,27 @@ class MultiselectPrompt extends Prompt {
this.render();
}

_(c, key) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one!

package.json Outdated
@@ -48,6 +48,6 @@
"tape": "^4.11.0"
},
"engines": {
"node": ">= 6"
"node": ">= 7"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very thought out PR. Thank you for paying attention to things like versioning. - appreciate it. However I have a script that automatically bump version and publish. Would you mind reverting this?

<img src="https://github.com/terkelg/prompts/raw/master/prompts.png" alt="Prompts" width="500" />
<img src="./prompts.png" alt="Prompts" width="500" />
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one! How does this work with the readme shown on NPM? @lukeed you spent some time researching this right? I would be nice to have these readme updates in their own PR

@@ -0,0 +1,125 @@
const child_process = require('child_process');
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm looking into how to test the lib for version 3. If you have more ideas for how to do testing, please let me know.

@NickHeiner
Copy link
Author

Ok @terkelg I addressed your comments. It's now passing in Node 6.

@NickHeiner
Copy link
Author

@terkelg I'm ready to move forward on this whenever you are. 😄

@NickHeiner NickHeiner requested a review from terkelg November 27, 2019 19:21
@terkelg
Copy link
Owner

terkelg commented Nov 28, 2019

Looks good. I wonder if we should pass some arguments to the handler callback? Like a reference to the prompts so that you can provide some sort of visual feedback?

@NickHeiner
Copy link
Author

Looks good. I wonder if we should pass some arguments to the handler callback? Like a reference to the prompts so that you can provide some sort of visual feedback?

Sounds interesting, but I'm not sure precisely what you have in mind. Can you elaborate?

@terkelg
Copy link
Owner

terkelg commented Nov 30, 2019

Right now there's no feedback to the user to indicate a hotkey has been pressed/activated. I wonder if there could be a way to change selected mode in the hotkey callbacks?

@NickHeiner
Copy link
Author

If a hotkey changes which answers are selected, that's reflected in the rendered output. In this gif, we can see that pressing a (which is a "built in hotkey") and r (which is a hotkey added by this PR) both provide the same type of feedback.

multiselect hotkey feedback

Does this address what you're looking for, or am I misunderstanding?

@terkelg
Copy link
Owner

terkelg commented Dec 5, 2019

I'll have a look at it this weekend – I didn't get that for some reason

@terkelg
Copy link
Owner

terkelg commented Dec 8, 2019

        {
            type: 'multiselect',
            name: 'multicolor',
            message: 'Pick colors',
            hint: false,
            hotkeys: {
                d: {
                    handle(x, y) {
                        /* handle user action */
                    },
                    instruction: 'Save current progress and stop answering questions.'
                }
            },
            choices: [
                { title: 'Red', description: 'This option has a description.', value: '#ff0000' },
                { title: 'Green', value: '#00ff00' },
                { title: 'Yellow', value: '#ffff00', disabled: true },
                { title: 'Blue', value: '#0000ff' }
            ]
        },

When I run this I get no visual feedback as a user that I hit the hotkey?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants