Skip to content

Commit 76550d6

Browse files
authored
feat: add withGuide support to selectKey prompt (#452)
1 parent 86e36d8 commit 76550d6

File tree

4 files changed

+125
-7
lines changed

4 files changed

+125
-7
lines changed

‎.changeset/modern-dots-make.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@clack/prompts": patch
3+
---
4+
5+
Add `withGuide` support to selectKey prompt

‎packages/prompts/src/select-key.ts‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { SelectKeyPrompt, wrapTextWithPrefix } from '@clack/core';
1+
import { SelectKeyPrompt, settings, wrapTextWithPrefix } from '@clack/core';
22
import color from 'picocolors';
33
import { type CommonOptions, S_BAR, S_BAR_END, symbol } from './common.js';
44
import type { Option } from './select.js';
@@ -40,11 +40,12 @@ export const selectKey = <Value extends string>(opts: SelectKeyOptions<Value>) =
4040
initialValue: opts.initialValue,
4141
caseSensitive: opts.caseSensitive,
4242
render() {
43-
const title = `${color.gray(S_BAR)}\n${symbol(this.state)} ${opts.message}\n`;
43+
const hasGuide = (opts.withGuide ?? settings.withGuide) !== false;
44+
const title = `${hasGuide ? `${color.gray(S_BAR)}\n` : ''}${symbol(this.state)} ${opts.message}\n`;
4445

4546
switch (this.state) {
4647
case 'submit': {
47-
const submitPrefix = `${color.gray(S_BAR)} `;
48+
const submitPrefix = hasGuide ? `${color.gray(S_BAR)} ` : '';
4849
const selectedOption =
4950
this.options.find((opt) => opt.value === this.value) ?? opts.options[0];
5051
const wrapped = wrapTextWithPrefix(
@@ -55,16 +56,17 @@ export const selectKey = <Value extends string>(opts: SelectKeyOptions<Value>) =
5556
return `${title}${wrapped}`;
5657
}
5758
case 'cancel': {
58-
const cancelPrefix = `${color.gray(S_BAR)} `;
59+
const cancelPrefix = hasGuide ? `${color.gray(S_BAR)} ` : '';
5960
const wrapped = wrapTextWithPrefix(
6061
opts.output,
6162
opt(this.options[0], 'cancelled'),
6263
cancelPrefix
6364
);
64-
return `${title}${wrapped}\n${color.gray(S_BAR)}`;
65+
return `${title}${wrapped}${hasGuide ? `\n${color.gray(S_BAR)}` : ''}`;
6566
}
6667
default: {
67-
const defaultPrefix = `${color.cyan(S_BAR)} `;
68+
const defaultPrefix = hasGuide ? `${color.cyan(S_BAR)} ` : '';
69+
const defaultPrefixEnd = hasGuide ? color.cyan(S_BAR_END) : '';
6870
const wrapped = this.options
6971
.map((option, i) =>
7072
wrapTextWithPrefix(
@@ -74,7 +76,7 @@ export const selectKey = <Value extends string>(opts: SelectKeyOptions<Value>) =
7476
)
7577
)
7678
.join('\n');
77-
return `${title}${wrapped}\n${color.cyan(S_BAR_END)}\n`;
79+
return `${title}${wrapped}\n${defaultPrefixEnd}\n`;
7880
}
7981
}
8082
},

‎packages/prompts/test/__snapshots__/select-key.test.ts.snap‎

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,24 @@ exports[`text (isCI = false) > caseSensitive: true makes options case-sensitive
6363
]
6464
`;
6565
66+
exports[`text (isCI = false) > global withGuide: false removes guide 1`] = `
67+
[
68+
"<cursor.hide>",
69+
"◆ foo
70+
 a  Option A
71+
 b  Option B
72+
73+
",
74+
"<cursor.show>",
75+
"<cursor.backward count=999><cursor.up count=4>",
76+
"<erase.down>",
77+
"◇ foo
78+
Option A",
79+
"
80+
",
81+
]
82+
`;
83+
6684
exports[`text (isCI = false) > input is case-insensitive by default 1`] = `
6785
[
6886
"<cursor.hide>",
@@ -270,6 +288,24 @@ exports[`text (isCI = false) > selects option by keypress 1`] = `
270288
]
271289
`;
272290
291+
exports[`text (isCI = false) > withGuide: false removes guide 1`] = `
292+
[
293+
"<cursor.hide>",
294+
"◆ foo
295+
 a  Option A
296+
 b  Option B
297+
298+
",
299+
"<cursor.show>",
300+
"<cursor.backward count=999><cursor.up count=4>",
301+
"<erase.down>",
302+
"◇ foo
303+
Option A",
304+
"
305+
",
306+
]
307+
`;
308+
273309
exports[`text (isCI = true) > can cancel by pressing escape 1`] = `
274310
[
275311
"<cursor.hide>",
@@ -333,6 +369,24 @@ exports[`text (isCI = true) > caseSensitive: true makes options case-sensitive 1
333369
]
334370
`;
335371
372+
exports[`text (isCI = true) > global withGuide: false removes guide 1`] = `
373+
[
374+
"<cursor.hide>",
375+
"◆ foo
376+
 a  Option A
377+
 b  Option B
378+
379+
",
380+
"<cursor.show>",
381+
"<cursor.backward count=999><cursor.up count=4>",
382+
"<erase.down>",
383+
"◇ foo
384+
Option A",
385+
"
386+
",
387+
]
388+
`;
389+
336390
exports[`text (isCI = true) > input is case-insensitive by default 1`] = `
337391
[
338392
"<cursor.hide>",
@@ -539,3 +593,21 @@ exports[`text (isCI = true) > selects option by keypress 1`] = `
539593
",
540594
]
541595
`;
596+
597+
exports[`text (isCI = true) > withGuide: false removes guide 1`] = `
598+
[
599+
"<cursor.hide>",
600+
"◆ foo
601+
 a  Option A
602+
 b  Option B
603+
604+
",
605+
"<cursor.show>",
606+
"<cursor.backward count=999><cursor.up count=4>",
607+
"<erase.down>",
608+
"◇ foo
609+
Option A",
610+
"
611+
",
612+
]
613+
`;

‎packages/prompts/test/select-key.test.ts‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,45 @@ describe.each(['true', 'false'])('text (isCI = %s)', (isCI) => {
211211
expect(output.buffer).toMatchSnapshot();
212212
});
213213

214+
test('withGuide: false removes guide', async () => {
215+
const result = prompts.selectKey({
216+
message: 'foo',
217+
options: [
218+
{ label: 'Option A', value: 'a' },
219+
{ label: 'Option B', value: 'b' },
220+
],
221+
withGuide: false,
222+
input,
223+
output,
224+
});
225+
226+
input.emit('keypress', 'a', { name: 'a' });
227+
228+
await result;
229+
230+
expect(output.buffer).toMatchSnapshot();
231+
});
232+
233+
test('global withGuide: false removes guide', async () => {
234+
updateSettings({ withGuide: false });
235+
236+
const result = prompts.selectKey({
237+
message: 'foo',
238+
options: [
239+
{ label: 'Option A', value: 'a' },
240+
{ label: 'Option B', value: 'b' },
241+
],
242+
input,
243+
output,
244+
});
245+
246+
input.emit('keypress', 'a', { name: 'a' });
247+
248+
await result;
249+
250+
expect(output.buffer).toMatchSnapshot();
251+
});
252+
214253
test('long submitted labels are wrapped correctly', async () => {
215254
output.columns = 40;
216255

0 commit comments

Comments
 (0)