Skip to content
Merged
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
20 changes: 20 additions & 0 deletions crates/cli/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17984,6 +17984,26 @@ mod tests {
server.abort();
}

#[tokio::test]
async fn session_picker_ctrl_k_kills_to_end_of_line() {
let (mut app, _dir, server) = session_picker_app().await;
app.open_session_picker(SessionPickerPurpose::Switch);
picker_type(&mut app, "abcdef"); // cursor at 6, query "abcdef"
app.handle_session_picker_key(KeyEvent::new(KeyCode::Char('a'), KeyModifiers::CONTROL));
app.handle_session_picker_key(KeyEvent::new(KeyCode::Char('f'), KeyModifiers::CONTROL));
app.handle_session_picker_key(KeyEvent::new(KeyCode::Char('f'), KeyModifiers::CONTROL));
assert_eq!(app.session_picker.as_ref().unwrap().cursor, 2);
app.handle_session_picker_key(KeyEvent::new(KeyCode::Char('k'), KeyModifiers::CONTROL));
assert_eq!(app.session_picker.as_ref().unwrap().query, "ab");
// The cursor was already at (the new) end; it doesn't move.
assert_eq!(app.session_picker.as_ref().unwrap().cursor, 2);
// Killing again at the end of the line is a no-op.
app.handle_session_picker_key(KeyEvent::new(KeyCode::Char('k'), KeyModifiers::CONTROL));
assert_eq!(app.session_picker.as_ref().unwrap().query, "ab");
assert_eq!(app.session_picker.as_ref().unwrap().cursor, 2);
server.abort();
}

#[tokio::test]
async fn session_picker_open_with_no_sessions_is_noop() {
let (mut app, _dir, server) = empty_app().await;
Expand Down
12 changes: 12 additions & 0 deletions crates/cli/src/app/session_picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,17 @@ impl App {
}
}

/// `C-k`: kill from the cursor to the end of the query. The cursor itself
/// doesn't move — it's already at the (now shorter) end of the query.
fn session_picker_kill_to_end(&mut self) {
if let Some(dialog) = self.session_picker.as_mut() {
let pos = byte_pos(&dialog.query, dialog.cursor);
dialog.query.truncate(pos);
dialog.cursor = dialog.cursor.min(dialog.query.chars().count());
}
self.session_picker_reset_selection();
}

/// Snap the highlight back to the top match. Called after the effective
/// query changes (typing/backspace) so navigation resumes from the best hit.
fn session_picker_reset_selection(&mut self) {
Expand Down Expand Up @@ -593,6 +604,7 @@ impl App {
KeyCode::Char('b') if ctrl && !to_program => self.session_picker_move_cursor(-1),
KeyCode::Char('a') if ctrl && !to_program => self.session_picker_cursor_to_edge(false),
KeyCode::Char('e') if ctrl && !to_program => self.session_picker_cursor_to_edge(true),
KeyCode::Char('k') if ctrl && !to_program => self.session_picker_kill_to_end(),
KeyCode::Backspace if to_program => self.session_picker_program_backspace(),
KeyCode::Backspace => self.session_picker_backspace(),
KeyCode::Char(c) if !ctrl && !alt && !super_mod && to_program => {
Expand Down
Loading