use gpui::{App, FontWeight, Global, Hsla, SharedString};
use theme::Theme;
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct Marks {
entries: Vec<Entry>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct Entry {
pub(crate) name: SharedString,
pub(crate) delimiter: SharedString,
}
impl Marks {
pub fn new() -> Self {
Self::default()
}
pub fn with(
mut self,
name: impl Into<SharedString>,
delimiter: impl Into<SharedString>,
) -> Self {
let (name, delimiter) = (name.into(), delimiter.into());
let taken = self
.entries
.iter()
.any(|entry| entry.name == name || entry.delimiter == delimiter);
if !delimiter.is_empty() && !taken {
self.entries.push(Entry { name, delimiter });
}
self
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn names(&self) -> impl Iterator<Item = &SharedString> {
self.entries.iter().map(|entry| &entry.name)
}
pub fn delimiter(&self, name: &str) -> Option<&str> {
self.entries
.iter()
.find(|entry| entry.name == name)
.map(|entry| entry.delimiter.as_ref())
}
pub(crate) fn sorted(&self) -> Vec<&Entry> {
let mut entries: Vec<&Entry> = self.entries.iter().collect();
entries.sort_by_key(|entry| std::cmp::Reverse(entry.delimiter.len()));
entries
}
pub(crate) fn index(&self, ix: usize) -> Option<&Entry> {
self.entries.get(ix)
}
pub(crate) fn position(&self, entry: &Entry) -> Option<usize> {
self.entries.iter().position(|row| row == entry)
}
pub fn of(cx: &App) -> Self {
cx.try_global::<Installed>()
.map_or_else(Self::default, |installed| installed.0.clone())
}
}
struct Installed(Marks);
impl Global for Installed {}
pub fn set_marks(cx: &mut App, marks: Marks) {
cx.set_global(Installed(marks));
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct MarkPaint {
pub color: Option<Hsla>,
pub background: Option<Hsla>,
pub weight: Option<FontWeight>,
pub italic: bool,
pub underline: bool,
pub strikethrough: bool,
}
pub type Painter = fn(name: &str, theme: &Theme) -> Option<MarkPaint>;
struct InstalledPaint(Painter);
impl Global for InstalledPaint {}
pub fn set_mark_paint(cx: &mut App, paint: Painter) {
cx.set_global(InstalledPaint(paint));
}
pub(crate) fn paint_of(cx: &App, name: &str, theme: &Theme) -> Option<MarkPaint> {
(cx.try_global::<InstalledPaint>()?.0)(name, theme)
}