Skip to content

Commit f13cb76

Browse files
authored
chore: Minor CLI polish. (#784)
Aligns the interactive vp command text with the new text we decided on yesterday + changes the formatting of errors coming from Vite Task: <img width="880" height="736" alt="CleanShot 2026-03-12 at 09 36 11@2x" src="https://github.com/user-attachments/assets/ecaf6039-daf0-407c-81f4-795819e110d9" />
1 parent 05f175f commit f13cb76

File tree

7 files changed

+69
-9
lines changed

7 files changed

+69
-9
lines changed

crates/vite_global_cli/src/command_picker.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,7 @@ fn render_picker(
304304
let pad = if vite_shared::header::is_warp_terminal() { " " } else { "" };
305305
let max_width = usize::from(columns).saturating_sub(4 + pad.len());
306306
let viewport_end = (viewport_start + viewport_size).min(filtered_indices.len());
307-
let instruction = truncate_line(
308-
&format!("Select a command (↑/↓, Enter to run, Esc to cancel): {query}"),
309-
max_width,
310-
);
307+
let instruction = truncate_line(&picker_instruction(query), max_width);
311308

312309
execute!(stdout, cursor::MoveTo(0, 0), terminal::Clear(ClearType::All),)?;
313310
if vite_shared::header::is_warp_terminal() {
@@ -440,6 +437,10 @@ fn render_picker(
440437
stdout.flush()
441438
}
442439

440+
fn picker_instruction(query: &str) -> String {
441+
format!("Select a command (↑/↓, Enter to run, type to search): {query}")
442+
}
443+
443444
fn compute_viewport_size(
444445
terminal_rows: usize,
445446
total_commands: usize,
@@ -552,7 +553,7 @@ fn filtered_command_indices(query: &str, command_order: &[usize]) -> Vec<usize>
552553
mod tests {
553554
use super::{
554555
COMMANDS, align_viewport, compute_viewport_size, default_command_order,
555-
filtered_command_indices, selected_command_parts,
556+
filtered_command_indices, picker_instruction, selected_command_parts,
556557
};
557558

558559
#[test]
@@ -670,4 +671,12 @@ mod tests {
670671
assert_eq!(help.label, "help");
671672
assert_eq!(help.summary, "View all commands and details");
672673
}
674+
675+
#[test]
676+
fn picker_instruction_mentions_search() {
677+
assert_eq!(
678+
picker_instruction(""),
679+
"Select a command (↑/↓, Enter to run, type to search): "
680+
);
681+
}
673682
}

packages/cli/binding/src/lib.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ mod package_manager;
1818
#[allow(dead_code)]
1919
mod utils;
2020

21-
use std::{collections::HashMap, ffi::OsStr, sync::Arc};
21+
use std::{collections::HashMap, error::Error as StdError, ffi::OsStr, fmt::Write as _, sync::Arc};
2222

2323
use napi::{anyhow, bindgen_prelude::*, threadsafe_function::ThreadsafeFunction};
2424
use napi_derive::napi;
@@ -111,6 +111,18 @@ fn create_vite_config_resolver(
111111
})
112112
}
113113

114+
fn format_error_message(error: &(dyn StdError + 'static)) -> String {
115+
let mut message = error.to_string();
116+
let mut source = error.source();
117+
118+
while let Some(current) = source {
119+
let _ = write!(message, "\n* {current}");
120+
source = current.source();
121+
}
122+
123+
message
124+
}
125+
114126
/// Main entry point for the CLI, called from JavaScript.
115127
///
116128
/// This is an async function that spawns a new thread for the non-Send async code
@@ -180,7 +192,7 @@ pub async fn run(options: CliOptions) -> Result<i32> {
180192
vite_error::Error::UserCancelled => Ok(130),
181193
_ => {
182194
tracing::error!("Rust error: {:?}", e);
183-
Err(anyhow::Error::from(e).into())
195+
Err(napi::Error::from_reason(format_error_message(&e)))
184196
}
185197
},
186198
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "run-task-command-conflict-test",
3+
"private": true,
4+
"scripts": {
5+
"build": "echo 'build from package.json'"
6+
}
7+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
> # Test that conflicting package.json and vite.config.ts task commands render cleanly
2+
[1]> vp run build
3+
error: Failed to load task graph
4+
* Failed to resolve task config for task run-task-command-conflict-test#build
5+
* Both package.json script and vite.config.* task define commands for the task
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"commands": [
3+
"# Test that conflicting package.json and vite.config.ts task commands render cleanly",
4+
"vp run build"
5+
]
6+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default {
2+
run: {
3+
tasks: {
4+
build: {
5+
command: "echo 'build from vite.config.ts'",
6+
},
7+
},
8+
},
9+
};

packages/cli/src/bin.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,19 @@ import { pack } from './resolve-pack.js';
2121
import { test } from './resolve-test.js';
2222
import { resolveUniversalViteConfig } from './resolve-vite-config.js';
2323
import { vite } from './resolve-vite.js';
24-
import { accent, log } from './utils/terminal.js';
24+
import { accent, errorMsg, log } from './utils/terminal.js';
25+
26+
function getErrorMessage(err: unknown): string {
27+
if (err instanceof Error) {
28+
return err.message;
29+
}
30+
31+
if (typeof err === 'object' && err && 'message' in err && typeof err.message === 'string') {
32+
return err.message;
33+
}
34+
35+
return String(err);
36+
}
2537

2638
// Parse command line arguments
2739
let args = process.argv.slice(2);
@@ -113,7 +125,7 @@ if (command === 'create') {
113125

114126
process.exit(finalExitCode);
115127
} catch (err) {
116-
console.error('[Vite+] run error:', err);
128+
errorMsg(getErrorMessage(err));
117129
process.exit(1);
118130
}
119131
}

0 commit comments

Comments
 (0)