Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Changelog

- **Fixed** Cmd+Backspace on macOS now clears the interactive task selector's search query instead of inserting `u`.
- **Fixed** Vite+ diagnostics now display individual paths and working directories without Rust debug formatting such as quoted paths or escaped Windows backslashes ([#534](https://github.com/voidzero-dev/vite-task/pull/534)).
- **Fixed** Automatic file-access tracking now works inside the default Codex CLI and Claude Code sandboxes ([#562](https://github.com/voidzero-dev/vite-task/issues/562), [#563](https://github.com/voidzero-dev/vite-task/issues/563), [#576](https://github.com/voidzero-dev/vite-task/pull/576), [#569](https://github.com/voidzero-dev/vite-task/pull/569)).
- **Fixed** Broad workspace globs no longer discover and run package scripts inside `node_modules` ([#539](https://github.com/voidzero-dev/vite-task/pull/539)).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,33 @@ steps = [
] },
]

[[e2e]]
name = "interactive_ctrl_u_clears_query"
comment = """
Ctrl+U should clear the current query and reset the selection, while other control characters are ignored and Shift characters remain searchable.
"""
cwd = "packages/app"
steps = [
{ argv = [
"vt",
"run",
], interactions = [
{ "expect-milestone" = "task-select::0" },
{ "write" = "lin" },
{ "expect-milestone" = "task-select:lin:0" },
{ "write-key" = "ctrl-w" },
{ "write-key" = "backspace" },
{ "expect-milestone" = "task-select:li:0" },
{ "write" = "N" },
{ "expect-milestone" = "task-select:liN:0" },
{ "write-key" = "down" },
{ "expect-milestone" = "task-select:liN:1" },
{ "write-key" = "ctrl-u" },
{ "expect-milestone" = "task-select::0" },
{ "write-key" = "enter" },
] },
]

[[e2e]]
name = "recursive_without_task_errors"
comment = """
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# interactive_ctrl_u_clears_query

Ctrl+U should clear the current query and reset the selection, while other control characters are ignored and Shift characters remain searchable.

## `vt run`

**→ expect-milestone:** `task-select::0`

```
Select a task (↑/↓, Enter to run, type to search):

› build echo build app
lint echo lint app
test echo test app
lib (packages/lib)
build echo build lib
lint echo lint lib
test echo test lib
typecheck echo typecheck lib
task-select-test (workspace root)
check echo check root
clean echo clean root
deploy echo deploy root
(…5 more)
```

**← write:** `lin`

**→ expect-milestone:** `task-select:lin:0`

```
Select a task (↑/↓, Enter to run, type to search): lin

› lint echo lint app
lib (packages/lib)
lint echo lint lib
```

**← write-key:** `ctrl-w`

**← write-key:** `backspace`

**→ expect-milestone:** `task-select:li:0`

```
Select a task (↑/↓, Enter to run, type to search): li

› lint echo lint app
lib (packages/lib)
build echo build lib
lint echo lint lib
test echo test lib
typecheck echo typecheck lib
task-select-test (workspace root)
validate echo validate root
```

**← write:** `N`

**→ expect-milestone:** `task-select:liN:0`

```
Select a task (↑/↓, Enter to run, type to search): liN

› lint echo lint app
lib (packages/lib)
lint echo lint lib
```

**← write-key:** `down`

**→ expect-milestone:** `task-select:liN:1`

```
Select a task (↑/↓, Enter to run, type to search): liN

lint echo lint app
lib (packages/lib)
› lint echo lint lib
```

**← write-key:** `ctrl-u`

**→ expect-milestone:** `task-select::0`

```
Select a task (↑/↓, Enter to run, type to search):

› build echo build app
lint echo lint app
test echo test app
lib (packages/lib)
build echo build lib
lint echo lint lib
test echo test lib
typecheck echo typecheck lib
task-select-test (workspace root)
check echo check root
clean echo clean root
deploy echo deploy root
(…5 more)
```

**← write-key:** `enter`

```
Selected task: build
~/packages/app$ echo build app ⊘ cache disabled
build app
```
6 changes: 6 additions & 0 deletions crates/vt_bin/tests/e2e_snapshots/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ enum WriteKey {
Escape,
Backspace,
CtrlC,
CtrlU,
CtrlW,
}

impl WriteKey {
Expand All @@ -206,6 +208,8 @@ impl WriteKey {
Self::Escape => "escape",
Self::Backspace => "backspace",
Self::CtrlC => "ctrl-c",
Self::CtrlU => "ctrl-u",
Self::CtrlW => "ctrl-w",
}
}

Expand All @@ -217,6 +221,8 @@ impl WriteKey {
Self::Escape => b"\x1b",
Self::Backspace => b"\x7f",
Self::CtrlC => b"\x03",
Self::CtrlU => b"\x15",
Self::CtrlW => b"\x17",
}
}
}
Expand Down
20 changes: 19 additions & 1 deletion crates/vt_select/src/interactive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,10 @@ pub fn run(
cleanup(&mut out, &state)?;
return Ok(super::SelectResult::Cancelled);
}
KeyCode::Char('u') if modifiers == KeyModifiers::CONTROL => {
state.query.clear();
state.refilter();
}
KeyCode::Enter => {
let Some(idx) = state.selected_item_index() else {
continue;
Expand All @@ -532,7 +536,7 @@ pub fn run(
KeyCode::Down => {
state.move_down();
}
KeyCode::Char(c) => {
KeyCode::Char(c) if accepts_search_character(modifiers) => {
state.query.push(c);
state.refilter();
}
Expand All @@ -550,6 +554,12 @@ pub fn run(
}
}

fn accepts_search_character(modifiers: KeyModifiers) -> bool {
// Windows reports AltGr as Ctrl+Alt while preserving the printable character.
let modifiers = modifiers.difference(KeyModifiers::SHIFT);
modifiers.is_empty() || modifiers == (KeyModifiers::CONTROL | KeyModifiers::ALT)
}

/// Clear the widget output and restore cursor.
fn cleanup(stdout: &mut impl Write, state: &State<'_>) -> anyhow::Result<()> {
if state.rendered_lines > 0 {
Expand Down Expand Up @@ -672,6 +682,14 @@ mod tests {
strip_ansi(&String::from_utf8(buf).unwrap())
}

#[test]
fn search_character_modifiers_preserve_alt_gr_input() {
assert!(accepts_search_character(KeyModifiers::CONTROL | KeyModifiers::ALT));
assert!(accepts_search_character(
KeyModifiers::CONTROL | KeyModifiers::ALT | KeyModifiers::SHIFT
));
}

#[test]
fn truncates_long_description() {
let items = make_items(&[("build", "a really long command that exceeds the width limit")]);
Expand Down