Skip to content

Commit 5f31765

Browse files
committed
feat: improve script menu with unified sorting for favorites and recent scripts
1 parent 18f2ce0 commit 5f31765

File tree

1 file changed

+34
-50
lines changed

1 file changed

+34
-50
lines changed

src/ui.js

Lines changed: 34 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -214,77 +214,61 @@ export function showWarning(message) {
214214
export async function showScriptMenuWithHistory(scripts, descriptions = {}, backgroundProcesses = [], recentScripts = [], favorites = []) {
215215
const scriptEntries = Object.entries(scripts);
216216
const choices = [];
217-
const favoriteScripts = favorites.map(f => f.script);
218-
219-
// Favorites section
220-
if (favorites.length > 0) {
221-
choices.push(new Separator(chalk.hex(COLORS.accent)(' ★ Favorites')));
222-
223-
for (const fav of favorites) {
224-
if (scripts[fav.script]) {
225-
choices.push({
226-
name: `${chalk.hex(COLORS.accent)('★')} ${chalk.hex(getScriptColor(fav.script)).bold(fav.script.padEnd(14))} ${chalk.hex(COLORS.muted)('→')} ${chalk.hex(COLORS.muted)(scripts[fav.script])}`,
227-
value: fav.script,
228-
});
229-
}
230-
}
231-
}
232217

233-
// Recent scripts section (exclude favorites)
234-
const recentNotFavorite = recentScripts.filter(r => !favoriteScripts.includes(r.script));
235-
if (recentNotFavorite.length > 0) {
236-
choices.push(new Separator(chalk.hex(COLORS.muted)(' ↻ Recent')));
237-
238-
for (const recent of recentNotFavorite) {
239-
if (scripts[recent.script]) {
240-
choices.push({
241-
name: `${chalk.hex(COLORS.muted)('↻')} ${chalk.hex(getScriptColor(recent.script)).bold(recent.script.padEnd(14))} ${chalk.hex(COLORS.muted)('→')} ${chalk.hex(COLORS.muted)(scripts[recent.script])}`,
242-
value: recent.script,
243-
});
244-
}
218+
const favoriteNames = new Set(favorites.map(f => f.script));
219+
const recentNames = new Set(recentScripts.map(r => r.script));
220+
221+
// Sort: favorites first, then recent (non-favorite), then alphabetical
222+
const sortedScripts = scriptEntries.sort(([a], [b]) => {
223+
const aFav = favoriteNames.has(a);
224+
const bFav = favoriteNames.has(b);
225+
const aRecent = recentNames.has(a) && !aFav;
226+
const bRecent = recentNames.has(b) && !bFav;
227+
228+
if (aFav && !bFav) return -1;
229+
if (!aFav && bFav) return 1;
230+
if (aRecent && !bRecent) return -1;
231+
if (!aRecent && bRecent) return 1;
232+
return a.localeCompare(b);
233+
});
234+
235+
// Single unified list
236+
for (const [name, command] of sortedScripts) {
237+
const desc = descriptions[name];
238+
const descText = desc ? ` ${chalk.hex(COLORS.muted).italic(`# ${desc}`)}` : '';
239+
240+
let icon = ' ';
241+
if (favoriteNames.has(name)) {
242+
icon = chalk.hex(COLORS.accent)('★ ');
243+
} else if (recentNames.has(name)) {
244+
icon = chalk.hex(COLORS.muted)('↻ ');
245245
}
246-
}
247246

248-
// All scripts section header
249-
if (favorites.length > 0 || recentNotFavorite.length > 0) {
250-
choices.push(new Separator(chalk.hex(COLORS.muted)(' All Scripts')));
247+
choices.push({
248+
name: `${icon}${chalk.hex(getScriptColor(name)).bold(name.padEnd(14))} ${chalk.hex(COLORS.muted)('→')} ${chalk.hex(COLORS.muted)(command)}${descText}`,
249+
value: name,
250+
});
251251
}
252252

253-
// All scripts
254-
choices.push(
255-
...scriptEntries.map(([name, command]) => {
256-
const desc = descriptions[name];
257-
const descText = desc ? ` ${chalk.hex(COLORS.muted).italic(`# ${desc}`)}` : '';
258-
const starIcon = favoriteScripts.includes(name) ? chalk.hex(COLORS.accent)('★ ') : ' ';
259-
return {
260-
name: `${starIcon}${chalk.hex(getScriptColor(name)).bold(name.padEnd(14))} ${chalk.hex(COLORS.muted)('→')} ${chalk.hex(COLORS.muted)(command)}${descText}`,
261-
value: name,
262-
};
263-
})
264-
);
265-
266253
// Background processes
267-
choices.push(new Separator(chalk.hex(COLORS.muted)('─'.repeat(40))));
268-
269254
if (backgroundProcesses.length > 0) {
255+
choices.push(new Separator(chalk.hex(COLORS.muted)('─'.repeat(40))));
270256
for (const proc of backgroundProcesses) {
271257
choices.push({
272258
name: `${chalk.hex(COLORS.secondary)('⚡')} ${chalk.hex(COLORS.accent)(proc.name.padEnd(14))} ${chalk.hex(COLORS.muted)(`PID: ${proc.pid}`)}`,
273259
value: { type: 'background', ...proc },
274260
});
275261
}
276-
choices.push(new Separator(chalk.hex(COLORS.muted)('─'.repeat(40))));
277262
}
278263

264+
choices.push(new Separator(chalk.hex(COLORS.muted)('─'.repeat(40))));
279265
choices.push({ name: chalk.hex(COLORS.danger)('Exit'), value: 'exit' });
280266

281-
const answer = await select({
267+
return await select({
282268
message: 'Select script to run:',
283269
choices,
284270
loop: true,
285271
});
286-
287-
return answer;
288272
}
289273

290274
export async function showWorkspaceMenu(workspaces, rootProjectName) {

0 commit comments

Comments
 (0)