feat: add support for commands in the Rust TUI (#935)
Introduces support for slash commands like in the TypeScript CLI. We do
not support the full set of commands yet, but the core abstraction is
there now.
In particular, we have a `SlashCommand` enum and due to thoughtful use
of the [strum](https://crates.io/crates/strum) crate, it requires
minimal boilerplate to add a new command to the list.
The key new piece of UI is `CommandPopup`, though the keyboard events
are still handled by `ChatComposer`. The behavior is roughly as follows:
* if the first character in the composer is `/`, the command popup is
displayed (if you really want to send a message to Codex that starts
with a `/`, simply put a space before the `/`)
* while the popup is displayed, up/down can be used to change the
selection of the popup
* if there is a selection, hitting tab completes the command, but does
not send it
* if there is a selection, hitting enter sends the command
* if the prefix of the composer matches a command, the command will be
visible in the popup so the user can see the description (commands could
take arguments, so additional text may appear after the command name
itself)
https://github.com/user-attachments/assets/39c3e6ee-eeb7-4ef7-a911-466d8184975f
Incidentally, Codex wrote almost all the code for this PR!
2025-05-14 12:55:49 -07:00
|
|
|
use ratatui::buffer::Buffer;
|
|
|
|
|
use ratatui::layout::Rect;
|
|
|
|
|
use ratatui::widgets::WidgetRef;
|
|
|
|
|
|
2025-08-06 21:23:09 -07:00
|
|
|
use super::popup_consts::MAX_POPUP_ROWS;
|
|
|
|
|
use super::scroll_state::ScrollState;
|
|
|
|
|
use super::selection_popup_common::GenericDisplayRow;
|
|
|
|
|
use super::selection_popup_common::render_rows;
|
feat: add support for commands in the Rust TUI (#935)
Introduces support for slash commands like in the TypeScript CLI. We do
not support the full set of commands yet, but the core abstraction is
there now.
In particular, we have a `SlashCommand` enum and due to thoughtful use
of the [strum](https://crates.io/crates/strum) crate, it requires
minimal boilerplate to add a new command to the list.
The key new piece of UI is `CommandPopup`, though the keyboard events
are still handled by `ChatComposer`. The behavior is roughly as follows:
* if the first character in the composer is `/`, the command popup is
displayed (if you really want to send a message to Codex that starts
with a `/`, simply put a space before the `/`)
* while the popup is displayed, up/down can be used to change the
selection of the popup
* if there is a selection, hitting tab completes the command, but does
not send it
* if there is a selection, hitting enter sends the command
* if the prefix of the composer matches a command, the command will be
visible in the popup so the user can see the description (commands could
take arguments, so additional text may appear after the command name
itself)
https://github.com/user-attachments/assets/39c3e6ee-eeb7-4ef7-a911-466d8184975f
Incidentally, Codex wrote almost all the code for this PR!
2025-05-14 12:55:49 -07:00
|
|
|
use crate::slash_command::SlashCommand;
|
|
|
|
|
use crate::slash_command::built_in_slash_commands;
|
2025-08-06 21:23:09 -07:00
|
|
|
use codex_common::fuzzy_match::fuzzy_match;
|
feat: add support for commands in the Rust TUI (#935)
Introduces support for slash commands like in the TypeScript CLI. We do
not support the full set of commands yet, but the core abstraction is
there now.
In particular, we have a `SlashCommand` enum and due to thoughtful use
of the [strum](https://crates.io/crates/strum) crate, it requires
minimal boilerplate to add a new command to the list.
The key new piece of UI is `CommandPopup`, though the keyboard events
are still handled by `ChatComposer`. The behavior is roughly as follows:
* if the first character in the composer is `/`, the command popup is
displayed (if you really want to send a message to Codex that starts
with a `/`, simply put a space before the `/`)
* while the popup is displayed, up/down can be used to change the
selection of the popup
* if there is a selection, hitting tab completes the command, but does
not send it
* if there is a selection, hitting enter sends the command
* if the prefix of the composer matches a command, the command will be
visible in the popup so the user can see the description (commands could
take arguments, so additional text may appear after the command name
itself)
https://github.com/user-attachments/assets/39c3e6ee-eeb7-4ef7-a911-466d8184975f
Incidentally, Codex wrote almost all the code for this PR!
2025-05-14 12:55:49 -07:00
|
|
|
|
|
|
|
|
pub(crate) struct CommandPopup {
|
|
|
|
|
command_filter: String,
|
2025-06-26 13:03:31 -07:00
|
|
|
all_commands: Vec<(&'static str, SlashCommand)>,
|
2025-08-06 21:23:09 -07:00
|
|
|
state: ScrollState,
|
feat: add support for commands in the Rust TUI (#935)
Introduces support for slash commands like in the TypeScript CLI. We do
not support the full set of commands yet, but the core abstraction is
there now.
In particular, we have a `SlashCommand` enum and due to thoughtful use
of the [strum](https://crates.io/crates/strum) crate, it requires
minimal boilerplate to add a new command to the list.
The key new piece of UI is `CommandPopup`, though the keyboard events
are still handled by `ChatComposer`. The behavior is roughly as follows:
* if the first character in the composer is `/`, the command popup is
displayed (if you really want to send a message to Codex that starts
with a `/`, simply put a space before the `/`)
* while the popup is displayed, up/down can be used to change the
selection of the popup
* if there is a selection, hitting tab completes the command, but does
not send it
* if there is a selection, hitting enter sends the command
* if the prefix of the composer matches a command, the command will be
visible in the popup so the user can see the description (commands could
take arguments, so additional text may appear after the command name
itself)
https://github.com/user-attachments/assets/39c3e6ee-eeb7-4ef7-a911-466d8184975f
Incidentally, Codex wrote almost all the code for this PR!
2025-05-14 12:55:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl CommandPopup {
|
|
|
|
|
pub(crate) fn new() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
command_filter: String::new(),
|
|
|
|
|
all_commands: built_in_slash_commands(),
|
2025-08-06 21:23:09 -07:00
|
|
|
state: ScrollState::new(),
|
feat: add support for commands in the Rust TUI (#935)
Introduces support for slash commands like in the TypeScript CLI. We do
not support the full set of commands yet, but the core abstraction is
there now.
In particular, we have a `SlashCommand` enum and due to thoughtful use
of the [strum](https://crates.io/crates/strum) crate, it requires
minimal boilerplate to add a new command to the list.
The key new piece of UI is `CommandPopup`, though the keyboard events
are still handled by `ChatComposer`. The behavior is roughly as follows:
* if the first character in the composer is `/`, the command popup is
displayed (if you really want to send a message to Codex that starts
with a `/`, simply put a space before the `/`)
* while the popup is displayed, up/down can be used to change the
selection of the popup
* if there is a selection, hitting tab completes the command, but does
not send it
* if there is a selection, hitting enter sends the command
* if the prefix of the composer matches a command, the command will be
visible in the popup so the user can see the description (commands could
take arguments, so additional text may appear after the command name
itself)
https://github.com/user-attachments/assets/39c3e6ee-eeb7-4ef7-a911-466d8184975f
Incidentally, Codex wrote almost all the code for this PR!
2025-05-14 12:55:49 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Update the filter string based on the current composer text. The text
|
|
|
|
|
/// passed in is expected to start with a leading '/'. Everything after the
|
|
|
|
|
/// *first* '/" on the *first* line becomes the active filter that is used
|
|
|
|
|
/// to narrow down the list of available commands.
|
|
|
|
|
pub(crate) fn on_composer_text_change(&mut self, text: String) {
|
|
|
|
|
let first_line = text.lines().next().unwrap_or("");
|
|
|
|
|
|
|
|
|
|
if let Some(stripped) = first_line.strip_prefix('/') {
|
|
|
|
|
// Extract the *first* token (sequence of non-whitespace
|
|
|
|
|
// characters) after the slash so that `/clear something` still
|
|
|
|
|
// shows the help for `/clear`.
|
|
|
|
|
let token = stripped.trim_start();
|
|
|
|
|
let cmd_token = token.split_whitespace().next().unwrap_or("");
|
|
|
|
|
|
|
|
|
|
// Update the filter keeping the original case (commands are all
|
|
|
|
|
// lower-case for now but this may change in the future).
|
|
|
|
|
self.command_filter = cmd_token.to_string();
|
|
|
|
|
} else {
|
|
|
|
|
// The composer no longer starts with '/'. Reset the filter so the
|
|
|
|
|
// popup shows the *full* command list if it is still displayed
|
|
|
|
|
// for some reason.
|
|
|
|
|
self.command_filter.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reset or clamp selected index based on new filtered list.
|
|
|
|
|
let matches_len = self.filtered_commands().len();
|
2025-08-06 21:23:09 -07:00
|
|
|
self.state.clamp_selection(matches_len);
|
|
|
|
|
self.state
|
|
|
|
|
.ensure_visible(matches_len, MAX_POPUP_ROWS.min(matches_len));
|
feat: add support for commands in the Rust TUI (#935)
Introduces support for slash commands like in the TypeScript CLI. We do
not support the full set of commands yet, but the core abstraction is
there now.
In particular, we have a `SlashCommand` enum and due to thoughtful use
of the [strum](https://crates.io/crates/strum) crate, it requires
minimal boilerplate to add a new command to the list.
The key new piece of UI is `CommandPopup`, though the keyboard events
are still handled by `ChatComposer`. The behavior is roughly as follows:
* if the first character in the composer is `/`, the command popup is
displayed (if you really want to send a message to Codex that starts
with a `/`, simply put a space before the `/`)
* while the popup is displayed, up/down can be used to change the
selection of the popup
* if there is a selection, hitting tab completes the command, but does
not send it
* if there is a selection, hitting enter sends the command
* if the prefix of the composer matches a command, the command will be
visible in the popup so the user can see the description (commands could
take arguments, so additional text may appear after the command name
itself)
https://github.com/user-attachments/assets/39c3e6ee-eeb7-4ef7-a911-466d8184975f
Incidentally, Codex wrote almost all the code for this PR!
2025-05-14 12:55:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Determine the preferred height of the popup. This is the number of
|
2025-08-06 21:23:09 -07:00
|
|
|
/// rows required to show at most MAX_POPUP_ROWS commands.
|
2025-07-30 17:06:55 -07:00
|
|
|
pub(crate) fn calculate_required_height(&self) -> u16 {
|
2025-07-31 00:43:21 -07:00
|
|
|
self.filtered_commands().len().clamp(1, MAX_POPUP_ROWS) as u16
|
feat: add support for commands in the Rust TUI (#935)
Introduces support for slash commands like in the TypeScript CLI. We do
not support the full set of commands yet, but the core abstraction is
there now.
In particular, we have a `SlashCommand` enum and due to thoughtful use
of the [strum](https://crates.io/crates/strum) crate, it requires
minimal boilerplate to add a new command to the list.
The key new piece of UI is `CommandPopup`, though the keyboard events
are still handled by `ChatComposer`. The behavior is roughly as follows:
* if the first character in the composer is `/`, the command popup is
displayed (if you really want to send a message to Codex that starts
with a `/`, simply put a space before the `/`)
* while the popup is displayed, up/down can be used to change the
selection of the popup
* if there is a selection, hitting tab completes the command, but does
not send it
* if there is a selection, hitting enter sends the command
* if the prefix of the composer matches a command, the command will be
visible in the popup so the user can see the description (commands could
take arguments, so additional text may appear after the command name
itself)
https://github.com/user-attachments/assets/39c3e6ee-eeb7-4ef7-a911-466d8184975f
Incidentally, Codex wrote almost all the code for this PR!
2025-05-14 12:55:49 -07:00
|
|
|
}
|
|
|
|
|
|
2025-08-06 21:23:09 -07:00
|
|
|
/// Compute fuzzy-filtered matches paired with optional highlight indices and score.
|
|
|
|
|
/// Sorted by ascending score, then by command name for stability.
|
|
|
|
|
fn filtered(&self) -> Vec<(&SlashCommand, Option<Vec<usize>>, i32)> {
|
|
|
|
|
let filter = self.command_filter.trim();
|
|
|
|
|
let mut out: Vec<(&SlashCommand, Option<Vec<usize>>, i32)> = Vec::new();
|
|
|
|
|
if filter.is_empty() {
|
|
|
|
|
for (_, cmd) in self.all_commands.iter() {
|
|
|
|
|
out.push((cmd, None, 0));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (_, cmd) in self.all_commands.iter() {
|
|
|
|
|
if let Some((indices, score)) = fuzzy_match(cmd.command(), filter) {
|
|
|
|
|
out.push((cmd, Some(indices), score));
|
feat: add support for commands in the Rust TUI (#935)
Introduces support for slash commands like in the TypeScript CLI. We do
not support the full set of commands yet, but the core abstraction is
there now.
In particular, we have a `SlashCommand` enum and due to thoughtful use
of the [strum](https://crates.io/crates/strum) crate, it requires
minimal boilerplate to add a new command to the list.
The key new piece of UI is `CommandPopup`, though the keyboard events
are still handled by `ChatComposer`. The behavior is roughly as follows:
* if the first character in the composer is `/`, the command popup is
displayed (if you really want to send a message to Codex that starts
with a `/`, simply put a space before the `/`)
* while the popup is displayed, up/down can be used to change the
selection of the popup
* if there is a selection, hitting tab completes the command, but does
not send it
* if there is a selection, hitting enter sends the command
* if the prefix of the composer matches a command, the command will be
visible in the popup so the user can see the description (commands could
take arguments, so additional text may appear after the command name
itself)
https://github.com/user-attachments/assets/39c3e6ee-eeb7-4ef7-a911-466d8184975f
Incidentally, Codex wrote almost all the code for this PR!
2025-05-14 12:55:49 -07:00
|
|
|
}
|
2025-08-06 21:23:09 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
out.sort_by(|a, b| a.2.cmp(&b.2).then_with(|| a.0.command().cmp(b.0.command())));
|
|
|
|
|
out
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn filtered_commands(&self) -> Vec<&SlashCommand> {
|
|
|
|
|
self.filtered().into_iter().map(|(c, _, _)| c).collect()
|
feat: add support for commands in the Rust TUI (#935)
Introduces support for slash commands like in the TypeScript CLI. We do
not support the full set of commands yet, but the core abstraction is
there now.
In particular, we have a `SlashCommand` enum and due to thoughtful use
of the [strum](https://crates.io/crates/strum) crate, it requires
minimal boilerplate to add a new command to the list.
The key new piece of UI is `CommandPopup`, though the keyboard events
are still handled by `ChatComposer`. The behavior is roughly as follows:
* if the first character in the composer is `/`, the command popup is
displayed (if you really want to send a message to Codex that starts
with a `/`, simply put a space before the `/`)
* while the popup is displayed, up/down can be used to change the
selection of the popup
* if there is a selection, hitting tab completes the command, but does
not send it
* if there is a selection, hitting enter sends the command
* if the prefix of the composer matches a command, the command will be
visible in the popup so the user can see the description (commands could
take arguments, so additional text may appear after the command name
itself)
https://github.com/user-attachments/assets/39c3e6ee-eeb7-4ef7-a911-466d8184975f
Incidentally, Codex wrote almost all the code for this PR!
2025-05-14 12:55:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Move the selection cursor one step up.
|
|
|
|
|
pub(crate) fn move_up(&mut self) {
|
2025-08-06 21:23:09 -07:00
|
|
|
let matches = self.filtered_commands();
|
|
|
|
|
let len = matches.len();
|
|
|
|
|
self.state.move_up_wrap(len);
|
|
|
|
|
self.state.ensure_visible(len, MAX_POPUP_ROWS.min(len));
|
feat: add support for commands in the Rust TUI (#935)
Introduces support for slash commands like in the TypeScript CLI. We do
not support the full set of commands yet, but the core abstraction is
there now.
In particular, we have a `SlashCommand` enum and due to thoughtful use
of the [strum](https://crates.io/crates/strum) crate, it requires
minimal boilerplate to add a new command to the list.
The key new piece of UI is `CommandPopup`, though the keyboard events
are still handled by `ChatComposer`. The behavior is roughly as follows:
* if the first character in the composer is `/`, the command popup is
displayed (if you really want to send a message to Codex that starts
with a `/`, simply put a space before the `/`)
* while the popup is displayed, up/down can be used to change the
selection of the popup
* if there is a selection, hitting tab completes the command, but does
not send it
* if there is a selection, hitting enter sends the command
* if the prefix of the composer matches a command, the command will be
visible in the popup so the user can see the description (commands could
take arguments, so additional text may appear after the command name
itself)
https://github.com/user-attachments/assets/39c3e6ee-eeb7-4ef7-a911-466d8184975f
Incidentally, Codex wrote almost all the code for this PR!
2025-05-14 12:55:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Move the selection cursor one step down.
|
|
|
|
|
pub(crate) fn move_down(&mut self) {
|
2025-08-06 21:23:09 -07:00
|
|
|
let matches = self.filtered_commands();
|
|
|
|
|
let matches_len = matches.len();
|
|
|
|
|
self.state.move_down_wrap(matches_len);
|
|
|
|
|
self.state
|
|
|
|
|
.ensure_visible(matches_len, MAX_POPUP_ROWS.min(matches_len));
|
feat: add support for commands in the Rust TUI (#935)
Introduces support for slash commands like in the TypeScript CLI. We do
not support the full set of commands yet, but the core abstraction is
there now.
In particular, we have a `SlashCommand` enum and due to thoughtful use
of the [strum](https://crates.io/crates/strum) crate, it requires
minimal boilerplate to add a new command to the list.
The key new piece of UI is `CommandPopup`, though the keyboard events
are still handled by `ChatComposer`. The behavior is roughly as follows:
* if the first character in the composer is `/`, the command popup is
displayed (if you really want to send a message to Codex that starts
with a `/`, simply put a space before the `/`)
* while the popup is displayed, up/down can be used to change the
selection of the popup
* if there is a selection, hitting tab completes the command, but does
not send it
* if there is a selection, hitting enter sends the command
* if the prefix of the composer matches a command, the command will be
visible in the popup so the user can see the description (commands could
take arguments, so additional text may appear after the command name
itself)
https://github.com/user-attachments/assets/39c3e6ee-eeb7-4ef7-a911-466d8184975f
Incidentally, Codex wrote almost all the code for this PR!
2025-05-14 12:55:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Return currently selected command, if any.
|
|
|
|
|
pub(crate) fn selected_command(&self) -> Option<&SlashCommand> {
|
|
|
|
|
let matches = self.filtered_commands();
|
2025-08-06 21:23:09 -07:00
|
|
|
self.state
|
|
|
|
|
.selected_idx
|
|
|
|
|
.and_then(|idx| matches.get(idx).copied())
|
feat: add support for commands in the Rust TUI (#935)
Introduces support for slash commands like in the TypeScript CLI. We do
not support the full set of commands yet, but the core abstraction is
there now.
In particular, we have a `SlashCommand` enum and due to thoughtful use
of the [strum](https://crates.io/crates/strum) crate, it requires
minimal boilerplate to add a new command to the list.
The key new piece of UI is `CommandPopup`, though the keyboard events
are still handled by `ChatComposer`. The behavior is roughly as follows:
* if the first character in the composer is `/`, the command popup is
displayed (if you really want to send a message to Codex that starts
with a `/`, simply put a space before the `/`)
* while the popup is displayed, up/down can be used to change the
selection of the popup
* if there is a selection, hitting tab completes the command, but does
not send it
* if there is a selection, hitting enter sends the command
* if the prefix of the composer matches a command, the command will be
visible in the popup so the user can see the description (commands could
take arguments, so additional text may appear after the command name
itself)
https://github.com/user-attachments/assets/39c3e6ee-eeb7-4ef7-a911-466d8184975f
Incidentally, Codex wrote almost all the code for this PR!
2025-05-14 12:55:49 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl WidgetRef for CommandPopup {
|
|
|
|
|
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
|
2025-08-06 21:23:09 -07:00
|
|
|
let matches = self.filtered();
|
|
|
|
|
let rows_all: Vec<GenericDisplayRow> = if matches.is_empty() {
|
|
|
|
|
Vec::new()
|
feat: add support for commands in the Rust TUI (#935)
Introduces support for slash commands like in the TypeScript CLI. We do
not support the full set of commands yet, but the core abstraction is
there now.
In particular, we have a `SlashCommand` enum and due to thoughtful use
of the [strum](https://crates.io/crates/strum) crate, it requires
minimal boilerplate to add a new command to the list.
The key new piece of UI is `CommandPopup`, though the keyboard events
are still handled by `ChatComposer`. The behavior is roughly as follows:
* if the first character in the composer is `/`, the command popup is
displayed (if you really want to send a message to Codex that starts
with a `/`, simply put a space before the `/`)
* while the popup is displayed, up/down can be used to change the
selection of the popup
* if there is a selection, hitting tab completes the command, but does
not send it
* if there is a selection, hitting enter sends the command
* if the prefix of the composer matches a command, the command will be
visible in the popup so the user can see the description (commands could
take arguments, so additional text may appear after the command name
itself)
https://github.com/user-attachments/assets/39c3e6ee-eeb7-4ef7-a911-466d8184975f
Incidentally, Codex wrote almost all the code for this PR!
2025-05-14 12:55:49 -07:00
|
|
|
} else {
|
2025-08-06 21:23:09 -07:00
|
|
|
matches
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|(cmd, indices, _)| GenericDisplayRow {
|
|
|
|
|
name: format!("/{}", cmd.command()),
|
|
|
|
|
match_indices: indices.map(|v| v.into_iter().map(|i| i + 1).collect()),
|
|
|
|
|
is_current: false,
|
|
|
|
|
description: Some(cmd.description().to_string()),
|
|
|
|
|
})
|
|
|
|
|
.collect()
|
|
|
|
|
};
|
|
|
|
|
render_rows(area, buf, &rows_all, &self.state, MAX_POPUP_ROWS);
|
feat: add support for commands in the Rust TUI (#935)
Introduces support for slash commands like in the TypeScript CLI. We do
not support the full set of commands yet, but the core abstraction is
there now.
In particular, we have a `SlashCommand` enum and due to thoughtful use
of the [strum](https://crates.io/crates/strum) crate, it requires
minimal boilerplate to add a new command to the list.
The key new piece of UI is `CommandPopup`, though the keyboard events
are still handled by `ChatComposer`. The behavior is roughly as follows:
* if the first character in the composer is `/`, the command popup is
displayed (if you really want to send a message to Codex that starts
with a `/`, simply put a space before the `/`)
* while the popup is displayed, up/down can be used to change the
selection of the popup
* if there is a selection, hitting tab completes the command, but does
not send it
* if there is a selection, hitting enter sends the command
* if the prefix of the composer matches a command, the command will be
visible in the popup so the user can see the description (commands could
take arguments, so additional text may appear after the command name
itself)
https://github.com/user-attachments/assets/39c3e6ee-eeb7-4ef7-a911-466d8184975f
Incidentally, Codex wrote almost all the code for this PR!
2025-05-14 12:55:49 -07:00
|
|
|
}
|
|
|
|
|
}
|
2025-08-06 09:10:23 -07:00
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn filter_includes_init_when_typing_prefix() {
|
|
|
|
|
let mut popup = CommandPopup::new();
|
|
|
|
|
// Simulate the composer line starting with '/in' so the popup filters
|
|
|
|
|
// matching commands by prefix.
|
|
|
|
|
popup.on_composer_text_change("/in".to_string());
|
|
|
|
|
|
|
|
|
|
// Access the filtered list via the selected command and ensure that
|
|
|
|
|
// one of the matches is the new "init" command.
|
|
|
|
|
let matches = popup.filtered_commands();
|
|
|
|
|
assert!(
|
|
|
|
|
matches.iter().any(|cmd| cmd.command() == "init"),
|
|
|
|
|
"expected '/init' to appear among filtered commands"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn selecting_init_by_exact_match() {
|
|
|
|
|
let mut popup = CommandPopup::new();
|
|
|
|
|
popup.on_composer_text_change("/init".to_string());
|
|
|
|
|
|
|
|
|
|
// When an exact match exists, the selected command should be that
|
|
|
|
|
// command by default.
|
|
|
|
|
let selected = popup.selected_command();
|
|
|
|
|
match selected {
|
|
|
|
|
Some(cmd) => assert_eq!(cmd.command(), "init"),
|
|
|
|
|
None => panic!("expected a selected command for exact match"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|