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