Publish harness and TUI open-source
initial sync from the monorepo
This commit is contained in:
commit
c68e39f604
2734 changed files with 1437016 additions and 0 deletions
132
crates/codegen/xai-grok-pager/src/slash/commands/find.rs
Normal file
132
crates/codegen/xai-grok-pager/src/slash/commands/find.rs
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
//! `/find` -- open an incremental search over the conversation scrollback.
|
||||
//!
|
||||
//! In simple mode a bare `/` goes to the prompt, so simple-mode users can't
|
||||
//! reach the vim `/` scrollback search. `/find` focuses the scrollback pane
|
||||
//! and opens the same search from either mode.
|
||||
|
||||
use crate::app::actions::Action;
|
||||
use crate::slash::command::{CommandExecCtx, CommandResult, SlashCommand};
|
||||
|
||||
/// Open scrollback search via `/find`.
|
||||
pub struct FindCommand;
|
||||
|
||||
impl SlashCommand for FindCommand {
|
||||
fn name(&self) -> &str {
|
||||
"find"
|
||||
}
|
||||
|
||||
fn description(&self) -> &str {
|
||||
"Search the conversation scrollback"
|
||||
}
|
||||
|
||||
fn session_scoped(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"/find [text]"
|
||||
}
|
||||
|
||||
fn takes_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn arg_placeholder(&self) -> Option<&str> {
|
||||
Some("[text]")
|
||||
}
|
||||
|
||||
/// Minimal mode has no interactive scrollback pane to search — the
|
||||
/// terminal's own search covers it (K7/§6.13). Gated off with a message.
|
||||
fn available_in_minimal(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn run(&self, _ctx: &mut CommandExecCtx, args: &str) -> CommandResult {
|
||||
// whitespace-only args open a blank search.
|
||||
let initial = args.trim();
|
||||
let query = (!initial.is_empty()).then(|| initial.to_string());
|
||||
CommandResult::Action(Action::OpenScrollbackSearch(query))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::acp::model_state::ModelState;
|
||||
|
||||
static DEFAULT_BUNDLE_STATE: crate::app::bundle::BundleState =
|
||||
crate::app::bundle::BundleState {
|
||||
has_cache: false,
|
||||
version: String::new(),
|
||||
personas: Vec::new(),
|
||||
roles: Vec::new(),
|
||||
agents: Vec::new(),
|
||||
skills: Vec::new(),
|
||||
persona_details: Vec::new(),
|
||||
role_details: Vec::new(),
|
||||
};
|
||||
|
||||
fn make_ctx(models: &ModelState) -> CommandExecCtx<'_> {
|
||||
CommandExecCtx {
|
||||
models,
|
||||
session_id: None,
|
||||
bundle_state: &DEFAULT_BUNDLE_STATE,
|
||||
screen_mode: crate::app::ScreenMode::Inline,
|
||||
pager_state: crate::settings::PagerLocalSnapshot::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_returns_open_scrollback_search_action() {
|
||||
let models = ModelState::default();
|
||||
let mut ctx = make_ctx(&models);
|
||||
let cmd = FindCommand;
|
||||
assert!(matches!(
|
||||
cmd.run(&mut ctx, ""),
|
||||
CommandResult::Action(Action::OpenScrollbackSearch(None))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_with_word_carries_it_as_initial_query() {
|
||||
let models = ModelState::default();
|
||||
let mut ctx = make_ctx(&models);
|
||||
let cmd = FindCommand;
|
||||
let CommandResult::Action(Action::OpenScrollbackSearch(query)) = cmd.run(&mut ctx, "foo")
|
||||
else {
|
||||
panic!("/find foo must open scrollback search");
|
||||
};
|
||||
assert_eq!(query.as_deref(), Some("foo"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_with_blank_args_carries_no_initial_query() {
|
||||
let models = ModelState::default();
|
||||
let mut ctx = make_ctx(&models);
|
||||
let cmd = FindCommand;
|
||||
// Both a bare `/find` and whitespace-only args open a blank search.
|
||||
for args in ["", " "] {
|
||||
assert!(matches!(
|
||||
cmd.run(&mut ctx, args),
|
||||
CommandResult::Action(Action::OpenScrollbackSearch(None))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_advertises_optional_text_arg() {
|
||||
// Pins the slash-arg contract so completion-accept appends a trailing
|
||||
// space and the `[text]` placeholder shows while typing; bare `/find`
|
||||
// stays valid (args not required).
|
||||
let cmd = FindCommand;
|
||||
assert!(cmd.takes_args());
|
||||
assert!(!cmd.args_required());
|
||||
assert_eq!(cmd.arg_placeholder(), Some("[text]"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn not_available_in_minimal() {
|
||||
// Native terminal search replaces in-app scrollback search in minimal.
|
||||
assert!(!FindCommand.available_in_minimal());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue