reovim_plugin_microscope/microscope/picker/mod.rs
1//! Picker trait and infrastructure
2//!
3//! This module provides the core picker infrastructure:
4//! - `Picker` trait for implementing custom pickers
5//! - `PickerContext` for picker operations
6//! - `MicroscopeAction` for actions on selection
7//! - `PickerRegistry` for dynamic picker registration
8//!
9//! Actual picker implementations are in the separate `reovim-plugin-pickers` crate.
10
11pub mod registry;
12
13pub use registry::PickerRegistry;
14
15use std::{future::Future, path::PathBuf, pin::Pin};
16
17use reovim_core::{command::CommandId, highlight::ThemeName};
18
19use super::{item::MicroscopeItem, state::PreviewContent};
20
21/// Buffer info passed from runtime for buffer picker
22#[derive(Debug, Clone)]
23pub struct BufferInfo {
24 /// Buffer ID
25 pub id: usize,
26 /// Buffer name/path
27 pub name: String,
28 /// Whether the buffer is modified
29 pub modified: bool,
30 /// Preview lines
31 pub preview_lines: Vec<String>,
32}
33
34/// Context for picker operations
35#[derive(Debug, Clone)]
36pub struct PickerContext {
37 /// Current search query
38 pub query: String,
39 /// Working directory
40 pub cwd: PathBuf,
41 /// Maximum items to fetch
42 pub max_items: usize,
43 /// Available buffers (for buffers picker)
44 pub buffers: Vec<BufferInfo>,
45}
46
47impl Default for PickerContext {
48 fn default() -> Self {
49 Self {
50 query: String::new(),
51 cwd: std::env::current_dir().unwrap_or_default(),
52 max_items: 1000,
53 buffers: Vec::new(),
54 }
55 }
56}
57
58/// Action to perform when an item is selected
59#[derive(Debug, Clone)]
60pub enum MicroscopeAction {
61 /// Open a file
62 OpenFile(PathBuf),
63 /// Switch to a buffer
64 SwitchBuffer(usize),
65 /// Execute a command
66 ExecuteCommand(CommandId),
67 /// Go to a specific location
68 GotoLocation {
69 path: PathBuf,
70 line: usize,
71 col: usize,
72 },
73 /// Show help for a tag
74 ShowHelp(String),
75 /// Apply a theme/colorscheme
76 ApplyTheme(ThemeName),
77 /// Switch to a configuration profile
78 SwitchProfile(String),
79 /// Close microscope without action
80 Close,
81 /// Do nothing
82 Nothing,
83}
84
85/// Trait for implementing microscope pickers
86///
87/// Pickers are responsible for:
88/// - Fetching items (files, buffers, commands, etc.)
89/// - Determining actions when an item is selected
90/// - Optionally providing preview content
91///
92/// # Example
93///
94/// ```ignore
95/// use reovim_plugin_microscope::{Picker, PickerContext, MicroscopeAction, MicroscopeItem};
96///
97/// pub struct MyPicker;
98///
99/// impl Picker for MyPicker {
100/// fn name(&self) -> &'static str { "my_picker" }
101/// fn title(&self) -> &'static str { "My Picker" }
102///
103/// fn fetch(&self, ctx: &PickerContext) -> Pin<Box<dyn Future<Output = Vec<MicroscopeItem>> + Send + '_>> {
104/// Box::pin(async { vec![] })
105/// }
106///
107/// fn on_select(&self, item: &MicroscopeItem) -> MicroscopeAction {
108/// MicroscopeAction::Nothing
109/// }
110/// }
111/// ```
112pub trait Picker: Send + Sync {
113 /// Unique identifier for this picker
114 fn name(&self) -> &'static str;
115
116 /// Human-readable title for the picker window
117 fn title(&self) -> &'static str;
118
119 /// Prompt string (shown before input)
120 fn prompt(&self) -> &'static str {
121 "> "
122 }
123
124 /// Fetch items asynchronously
125 fn fetch(
126 &self,
127 ctx: &PickerContext,
128 ) -> Pin<Box<dyn Future<Output = Vec<MicroscopeItem>> + Send + '_>>;
129
130 /// Handle selection of an item
131 fn on_select(&self, item: &MicroscopeItem) -> MicroscopeAction;
132
133 /// Optional: preview content for the selected item
134 fn preview(
135 &self,
136 _item: &MicroscopeItem,
137 ) -> Pin<Box<dyn Future<Output = Option<PreviewContent>> + Send + '_>> {
138 Box::pin(async { None })
139 }
140
141 /// Whether this picker supports live filtering vs full re-fetch
142 /// If true, the picker only needs to fetch once and nucleo handles filtering
143 /// If false, the picker needs to re-fetch on each query change (e.g., live grep)
144 fn supports_live_filter(&self) -> bool {
145 true
146 }
147}