reovim_plugin_statusline/
lib.rs1pub mod command;
27pub mod context_section;
28pub mod section;
29pub mod state;
30
31use std::{any::TypeId, sync::Arc};
32
33use {
34 reovim_core::{
35 event_bus::{EventBus, EventResult},
36 plugin::{Plugin, PluginContext, PluginId, PluginStateRegistry},
37 },
38 reovim_plugin_context::CursorContextUpdated,
39};
40
41use {
42 command::{StatuslineSectionRegister, StatuslineSectionUnregister},
43 state::{CachedCursorContext, SharedStatuslineManager},
44};
45
46pub use {
48 command::StatuslineRefresh,
49 section::{SectionContent, SectionRenderContext, StatuslineSection},
50 state::StatuslineManagerHandle,
51};
52
53pub struct StatuslinePlugin {
57 manager: Arc<SharedStatuslineManager>,
58}
59
60impl Default for StatuslinePlugin {
61 fn default() -> Self {
62 Self::new()
63 }
64}
65
66impl StatuslinePlugin {
67 #[must_use]
69 pub fn new() -> Self {
70 Self {
71 manager: Arc::new(SharedStatuslineManager::new()),
72 }
73 }
74}
75
76impl Plugin for StatuslinePlugin {
77 fn id(&self) -> PluginId {
78 PluginId::new("reovim:statusline")
79 }
80
81 fn name(&self) -> &'static str {
82 "Statusline"
83 }
84
85 fn description(&self) -> &'static str {
86 "Extensible statusline with section-based API"
87 }
88
89 fn dependencies(&self) -> Vec<TypeId> {
90 vec![]
91 }
92
93 fn build(&self, ctx: &mut PluginContext) {
94 let _ = ctx.register_command(StatuslineRefresh);
96
97 tracing::debug!("StatuslinePlugin: registered commands");
98 }
99
100 fn init_state(&self, registry: &PluginStateRegistry) {
101 use reovim_core::plugin::StatuslineSectionProvider;
102
103 registry.register(Arc::clone(&self.manager));
105
106 registry.set_statusline_provider(
108 Arc::clone(&self.manager) as Arc<dyn StatuslineSectionProvider>
109 );
110
111 tracing::debug!("StatuslinePlugin: registered as statusline provider");
112 }
113
114 fn subscribe(&self, bus: &EventBus, _state: Arc<PluginStateRegistry>) {
115 use reovim_core::option::{
116 OptionCategory, OptionConstraint, OptionSpec, OptionValue, RegisterOption,
117 };
118
119 bus.emit(RegisterOption::new(
121 OptionSpec::new(
122 "context_breadcrumb_enabled",
123 "Show context breadcrumb in statusline",
124 OptionValue::Bool(true),
125 )
126 .with_category(OptionCategory::Display)
127 .with_section("Statusline")
128 .with_display_order(50),
129 ));
130
131 bus.emit(RegisterOption::new(
132 OptionSpec::new(
133 "context_separator",
134 "Context breadcrumb separator",
135 OptionValue::String(" > ".into()),
136 )
137 .with_category(OptionCategory::Display)
138 .with_section("Statusline")
139 .with_display_order(51),
140 ));
141
142 bus.emit(RegisterOption::new(
143 OptionSpec::new(
144 "context_max_items",
145 "Maximum breadcrumb items",
146 OptionValue::Integer(4),
147 )
148 .with_category(OptionCategory::Display)
149 .with_section("Statusline")
150 .with_display_order(52)
151 .with_constraint(OptionConstraint::range(1, 10)),
152 ));
153
154 bus.emit(StatuslineSectionRegister {
156 section: context_section::create_context_section(),
157 });
158
159 let manager = Arc::clone(&self.manager);
161 bus.subscribe::<StatuslineSectionRegister, _>(100, move |event, ctx| {
162 manager.register_section(event.section.clone());
163 ctx.request_render();
164 EventResult::Handled
165 });
166
167 let manager = Arc::clone(&self.manager);
169 bus.subscribe::<StatuslineSectionUnregister, _>(100, move |event, ctx| {
170 manager.unregister_section(event.id);
171 ctx.request_render();
172 EventResult::Handled
173 });
174
175 let _manager = Arc::clone(&self.manager);
177 bus.subscribe::<StatuslineRefresh, _>(100, move |_event, ctx| {
178 ctx.request_render();
179 EventResult::Handled
180 });
181
182 let manager = Arc::clone(&self.manager);
184 bus.subscribe::<CursorContextUpdated, _>(100, move |event, ctx| {
185 manager.set_cached_cursor_context(CachedCursorContext {
187 buffer_id: event.buffer_id,
188 line: event.line,
189 col: event.col,
190 context: event.context.clone(),
191 });
192
193 ctx.request_render();
195
196 tracing::trace!(
197 buffer_id = event.buffer_id,
198 line = event.line,
199 col = event.col,
200 has_context = event.context.is_some(),
201 "StatuslinePlugin: received CursorContextUpdated"
202 );
203
204 EventResult::Handled
205 });
206
207 tracing::debug!("StatuslinePlugin: subscribed to events");
208 }
209}