fix(prompts): code review fixes

This commit is contained in:
Davor Racić 2026-05-16 22:38:50 +02:00
parent 2a81fbb7fa
commit ef888c7b28
1 changed files with 25 additions and 10 deletions

View File

@ -11,6 +11,7 @@ let _clack = null;
let _clackCore = null; let _clackCore = null;
let _picocolors = null; let _picocolors = null;
const fs = require('node:fs'); const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path'); const path = require('node:path');
/** /**
@ -581,6 +582,15 @@ function hasPathSeparator(value) {
return value.endsWith('/') || value.endsWith('\\'); return value.endsWith('/') || value.endsWith('\\');
} }
function expandHome(input) {
if (!input) return input;
if (input === '~') return os.homedir();
if (input.startsWith('~/') || input.startsWith('~\\')) {
return path.join(os.homedir(), input.slice(2));
}
return input;
}
function toDirectoryOption(value, label = value, synthetic = false) { function toDirectoryOption(value, label = value, synthetic = false) {
return { value, label, synthetic }; return { value, label, synthetic };
} }
@ -596,14 +606,15 @@ function isExistingDirectory(value) {
function listDirectoryOptions(input, options) { function listDirectoryOptions(input, options) {
const cwd = options.cwd || process.cwd(); const cwd = options.cwd || process.cwd();
const rawInput = input.trim(); const rawInput = input.trim();
const resolvedInput = rawInput ? path.resolve(cwd, rawInput) : cwd; const expandedInput = expandHome(rawInput);
const browseDir = const trailingSep = hasPathSeparator(rawInput) || hasPathSeparator(expandedInput);
rawInput && !hasPathSeparator(rawInput) && !isExistingDirectory(resolvedInput) ? path.dirname(resolvedInput) : resolvedInput; const resolvedInput = expandedInput ? path.resolve(cwd, expandedInput) : cwd;
const prefix = rawInput && browseDir !== resolvedInput ? path.basename(resolvedInput).toLowerCase() : ''; const browseDir = expandedInput && !trailingSep && !isExistingDirectory(resolvedInput) ? path.dirname(resolvedInput) : resolvedInput;
const prefix = expandedInput && browseDir !== resolvedInput ? path.basename(resolvedInput).toLowerCase() : '';
const results = []; const results = [];
if (!hasPathSeparator(rawInput) && isExistingDirectory(resolvedInput)) { if (!trailingSep && isExistingDirectory(resolvedInput)) {
results.push(toDirectoryOption(resolvedInput)); results.push(toDirectoryOption(resolvedInput, `. (use this directory)`));
} }
if (isExistingDirectory(browseDir)) { if (isExistingDirectory(browseDir)) {
@ -622,9 +633,9 @@ function listDirectoryOptions(input, options) {
} }
const validation = options.validate?.(rawInput); const validation = options.validate?.(rawInput);
const hasMatchingOption = results.some((option) => option.value === rawInput || option.value === resolvedInput); const hasMatchingOption = results.some((option) => option.value === resolvedInput);
if (rawInput && !validation && !hasMatchingOption) { if (expandedInput && !validation && !hasMatchingOption) {
results.unshift(toDirectoryOption(rawInput, `Create/use: ${rawInput}`, true)); results.unshift(toDirectoryOption(resolvedInput, `Create/use: ${resolvedInput}`, true));
} }
return results; return results;
@ -680,8 +691,12 @@ async function directory(options) {
}, },
}); });
const hasSetUserInput = typeof prompt._setUserInput === 'function';
const hasClearUserInput = typeof prompt._clearUserInput === 'function';
prompt.on('key', (_, key) => { prompt.on('key', (_, key) => {
if (key?.name !== 'tab') return; if (key?.name !== 'tab') return;
if (!hasSetUserInput) return; // @clack/core API surface changed — skip Tab silently.
const currentInput = prompt.userInput; const currentInput = prompt.userInput;
const isContinuingCycle = tabCompletion.lastValue && currentInput === tabCompletion.lastValue; const isContinuingCycle = tabCompletion.lastValue && currentInput === tabCompletion.lastValue;
const completionOptions = isContinuingCycle ? tabCompletion.options : prompt.filteredOptions.filter((option) => !option.synthetic); const completionOptions = isContinuingCycle ? tabCompletion.options : prompt.filteredOptions.filter((option) => !option.synthetic);
@ -699,7 +714,7 @@ async function directory(options) {
if (!focusedOption) return; if (!focusedOption) return;
const completedValue = focusedOption.value; const completedValue = focusedOption.value;
tabCompletion.lastValue = completedValue; tabCompletion.lastValue = completedValue;
prompt._clearUserInput(); if (hasClearUserInput) prompt._clearUserInput();
prompt._setUserInput(completedValue, true); prompt._setUserInput(completedValue, true);
}); });