gpui_component/input/lsp/
document_colors.rs1use std::ops::Range;
2
3use anyhow::Result;
4use gpui::{App, Context, Hsla, Task, Window};
5use lsp_types::ColorInformation;
6use ropey::Rope;
7
8use crate::input::{InputState, Lsp, RopeExt};
9
10pub trait DocumentColorProvider {
11 fn document_colors(
17 &self,
18 _text: &Rope,
19 window: &mut Window,
20 cx: &mut App,
21 ) -> Task<Result<Vec<ColorInformation>>>;
22}
23
24impl Lsp {
25 pub(crate) fn document_colors_for_range(
29 &self,
30 text: &Rope,
31 visible_range: &Range<usize>,
32 ) -> Vec<(Range<usize>, Hsla)> {
33 self.document_colors
34 .iter()
35 .filter_map(|(range, color)| {
36 if (range.start.line as usize) > visible_range.end
37 || (range.end.line as usize) < visible_range.start
38 {
39 return None;
40 }
41
42 let start = text.position_to_offset(&range.start);
43 let end = text.position_to_offset(&range.end);
44
45 Some((start..end, *color))
46 })
47 .collect()
48 }
49
50 pub(crate) fn update_document_colors(
51 &mut self,
52 text: &Rope,
53 window: &mut Window,
54 cx: &mut Context<InputState>,
55 ) {
56 let Some(provider) = self.document_color_provider.as_ref() else {
57 return;
58 };
59
60 let task = provider.document_colors(text, window, cx);
61 self._hover_task = cx.spawn_in(window, async move |editor, cx| {
62 let colors = task.await?;
63
64 editor.update(cx, |editor, cx| {
65 let mut document_colors: Vec<(lsp_types::Range, Hsla)> = colors
66 .iter()
67 .map(|info| {
68 let color = gpui::Rgba {
69 r: info.color.red,
70 g: info.color.green,
71 b: info.color.blue,
72 a: info.color.alpha,
73 }
74 .into();
75
76 (info.range, color)
77 })
78 .collect();
79 document_colors.sort_by_key(|(range, _)| range.start);
80
81 if document_colors == editor.lsp.document_colors {
82 return;
83 }
84 editor.lsp.document_colors = document_colors;
85 cx.notify();
86 })?;
87
88 Ok(())
89 });
90 }
91}