Skip to content

Commit 29a50cb

Browse files
dreyfus9243081j
andauthored
fix(prompts): submit initial directory value in path prompt (#484)
Co-authored-by: James Garbutt <43081j@users.noreply.github.com>
1 parent 134a1a1 commit 29a50cb

File tree

3 files changed

+65
-3
lines changed

3 files changed

+65
-3
lines changed

.changeset/tricky-states-tease.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+
Fix `path` directory mode so pressing Enter with an existing directory `initialValue` submits that current directory instead of the first child option, and add regression coverage for immediate submit and child-directory navigation.

packages/prompts/src/path.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,17 @@ export const path = (opts: PathOptions) => {
4444
searchPath = dirname(userInput);
4545
} else {
4646
const stat = lstatSync(userInput);
47-
if (stat.isDirectory()) {
47+
if (stat.isDirectory() && (!opts.directory || userInput.endsWith('/'))) {
4848
searchPath = userInput;
4949
} else {
5050
searchPath = dirname(userInput);
5151
}
5252
}
5353

54+
// Strip trailing slash so startsWith matches the directory itself among its siblings
55+
const prefix =
56+
userInput.length > 1 && userInput.endsWith('/') ? userInput.slice(0, -1) : userInput;
57+
5458
const items = readdirSync(searchPath)
5559
.map((item) => {
5660
const path = join(searchPath, item);
@@ -62,9 +66,9 @@ export const path = (opts: PathOptions) => {
6266
};
6367
})
6468
.filter(
65-
({ path, isDirectory }) =>
66-
path.startsWith(userInput) && (isDirectory || !opts.directory)
69+
({ path, isDirectory }) => path.startsWith(prefix) && (isDirectory || !opts.directory)
6770
);
71+
6872
return items.map((item) => ({
6973
value: item.path,
7074
}));

packages/prompts/test/path.test.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,59 @@ describe.each(['true', 'false'])('text (isCI = %s)', (isCI) => {
163163
expect(value).toBe('/tmp/foo');
164164
});
165165

166+
test('directory mode submits initial directory value on enter', async () => {
167+
const result = prompts.path({
168+
message: 'foo',
169+
root: '/tmp/',
170+
initialValue: '/tmp',
171+
directory: true,
172+
input,
173+
output,
174+
});
175+
176+
input.emit('keypress', '', { name: 'return' });
177+
178+
const value = await result;
179+
180+
expect(value).toBe('/tmp');
181+
});
182+
183+
test('directory mode traverses into child when trailing slash entered', async () => {
184+
const result = prompts.path({
185+
message: 'foo',
186+
root: '/tmp/',
187+
initialValue: '/tmp',
188+
directory: true,
189+
input,
190+
output,
191+
});
192+
193+
input.emit('keypress', '/', { name: '/' });
194+
input.emit('keypress', '', { name: 'return' });
195+
196+
const value = await result;
197+
198+
expect(value).toBe('/tmp/foo');
199+
});
200+
201+
test('directory mode can navigate from initial directory to child directory', async () => {
202+
const result = prompts.path({
203+
message: 'foo',
204+
root: '/tmp/',
205+
initialValue: '/tmp/',
206+
directory: true,
207+
input,
208+
output,
209+
});
210+
211+
input.emit('keypress', 'f', { name: 'f' });
212+
input.emit('keypress', '', { name: 'return' });
213+
214+
const value = await result;
215+
216+
expect(value).toBe('/tmp/foo');
217+
});
218+
166219
test('default mode allows selecting files', async () => {
167220
const result = prompts.path({
168221
message: 'foo',

0 commit comments

Comments
 (0)