Commit 6d614b7
Changed files (2)
src
test
src/experimental.ts
@@ -13,7 +13,7 @@
// limitations under the License.
import assert from 'node:assert'
-import { $ } from './core.js'
+import { $, within } from './core.js'
import { sleep } from './goods.js'
import { Duration, parseDuration } from './util.js'
@@ -56,20 +56,26 @@ export async function retry<T>(
throw 'unreachable'
}
-/**
- * Starts a simple CLI spinner.
- * @param title Spinner's title.
- * @return A stop() func.
- */
-export function startSpinner(title = '') {
- let i = 0,
- v = $.verbose
- $.verbose = false
- let spin = () =>
+export async function spinner<T>(callback: () => T): Promise<T>
+export async function spinner<T>(title: string, callback: () => T): Promise<T>
+export async function spinner<T>(
+ title: string | (() => T),
+ callback?: () => T
+): Promise<T> {
+ if (typeof title == 'string') {
+ assert(callback)
+ } else {
+ callback = title
+ title = ''
+ }
+ let i = 0
+ const spin = () =>
process.stderr.write(` ${'⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'[i++ % 10]} ${title}\r`)
- let id = setInterval(spin, 100)
- return () => {
+ return within(async () => {
+ $.verbose = false
+ const id = setInterval(spin, 100)
+ const result = await callback!()
clearInterval(id)
- $.verbose = v
- }
+ return result
+ })
}
test/experimental.test.js
@@ -40,13 +40,24 @@ test('retry works', async () => {
assert.ok(Date.now() >= now + 50 * (5 - 1))
})
-test('spinner works', async () => {
+test('spinner() works', async () => {
let out = await zx(`
- let stop = startSpinner('waiting')
- await sleep(1000)
- stop()
+ echo(await spinner(async () => {
+ await sleep(100)
+ await $\`echo hidden\`
+ return $\`echo result\`
+ }))
`)
- assert.match(out.stderr, 'waiting')
+ assert.match(out.stdout, 'result')
+ assert.not.match(out.stderr, 'result')
+ assert.not.match(out.stderr, 'hidden')
+})
+
+test('spinner() with title works', async () => {
+ let out = await zx(`
+ await spinner('processing', async () => sleep(100))
+ `)
+ assert.match(out.stderr, 'processing')
})
test.run()