lattice_ai/pi/
commands.rs1use lattice_agent::parse_no_args;
10use lattice_grammar::command::LatencyClass;
11use lattice_grammar::effect::Effect;
12use lattice_grammar::registry::{CommandRegistry, ExCommandSpec, SurfaceForm};
13use std::sync::Arc;
14
15use crate::pi::modes::PiMode;
16
17pub fn register_pi_ex_commands(registry: &mut CommandRegistry) {
19 registry.register_ex_command(
20 "pi",
21 "Launch the pi coding agent (pi.dev) in a terminal buffer, with \
22 pi-mode activated. Requires the `pi` CLI to be installed \
23 (curl -fsSL https://pi.dev/install.sh | sh).",
24 ExCommandSpec {
25 latency_class: LatencyClass::Reflex,
26 accepts_bang: false,
27 accepts_range: false,
28 parse_args: Arc::new(parse_no_args),
29 apply: Arc::new(|_ctx| {
30 Ok(Effect::SpawnTerminal {
31 cwd: None,
34 cmd_line: Some("pi".to_string()),
35 env: vec![],
36 activate_minor: Some(PiMode::mode_id().as_str().to_string()),
37 })
38 }),
39 args_schema: vec![],
40 surface_form: SurfaceForm::Keyword,
41 },
42 );
43}
44
45#[cfg(test)]
46mod tests {
47 #![allow(clippy::unwrap_used, clippy::panic)]
48 use super::*;
49 use lattice_grammar::args::Args;
50 use lattice_grammar::registry::ExCommandContext;
51 use lattice_grammar::{CancellationToken, Count, Register};
52
53 fn ctx() -> ExCommandContext {
54 ExCommandContext {
55 bang: false,
56 args: Args::None,
57 range: None,
58 register: Register::default(),
59 count: Count::default(),
60 buffer_id: lattice_core::BufferId::default(),
61 cursor: Default::default(),
68 buffer: Default::default(),
69 path: None,
70 syntax: None,
71 cancel: CancellationToken::new(),
72 }
73 }
74
75 #[test]
78 fn pi_spawns_terminal_and_activates_mode() {
79 let mut registry = CommandRegistry::new();
80 register_pi_ex_commands(&mut registry);
81 let id = registry.id_by_name("pi").expect("`:pi` registered");
82 let spec = registry.ex_command_spec(id).expect("spec present");
83 match (spec.apply)(&ctx()).expect("apply ok") {
84 Effect::SpawnTerminal {
85 cmd_line,
86 activate_minor,
87 ..
88 } => {
89 assert_eq!(cmd_line.as_deref(), Some("pi"));
90 assert_eq!(activate_minor.as_deref(), Some("pi-mode"));
91 }
92 other => panic!("expected SpawnTerminal, got {other:?}"),
93 }
94 }
95}