-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
/
shortcuts.ts
129 lines (112 loc) · 2.8 KB
/
shortcuts.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import colors from 'picocolors'
import type { ViteDevServer } from './server'
import { openBrowser } from './server/openBrowser'
import { isDefined } from './utils'
export type BindShortcutsOptions = {
/**
* Print a one line hint to the terminal.
*/
print?: boolean
customShortcuts?: (CLIShortcut | undefined | null)[]
}
export type CLIShortcut = {
key: string
description: string
action(server: ViteDevServer): void | Promise<void>
}
export function bindShortcuts(
server: ViteDevServer,
opts: BindShortcutsOptions,
): void {
if (!server.httpServer || !process.stdin.isTTY || process.env.CI) {
return
}
server._shortcutsOptions = opts
if (opts.print) {
server.config.logger.info(
colors.dim(colors.green(' ➜')) +
colors.dim(' press ') +
colors.bold('h') +
colors.dim(' to show help'),
)
}
const shortcuts = (opts.customShortcuts ?? [])
.filter(isDefined)
.concat(BASE_SHORTCUTS)
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 BASE_SHORTCUTS: CLIShortcut[] = [
{
key: 'r',
description: 'restart the server',
async action(server) {
await server.restart()
},
},
{
key: 'u',
description: 'show server url',
action(server) {
server.config.logger.info('')
server.printUrls()
},
},
{
key: 'o',
description: 'open in browser',
action(server) {
const url = server.resolvedUrls?.local[0]
if (!url) {
server.config.logger.warn('No URL available to open in browser')
return
}
openBrowser(url, true, server.config.logger)
},
},
{
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())
},
},
]