Skip to content

Commit 5c6d1f4

Browse files
nik-revrongyi
authored andcommitted
Colors for items in the completion menu (helix-editor#12299)
1 parent ea4347c commit 5c6d1f4

File tree

2 files changed

+87
-43
lines changed

2 files changed

+87
-43
lines changed

helix-term/src/ui/completion.rs

Lines changed: 62 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ use helix_view::{
99
document::SavePoint,
1010
editor::CompleteAction,
1111
handlers::lsp::SignatureHelpInvoked,
12-
theme::{Modifier, Style},
12+
theme::{Color, Modifier, Style},
1313
ViewId,
1414
};
15-
use tui::{buffer::Buffer as Surface, text::Span};
15+
use tui::{
16+
buffer::Buffer as Surface,
17+
text::{Span, Spans},
18+
};
1619

1720
use std::{borrow::Cow, sync::Arc};
1821

@@ -64,53 +67,69 @@ impl menu::Item for CompletionItem {
6467

6568
let kind = match self {
6669
CompletionItem::Lsp(LspCompletionItem { item, .. }) => match item.kind {
67-
Some(lsp::CompletionItemKind::TEXT) => "text",
68-
Some(lsp::CompletionItemKind::METHOD) => "method",
69-
Some(lsp::CompletionItemKind::FUNCTION) => "function",
70-
Some(lsp::CompletionItemKind::CONSTRUCTOR) => "constructor",
71-
Some(lsp::CompletionItemKind::FIELD) => "field",
72-
Some(lsp::CompletionItemKind::VARIABLE) => "variable",
73-
Some(lsp::CompletionItemKind::CLASS) => "class",
74-
Some(lsp::CompletionItemKind::INTERFACE) => "interface",
75-
Some(lsp::CompletionItemKind::MODULE) => "module",
76-
Some(lsp::CompletionItemKind::PROPERTY) => "property",
77-
Some(lsp::CompletionItemKind::UNIT) => "unit",
78-
Some(lsp::CompletionItemKind::VALUE) => "value",
79-
Some(lsp::CompletionItemKind::ENUM) => "enum",
80-
Some(lsp::CompletionItemKind::KEYWORD) => "keyword",
81-
Some(lsp::CompletionItemKind::SNIPPET) => "snippet",
82-
Some(lsp::CompletionItemKind::COLOR) => "color",
83-
Some(lsp::CompletionItemKind::FILE) => "file",
84-
Some(lsp::CompletionItemKind::REFERENCE) => "reference",
85-
Some(lsp::CompletionItemKind::FOLDER) => "folder",
86-
Some(lsp::CompletionItemKind::ENUM_MEMBER) => "enum_member",
87-
Some(lsp::CompletionItemKind::CONSTANT) => "constant",
88-
Some(lsp::CompletionItemKind::STRUCT) => "struct",
89-
Some(lsp::CompletionItemKind::EVENT) => "event",
90-
Some(lsp::CompletionItemKind::OPERATOR) => "operator",
91-
Some(lsp::CompletionItemKind::TYPE_PARAMETER) => "type_param",
70+
Some(lsp::CompletionItemKind::TEXT) => "text".into(),
71+
Some(lsp::CompletionItemKind::METHOD) => "method".into(),
72+
Some(lsp::CompletionItemKind::FUNCTION) => "function".into(),
73+
Some(lsp::CompletionItemKind::CONSTRUCTOR) => "constructor".into(),
74+
Some(lsp::CompletionItemKind::FIELD) => "field".into(),
75+
Some(lsp::CompletionItemKind::VARIABLE) => "variable".into(),
76+
Some(lsp::CompletionItemKind::CLASS) => "class".into(),
77+
Some(lsp::CompletionItemKind::INTERFACE) => "interface".into(),
78+
Some(lsp::CompletionItemKind::MODULE) => "module".into(),
79+
Some(lsp::CompletionItemKind::PROPERTY) => "property".into(),
80+
Some(lsp::CompletionItemKind::UNIT) => "unit".into(),
81+
Some(lsp::CompletionItemKind::VALUE) => "value".into(),
82+
Some(lsp::CompletionItemKind::ENUM) => "enum".into(),
83+
Some(lsp::CompletionItemKind::KEYWORD) => "keyword".into(),
84+
Some(lsp::CompletionItemKind::SNIPPET) => "snippet".into(),
85+
Some(lsp::CompletionItemKind::COLOR) => item
86+
.documentation
87+
.as_ref()
88+
.and_then(|docs| {
89+
let text = match docs {
90+
lsp::Documentation::String(text) => text,
91+
lsp::Documentation::MarkupContent(lsp::MarkupContent {
92+
value, ..
93+
}) => value,
94+
};
95+
Color::from_hex(text)
96+
})
97+
.map_or("color".into(), |color| {
98+
Spans::from(vec![
99+
Span::raw("color "),
100+
Span::styled("■", Style::default().fg(color)),
101+
])
102+
}),
103+
Some(lsp::CompletionItemKind::FILE) => "file".into(),
104+
Some(lsp::CompletionItemKind::REFERENCE) => "reference".into(),
105+
Some(lsp::CompletionItemKind::FOLDER) => "folder".into(),
106+
Some(lsp::CompletionItemKind::ENUM_MEMBER) => "enum_member".into(),
107+
Some(lsp::CompletionItemKind::CONSTANT) => "constant".into(),
108+
Some(lsp::CompletionItemKind::STRUCT) => "struct".into(),
109+
Some(lsp::CompletionItemKind::EVENT) => "event".into(),
110+
Some(lsp::CompletionItemKind::OPERATOR) => "operator".into(),
111+
Some(lsp::CompletionItemKind::TYPE_PARAMETER) => "type_param".into(),
92112
Some(kind) => {
93113
log::error!("Received unknown completion item kind: {:?}", kind);
94-
""
114+
"".into()
95115
}
96-
None => "",
116+
None => "".into(),
97117
},
98-
CompletionItem::Other(core::CompletionItem { kind, .. }) => kind,
118+
CompletionItem::Other(core::CompletionItem { kind, .. }) => kind.as_ref().into(),
99119
};
100120

101-
menu::Row::new([
102-
menu::Cell::from(Span::styled(
103-
label,
104-
if deprecated {
105-
Style::default().add_modifier(Modifier::CROSSED_OUT)
106-
} else if kind == "folder" {
107-
*dir_style
108-
} else {
109-
Style::default()
110-
},
111-
)),
112-
menu::Cell::from(kind),
113-
])
121+
let label = Span::styled(
122+
label,
123+
if deprecated {
124+
Style::default().add_modifier(Modifier::CROSSED_OUT)
125+
} else if kind.0[0].content == "folder" {
126+
*dir_style
127+
} else {
128+
Style::default()
129+
},
130+
);
131+
132+
menu::Row::new([menu::Cell::from(label), menu::Cell::from(kind)])
114133
}
115134
}
116135

helix-view/src/graphics.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,31 @@ pub enum Color {
263263
Indexed(u8),
264264
}
265265

266+
impl Color {
267+
/// Creates a `Color` from a hex string
268+
///
269+
/// # Examples
270+
///
271+
/// ```rust
272+
/// use helix_view::theme::Color;
273+
///
274+
/// let color1 = Color::from_hex("#c0ffee").unwrap();
275+
/// let color2 = Color::Rgb(192, 255, 238);
276+
///
277+
/// assert_eq!(color1, color2);
278+
/// ```
279+
pub fn from_hex(hex: &str) -> Option<Self> {
280+
if !(hex.starts_with('#') && hex.len() == 7) {
281+
return None;
282+
}
283+
match [1..=2, 3..=4, 5..=6].map(|i| hex.get(i).and_then(|c| u8::from_str_radix(c, 16).ok()))
284+
{
285+
[Some(r), Some(g), Some(b)] => Some(Self::Rgb(r, g, b)),
286+
_ => None,
287+
}
288+
}
289+
}
290+
266291
#[cfg(feature = "term")]
267292
impl From<Color> for crossterm::style::Color {
268293
fn from(color: Color) -> Self {

0 commit comments

Comments
 (0)