use std::sync::Arc;
use {
reovim_driver_annotation::{
Annotation, AnnotationContext, AnnotationKind, AnnotationPayload, AnnotationSource,
AnnotationTarget, LineNumberMode,
},
reovim_kernel::api::v1::BufferId,
};
static LINE_NUMBER_KIND: std::sync::LazyLock<AnnotationKind> =
std::sync::LazyLock::new(|| AnnotationKind::new("line_number"));
#[derive(Debug, Clone)]
pub struct LineNumberSource {
mode: LineNumberMode,
}
impl LineNumberSource {
#[must_use]
pub const fn new(mode: LineNumberMode) -> Self {
Self { mode }
}
#[must_use]
pub const fn absolute() -> Self {
Self::new(LineNumberMode::Absolute)
}
#[must_use]
pub const fn relative() -> Self {
Self::new(LineNumberMode::Relative)
}
#[must_use]
pub const fn hybrid() -> Self {
Self::new(LineNumberMode::Hybrid)
}
#[must_use]
pub const fn mode(&self) -> LineNumberMode {
self.mode
}
pub const fn set_mode(&mut self, mode: LineNumberMode) {
self.mode = mode;
}
}
impl AnnotationSource for LineNumberSource {
fn id(&self) -> &'static str {
"builtin.line_number"
}
fn provides(&self) -> Vec<AnnotationKind> {
vec![LINE_NUMBER_KIND.clone()]
}
#[cfg_attr(coverage_nightly, coverage(off))]
fn annotations(
&self,
_buffer_id: BufferId,
range: std::ops::Range<usize>,
context: &AnnotationContext,
) -> Vec<Annotation> {
let mode = context.line_number_mode().unwrap_or(self.mode);
if mode == LineNumberMode::None {
return vec![];
}
range
.map(|line| {
let number = match mode {
LineNumberMode::None => unreachable!(),
LineNumberMode::Absolute => line + 1,
LineNumberMode::Hybrid if line == context.cursor_line => line + 1,
LineNumberMode::Relative | LineNumberMode::Hybrid => {
line.abs_diff(context.cursor_line)
}
};
Annotation {
kind: LINE_NUMBER_KIND.clone(),
target: AnnotationTarget::Line(line),
priority: 0,
payload: AnnotationPayload::Number(number),
}
})
.collect()
}
fn has_annotations(&self, _buffer_id: BufferId) -> bool {
self.mode != LineNumberMode::None
}
}
#[must_use]
pub fn create_line_number_source(mode: LineNumberMode) -> Arc<LineNumberSource> {
Arc::new(LineNumberSource::new(mode))
}
#[cfg(test)]
#[path = "tests.rs"]
mod tests;