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

feat: add CLI keyboard shortcuts #9673

Closed
wants to merge 14 commits into from
Closed

feat: add CLI keyboard shortcuts #9673

wants to merge 14 commits into from

Conversation

joelmukuthu
Copy link

@joelmukuthu joelmukuthu commented Aug 14, 2022

Description

This is a rebase of #6014 to resolve merge conflicts. It introduces stdin shortcuts for restarting the dev server, opening the server in browser and toggling HMR.

  • h - show all shortcuts
  • r - restart server
  • o - open in browser
  • m - toggle HMR on/off
  • q - quit

Additional context

N/A


What is the purpose of this pull request?

  • Bug fix
  • New Feature
  • Documentation update
  • Other

Before submitting the PR, please make sure you do the following

  • Read the Contributing Guidelines.
  • Read the Pull Request Guidelines and follow the Commit Convention.
  • Check that there isn't already a PR that solves the problem the same way to avoid creating a duplicate.
  • Provide a description in this PR that addresses what the PR is solving, or reference the issue that it solves (e.g. fixes #123).
  • Ideally, include relevant tests that fail without this PR but pass with it.

aleclarson and others added 3 commits August 14, 2022 18:45
The shortcuts include:

  - [r] Restart the server (useful for third party config changes)
  - [o] Open the project in your default browser
  - [f] Clear the cache for optimized dependencies (then restart the
    server)

Co-authored-by: HomyeeKing <HomyeeKing@gmail.com>
Press "h" to toggle HMR updates on/off.

Useful when you hit a bug and don't want your code edits to refresh the browser (which would mean losing the error logs and app state).
@joelmukuthu joelmukuthu changed the title feat: add CLI keyboard shortcuts Draft: feat: add CLI keyboard shortcuts Aug 14, 2022
aleclarson
aleclarson previously approved these changes Aug 14, 2022
Copy link
Member

@aleclarson aleclarson left a comment

Choose a reason for hiding this comment

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

Looks good at a cursory glance!

Note to other reviewer: I haven't tested this PR specifically. It's possible that other changes are needed to get each shortcut working as expected with the newest Vite version.

@joelmukuthu joelmukuthu changed the title Draft: feat: add CLI keyboard shortcuts feat: add CLI keyboard shortcuts Aug 14, 2022
export async function resolveBrowserUrl(server: ViteDevServer): Promise<string> {
const options = server.config.server
const hostname = await resolveHostname(options.host)
const port = options.port || 3000
Copy link
Contributor

@tony19 tony19 Aug 15, 2022

Choose a reason for hiding this comment

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

The actual port used is not necessarily options.port unless strict port is enabled.

But there's already an existing utility function that determines the current server URL with the correct port:

export async function resolveServerUrls(

The results of that function are stored in server.resolvedUrls:

server.resolvedUrls = await resolveServerUrls(

So, you could use server.resolvedUrls.local[] instead of resolving it here. I think you could just default to the first URL in the array.

Copy link
Author

Choose a reason for hiding this comment

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

Super, thanks!

}

process.stdin
.on('data', onInput)
Copy link
Contributor

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.

I'm all in for uniformity!

},
{
key: 'f',
name: 'force restart',
Copy link
Contributor

Choose a reason for hiding this comment

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

The distinction between restart and force restart is unclear here IMO. The flag apparently forces the optimizer to re-bundle upon restarting the server. I think that should be reflected somehow in name here:

Suggested change
name: 'force restart',
name: 're-bundle dependencies and restart',

Copy link
Member

Choose a reason for hiding this comment

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

Sounds good to me!

@antfu @patak-dev Any opinion here?

Copy link
Member

Choose a reason for hiding this comment

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

I think we shouldn't expose this option. It is only needed if there is a bug in dependencies optimization re-bundling logic, that at this point is quite stable. I think it may end up confusing more users than helping them.

Copy link
Author

Choose a reason for hiding this comment

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

For posterity, I'd also suggest changing the key to some variation of "r" (maybe "R") if this option makes a comeback in the future.

@patak-dev
Copy link
Member

Thanks for keeping this PR active @joelmukuthu. Looks like there is an error when running the CLI, would you check in your local clone that the test is passing?

About the exposed option, I don't know if we should expose all of them. Maybe there are some discussions I missed, but f seems to niche (see comment above), and I also have doubts about h. When would this option be used? If HMR is working, I don't think it is needed. If there was an HMR bug, isn't a restart better? Could you expand on the use case for this one?

@aleclarson
Copy link
Member

I also have doubts about h. When would this option be used?

I added this one. It's useful when you're step debugging a client-side issue and hot-reloading would cause you to lose your state. If we don't have this option, you have to stop the dev server instead. I'd be fine with opening a separate PR for this option in the future, though.

@patak-dev
Copy link
Member

I also have doubts about h. When would this option be used?

I added this one. It's useful when you're step debugging a client-side issue and hot-reloading would cause you to lose your state. If we don't have this option, you have to stop the dev server instead. I'd be fine with opening a separate PR for this option in the future, though.

How does this debugging setup work? Is the idea that you would like to do changes to your files and they are big enough that you want to have intermediate save points while debugging purely in the client?
I'm ok with this, ya, it looks useful. Maybe we should add an explanation of when this is useful in the docs too. Let's see what others think about the option.

* Disable key bindings for the server by setting this to `false`. This can be
* useful if you need the `process.stdin` stream for another purpose.
*
* @default true
Copy link
Member

Choose a reason for hiding this comment

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

This should default to false for programmatic usages and only default to true in CLI

Copy link
Author

Choose a reason for hiding this comment

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

@antfu was this a docs-only change? Tbh I couldn't actually figure out where bindShortcuts was defaulted to true in the code. @aleclarson would you please point me in the right direction?

@joelmukuthu
Copy link
Author

joelmukuthu commented Aug 16, 2022

Thanks all for the reviews. I'll look into this within the next couple of days.

About the options, what I gather is that I should remove the f option.

Looks like there is an error when running the CLI, would you check in your local clone that the test is passing?

Will do!

@sapphi-red sapphi-red added the p2-nice-to-have Not breaking anything but nice to have (priority) label Aug 16, 2022
aleclarson
aleclarson previously approved these changes Aug 22, 2022
@patak-dev
Copy link
Member

I tested on MacOS and it pressing a key doesn't seem to work. And I can't use also Cmd+C to exit.

About the shortcuts info, this is the current output for the CLI after this PR:
image

If we are going to show the shortcuts on the CLI, the > Shortcuts: line should look similar to the Network line. I think that we shouldn't show the shortcuts all the time though, we have a very clean CLI output and there will be a lot of people that aren't going to be using these shortcuts. We could follow Vitest here. It shows h for help and q for quit.
image
And when you press h, it then shows the options, so we can keep adding in the future without adding more noise to the CLI:
image

@aleclarson
Copy link
Member

I tested on MacOS and it pressing a key doesn't seem to work. And I can't use also Cmd+C to exit.

This commit (6622560) should be reverted. There's no technical reason for it, and it likely causes the issue @patak-dev mentions above.

+1 for h and q keys

process.stdin.setRawMode(true)
}

process.stdin.on('keypress', keypressHandler).setEncoding('utf8').resume()
Copy link
Contributor

@tony19 tony19 Aug 22, 2022

Choose a reason for hiding this comment

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

@patak-dev @aleclarson The keys aren't detected in this changeset because of this...

The keypress event requires readline.emitKeypressEvents(process.stdin) beforehand.

I think the reason Vitest uses this instead of just the data event is because its shortcuts include a prompt for changing the test pattern input, where it needs to pause keypress handling to properly receive the input. Since our shortcuts don't have any prompts, we probably don't need this. Sorry for having suggested this change in my original review.

@joelmukuthu
Copy link
Author

Thanks for the reviews; ready for re-review.

@joelmukuthu joelmukuthu requested review from tony19, aleclarson and patak-dev and removed request for patak-dev, tony19 and aleclarson August 30, 2022 16:11
@joelmukuthu
Copy link
Author

Hi everyone, is there an update on this? Is there some way I can help to get this merged or reviewed?

@PengBoUESTC
Copy link
Contributor

I think this function should be treat as a plugin ... this is a expand of vite server. @patak-dev @antfu

@aleclarson
Copy link
Member

I think this function should be treat as a plugin ... this is a expand of vite server. @patak-dev @antfu

The dev server doesn't support CLI plugins, and it doesn't plan to (or at least, that's what I've inferred from previous discussions).

@PengBoUESTC
Copy link
Contributor

I think this function should be treat as a plugin ... this is a expand of vite server. @patak-dev @antfu

The dev server doesn't support CLI plugins, and it doesn't plan to (or at least, that's what I've inferred from previous discussions).

emmm.. this PR wants to communicate with vite server by terminal after server start, maybe it can be realized as a plugin. because In vite plugin, we can get server instance and user config info.

Comment on lines +118 to +124
/**
* Disable key bindings for the server by setting this to `false`. This can be
* useful if you need the `process.stdin` stream for another purpose.
*
* @default true in CLI, `false` in programmatic usage
*/
bindShortcuts?: boolean
Copy link
Member

Choose a reason for hiding this comment

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

Actually this is not called at all in programmatic usage. (like printURLs)

There is currently no option to disable print of server urls, I would do the same here.

If people want more complex use case, they can use the pragmatic usage.

Comment on lines +267 to +268
* Listen to `process.stdin` for pre-defined keyboard shortcuts, which are
* printed to the terminal by this method.
Copy link
Member

Choose a reason for hiding this comment

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

What can be useful for non standard custom usage is separating biding from help display with a little boolean flag on the method

return process.kill(process.pid, 'SIGINT')
}

if (input === 'h') {
Copy link
Member

Choose a reason for hiding this comment

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

This can be itself a shortcut. This is common for CLI to print the help option in the help itself

Comment on lines +66 to +72
export interface Shortcut {
key: string
description: string
action(server: ViteDevServer): void | Promise<void>
}

export const SHORTCUTS: Shortcut[] = [
Copy link
Member

Choose a reason for hiding this comment

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

Should this be exported?

return
}

if (actionRunning) {
Copy link
Member

Choose a reason for hiding this comment

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

Nit: this should be the second check

*/
config.server.hmr = config.server.hmr !== true
config.logger.info(
colors.cyan(` hmr ${config.server.hmr ? `enabled` : `disabled`}`)
Copy link
Member

Choose a reason for hiding this comment

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

I need to test but I think the two whitespaces at the beginning will look strange in the middle of Vite dev server logs

@joelmukuthu
Copy link
Author

Closed in favour of #11228

@joelmukuthu joelmukuthu closed this Dec 7, 2022
@joelmukuthu joelmukuthu deleted the feat/shortcuts branch December 7, 2022 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
p2-nice-to-have Not breaking anything but nice to have (priority)
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

8 participants