Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Colors for items in the completion menu #12299

Merged
merged 30 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
a0a622d
feat: show color boxes in color completion
nik-rev Dec 19, 2024
2b0c425
feat: larger boxess
nik-rev Dec 19, 2024
565c981
refactor: no longer need so many `.into()`
nik-rev Dec 19, 2024
22259e3
refactor: better variable naming
nik-rev Dec 19, 2024
f1281b1
perf: do not use unnecessary `clone`
nik-rev Dec 19, 2024
b7f7e25
feat: do not add unnecessary custom method
nik-rev Dec 19, 2024
fbbb045
refactor: do not use extra dependency
nik-rev Dec 19, 2024
3097c7e
feat: remove dependency
nik-rev Dec 19, 2024
d991979
refactor: use an array of ranges
nik-rev Dec 19, 2024
495adf7
refactor: extract into a `from_hex` method on Color
nik-rev Dec 19, 2024
73286a1
refactor: do not return early
nik-rev Dec 19, 2024
1a2b616
feat: use "color" text for accessibility next to a small colored cube
nik-rev Dec 19, 2024
662b6d3
refactor: rename variable for consistency
nik-rev Dec 19, 2024
fc54f2e
fix: "color" for items with documentation but a hex value which canno…
nik-rev Dec 19, 2024
aed0f8d
refactor: remove extra variable assignment
nik-rev Dec 19, 2024
6617f12
docs: add doc for from_hex
nik-rev Dec 19, 2024
b00cac3
docs: use `unwrap` in example to extract from Option
nik-rev Dec 19, 2024
0e7b392
docs: place in the correct position
nik-rev Dec 19, 2024
8e17b74
refactor: better variable naming
nik-rev Dec 19, 2024
1cc2235
docs: use Color in doc test
nik-rev Dec 19, 2024
530748d
docs: missing semicolon
nik-rev Dec 19, 2024
c2e24a4
feat: reject a set of invalid inputs for Color::from_hex
nik-rev Dec 19, 2024
f29f336
feat: resolve merge conflicts
nik-rev Dec 19, 2024
3d8dc15
perf: avoid unnecessary string allocation
nik-rev Dec 19, 2024
52ce26c
refactor: `kind` is `Spans`
nik-rev Dec 19, 2024
8bfff23
fix: remove unnecessary log statement
nik-rev Dec 19, 2024
e55e886
docs: distinction between "color" and "hex color"
nik-rev Dec 19, 2024
98e408f
refactor: use .into() instead of explicit Spans::raw
nik-rev Dec 20, 2024
cebdc59
style - simplify option handling
the-mikedavis Dec 20, 2024
e25fcfc
style - replace use with qualified path
the-mikedavis Dec 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 62 additions & 43 deletions helix-term/src/ui/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ use helix_view::{
document::SavePoint,
editor::CompleteAction,
handlers::lsp::SignatureHelpInvoked,
theme::{Modifier, Style},
theme::{Color, Modifier, Style},
ViewId,
};
use tui::{buffer::Buffer as Surface, text::Span};
use tui::{
buffer::Buffer as Surface,
text::{Span, Spans},
};

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

Expand Down Expand Up @@ -64,53 +67,69 @@ impl menu::Item for CompletionItem {

let kind = match self {
CompletionItem::Lsp(LspCompletionItem { item, .. }) => match item.kind {
Some(lsp::CompletionItemKind::TEXT) => "text",
Some(lsp::CompletionItemKind::METHOD) => "method",
Some(lsp::CompletionItemKind::FUNCTION) => "function",
Some(lsp::CompletionItemKind::CONSTRUCTOR) => "constructor",
Some(lsp::CompletionItemKind::FIELD) => "field",
Some(lsp::CompletionItemKind::VARIABLE) => "variable",
Some(lsp::CompletionItemKind::CLASS) => "class",
Some(lsp::CompletionItemKind::INTERFACE) => "interface",
Some(lsp::CompletionItemKind::MODULE) => "module",
Some(lsp::CompletionItemKind::PROPERTY) => "property",
Some(lsp::CompletionItemKind::UNIT) => "unit",
Some(lsp::CompletionItemKind::VALUE) => "value",
Some(lsp::CompletionItemKind::ENUM) => "enum",
Some(lsp::CompletionItemKind::KEYWORD) => "keyword",
Some(lsp::CompletionItemKind::SNIPPET) => "snippet",
Some(lsp::CompletionItemKind::COLOR) => "color",
Some(lsp::CompletionItemKind::FILE) => "file",
Some(lsp::CompletionItemKind::REFERENCE) => "reference",
Some(lsp::CompletionItemKind::FOLDER) => "folder",
Some(lsp::CompletionItemKind::ENUM_MEMBER) => "enum_member",
Some(lsp::CompletionItemKind::CONSTANT) => "constant",
Some(lsp::CompletionItemKind::STRUCT) => "struct",
Some(lsp::CompletionItemKind::EVENT) => "event",
Some(lsp::CompletionItemKind::OPERATOR) => "operator",
Some(lsp::CompletionItemKind::TYPE_PARAMETER) => "type_param",
Some(lsp::CompletionItemKind::TEXT) => "text".into(),
Some(lsp::CompletionItemKind::METHOD) => "method".into(),
Some(lsp::CompletionItemKind::FUNCTION) => "function".into(),
Some(lsp::CompletionItemKind::CONSTRUCTOR) => "constructor".into(),
Some(lsp::CompletionItemKind::FIELD) => "field".into(),
Some(lsp::CompletionItemKind::VARIABLE) => "variable".into(),
Some(lsp::CompletionItemKind::CLASS) => "class".into(),
Some(lsp::CompletionItemKind::INTERFACE) => "interface".into(),
Some(lsp::CompletionItemKind::MODULE) => "module".into(),
Some(lsp::CompletionItemKind::PROPERTY) => "property".into(),
Some(lsp::CompletionItemKind::UNIT) => "unit".into(),
Some(lsp::CompletionItemKind::VALUE) => "value".into(),
Some(lsp::CompletionItemKind::ENUM) => "enum".into(),
Some(lsp::CompletionItemKind::KEYWORD) => "keyword".into(),
Some(lsp::CompletionItemKind::SNIPPET) => "snippet".into(),
Some(lsp::CompletionItemKind::COLOR) => item
.documentation
.as_ref()
.and_then(|docs| {
let text = match docs {
lsp::Documentation::String(text) => text,
lsp::Documentation::MarkupContent(lsp::MarkupContent {
value, ..
}) => value,
};
Color::from_hex(text)
})
.map_or("color".into(), |color| {
Spans::from(vec![
Span::raw("color "),
Span::styled("■", Style::default().fg(color)),
])
}),
Some(lsp::CompletionItemKind::FILE) => "file".into(),
Some(lsp::CompletionItemKind::REFERENCE) => "reference".into(),
Some(lsp::CompletionItemKind::FOLDER) => "folder".into(),
Some(lsp::CompletionItemKind::ENUM_MEMBER) => "enum_member".into(),
Some(lsp::CompletionItemKind::CONSTANT) => "constant".into(),
Some(lsp::CompletionItemKind::STRUCT) => "struct".into(),
Some(lsp::CompletionItemKind::EVENT) => "event".into(),
Some(lsp::CompletionItemKind::OPERATOR) => "operator".into(),
Some(lsp::CompletionItemKind::TYPE_PARAMETER) => "type_param".into(),
Some(kind) => {
log::error!("Received unknown completion item kind: {:?}", kind);
""
"".into()
}
None => "",
None => "".into(),
},
CompletionItem::Other(core::CompletionItem { kind, .. }) => kind,
CompletionItem::Other(core::CompletionItem { kind, .. }) => kind.as_ref().into(),
};

menu::Row::new([
menu::Cell::from(Span::styled(
label,
if deprecated {
Style::default().add_modifier(Modifier::CROSSED_OUT)
} else if kind == "folder" {
*dir_style
} else {
Style::default()
},
)),
menu::Cell::from(kind),
])
let label = Span::styled(
label,
if deprecated {
Style::default().add_modifier(Modifier::CROSSED_OUT)
} else if kind.0[0].content == "folder" {
*dir_style
} else {
Style::default()
},
);

menu::Row::new([menu::Cell::from(label), menu::Cell::from(kind)])
}
}

Expand Down
25 changes: 25 additions & 0 deletions helix-view/src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,31 @@ pub enum Color {
Indexed(u8),
}

impl Color {
/// Creates a `Color` from a hex string
///
/// # Examples
///
/// ```rust
/// use helix_view::theme::Color;
///
/// let color1 = Color::from_hex("#c0ffee").unwrap();
/// let color2 = Color::Rgb(192, 255, 238);
///
/// assert_eq!(color1, color2);
/// ```
pub fn from_hex(hex: &str) -> Option<Self> {
if !(hex.starts_with('#') && hex.len() == 7) {
return None;
}
match [1..=2, 3..=4, 5..=6].map(|i| hex.get(i).and_then(|c| u8::from_str_radix(c, 16).ok()))
nik-rev marked this conversation as resolved.
Show resolved Hide resolved
{
[Some(r), Some(g), Some(b)] => Some(Self::Rgb(r, g, b)),
_ => None,
}
}
}

#[cfg(feature = "term")]
impl From<Color> for crossterm::style::Color {
fn from(color: Color) -> Self {
Expand Down
Loading