From 97065cefc22e4772c0295c5ad23a87eea286f46b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90=20Kevin=20Deng?= Date: Wed, 10 May 2023 23:36:15 +0800 Subject: [PATCH] feat(cli): add shortcuts (#2353) --- src/node/cli.ts | 2 + src/node/shortcuts.ts | 95 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 src/node/shortcuts.ts diff --git a/src/node/cli.ts b/src/node/cli.ts index 39be1190ced5..4aef97478890 100644 --- a/src/node/cli.ts +++ b/src/node/cli.ts @@ -4,6 +4,7 @@ import { createLogger } from 'vite' import { build, createServer, serve } from '.' import { init } from './init/init' import { version } from '../../package.json' +import { bindShortcuts } from './shortcuts' const argv: any = minimist(process.argv.slice(2)) @@ -33,6 +34,7 @@ if (!command || command === 'dev') { await server.listen() logVersion(server.config.logger) server.printUrls() + bindShortcuts(server) } createDevServer().catch((err) => { createLogger().error( diff --git a/src/node/shortcuts.ts b/src/node/shortcuts.ts new file mode 100644 index 000000000000..7e27fd65279d --- /dev/null +++ b/src/node/shortcuts.ts @@ -0,0 +1,95 @@ +import colors from 'picocolors' +import type { ViteDevServer } from 'vite' + +export type CLIShortcut = { + key: string + description: string + action(server: ViteDevServer): void | Promise +} + +export function bindShortcuts(server: ViteDevServer): void { + if (!server.httpServer || !process.stdin.isTTY || process.env.CI) { + return + } + + server.config.logger.info( + colors.dim(colors.green(' ➜')) + + colors.dim(' press ') + + colors.bold('h') + + colors.dim(' to show help') + ) + + let actionRunning = false + + const onInput = async (input: string) => { + // ctrl+c or ctrl+d + if (input === '\x03' || input === '\x04') { + await server.close().finally(() => process.exit(1)) + return + } + + if (actionRunning) return + + if (input === 'h') { + server.config.logger.info( + [ + '', + colors.bold(' Shortcuts'), + ...SHORTCUTS.map( + (shortcut) => + colors.dim(' press ') + + colors.bold(shortcut.key) + + colors.dim(` to ${shortcut.description}`) + ) + ].join('\n') + ) + } + + const shortcut = SHORTCUTS.find((shortcut) => shortcut.key === input) + if (!shortcut) return + + actionRunning = true + await shortcut.action(server) + actionRunning = false + } + + process.stdin.setRawMode(true) + + process.stdin.on('data', onInput).setEncoding('utf8').resume() + + server.httpServer.on('close', () => { + process.stdin.off('data', onInput).pause() + }) +} + +const SHORTCUTS: CLIShortcut[] = [ + { + key: 'u', + description: 'show server url', + action(server) { + server.config.logger.info('') + server.printUrls() + } + }, + { + key: 'o', + description: 'open in browser', + action(server) { + server.openBrowser() + } + }, + { + key: 'c', + description: 'clear console', + action(server) { + server.config.logger.clearScreen('error') + } + }, + { + key: 'q', + description: 'quit', + async action(server) { + await server.close().finally(() => process.exit()) + } + } +]