Skip to content

Commit

Permalink
completions: Add colors based on the LSP item kind
Browse files Browse the repository at this point in the history
  • Loading branch information
danyspin97 committed Apr 14, 2023
1 parent bb27542 commit 7979f6a
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 60 deletions.
10 changes: 5 additions & 5 deletions helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use helix_view::{
keyboard::KeyCode,
tree,
view::View,
Document, DocumentId, Editor, ViewId,
Document, DocumentId, Editor, Theme, ViewId,
};

use anyhow::{anyhow, bail, ensure, Context as _};
Expand Down Expand Up @@ -1989,7 +1989,7 @@ fn global_search(cx: &mut Context) {
impl ui::menu::Item for FileResult {
type Data = Option<PathBuf>;

fn format(&self, current_path: &Self::Data) -> Row {
fn format(&self, current_path: &Self::Data, _theme: Option<&Theme>) -> Row {
let relative_path = helix_core::path::get_relative_path(&self.path)
.to_string_lossy()
.into_owned();
Expand Down Expand Up @@ -2459,7 +2459,7 @@ fn buffer_picker(cx: &mut Context) {
impl ui::menu::Item for BufferMeta {
type Data = ();

fn format(&self, _data: &Self::Data) -> Row {
fn format(&self, _data: &Self::Data, _theme: Option<&Theme>) -> Row {
let path = self
.path
.as_deref()
Expand Down Expand Up @@ -2523,7 +2523,7 @@ fn jumplist_picker(cx: &mut Context) {
impl ui::menu::Item for JumpMeta {
type Data = ();

fn format(&self, _data: &Self::Data) -> Row {
fn format(&self, _data: &Self::Data, _theme: Option<&Theme>) -> Row {
let path = self
.path
.as_deref()
Expand Down Expand Up @@ -2603,7 +2603,7 @@ fn jumplist_picker(cx: &mut Context) {
impl ui::menu::Item for MappableCommand {
type Data = ReverseKeymap;

fn format(&self, keymap: &Self::Data) -> Row {
fn format(&self, keymap: &Self::Data, _theme: Option<&Theme>) -> Row {
let fmt_binding = |bindings: &Vec<Vec<KeyEvent>>| -> String {
bindings.iter().fold(String::new(), |mut acc, bind| {
if !acc.is_empty() {
Expand Down
8 changes: 4 additions & 4 deletions helix-term/src/commands/dap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use dap::{StackFrame, Thread, ThreadStates};
use helix_core::syntax::{DebugArgumentValue, DebugConfigCompletion, DebugTemplate};
use helix_dap::{self as dap, Client};
use helix_lsp::block_on;
use helix_view::editor::Breakpoint;
use helix_view::{editor::Breakpoint, Theme};

use serde_json::{to_value, Value};
use tokio_stream::wrappers::UnboundedReceiverStream;
Expand All @@ -25,23 +25,23 @@ use helix_view::handlers::dap::{breakpoints_changed, jump_to_stack_frame, select
impl ui::menu::Item for StackFrame {
type Data = ();

fn format(&self, _data: &Self::Data) -> Row {
fn format(&self, _data: &Self::Data, _theme: Option<&Theme>) -> Row {
self.name.as_str().into() // TODO: include thread_states in the label
}
}

impl ui::menu::Item for DebugTemplate {
type Data = ();

fn format(&self, _data: &Self::Data) -> Row {
fn format(&self, _data: &Self::Data, _theme: Option<&Theme>) -> Row {
self.name.as_str().into()
}
}

impl ui::menu::Item for Thread {
type Data = ThreadStates;

fn format(&self, thread_states: &Self::Data) -> Row {
fn format(&self, thread_states: &Self::Data, _theme: Option<&Theme>) -> Row {
format!(
"{} ({})",
self.name,
Expand Down
12 changes: 6 additions & 6 deletions helix-term/src/commands/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use helix_view::{
document::{DocumentInlayHints, DocumentInlayHintsId, Mode},
editor::Action,
theme::Style,
Document, View,
Document, Theme, View,
};

use crate::{
Expand Down Expand Up @@ -57,7 +57,7 @@ impl ui::menu::Item for lsp::Location {
/// Current working directory.
type Data = PathBuf;

fn format(&self, cwdir: &Self::Data) -> Row {
fn format(&self, cwdir: &Self::Data, _theme: Option<&Theme>) -> Row {
// The preallocation here will overallocate a few characters since it will account for the
// URL's scheme, which is not used most of the time since that scheme will be "file://".
// Those extra chars will be used to avoid allocating when writing the line number (in the
Expand Down Expand Up @@ -91,7 +91,7 @@ impl ui::menu::Item for lsp::SymbolInformation {
/// Path to currently focussed document
type Data = Option<lsp::Url>;

fn format(&self, current_doc_path: &Self::Data) -> Row {
fn format(&self, current_doc_path: &Self::Data, _theme: Option<&Theme>) -> Row {
if current_doc_path.as_ref() == Some(&self.location.uri) {
self.name.as_str().into()
} else {
Expand Down Expand Up @@ -121,7 +121,7 @@ struct PickerDiagnostic {
impl ui::menu::Item for PickerDiagnostic {
type Data = (DiagnosticStyles, DiagnosticsFormat);

fn format(&self, (styles, format): &Self::Data) -> Row {
fn format(&self, (styles, format): &Self::Data, _theme: Option<&Theme>) -> Row {
let mut style = self
.diag
.severity
Expand Down Expand Up @@ -476,7 +476,7 @@ pub fn workspace_diagnostics_picker(cx: &mut Context) {

impl ui::menu::Item for lsp::CodeActionOrCommand {
type Data = ();
fn format(&self, _data: &Self::Data) -> Row {
fn format(&self, _data: &Self::Data, _theme: Option<&Theme>) -> Row {
match self {
lsp::CodeActionOrCommand::CodeAction(action) => action.title.as_str().into(),
lsp::CodeActionOrCommand::Command(command) => command.title.as_str().into(),
Expand Down Expand Up @@ -672,7 +672,7 @@ pub fn code_action(cx: &mut Context) {

impl ui::menu::Item for lsp::Command {
type Data = ();
fn format(&self, _data: &Self::Data) -> Row {
fn format(&self, _data: &Self::Data, _theme: Option<&Theme>) -> Row {
self.title.as_str().into()
}
}
Expand Down
83 changes: 49 additions & 34 deletions helix-term/src/ui/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use helix_view::{
document::SavePoint,
editor::CompleteAction,
theme::{Modifier, Style},
ViewId,
Theme, ViewId,
};
use tui::{buffer::Buffer as Surface, text::Span};

Expand Down Expand Up @@ -33,11 +33,57 @@ impl menu::Item for CompletionItem {
.into()
}

fn format(&self, _data: &Self::Data) -> menu::Row {
// fn label(&self, _data: &Self::Data) -> Spans {
// self.label.as_str().into()
// }

fn format(&self, _data: &Self::Data, theme: Option<&Theme>) -> menu::Row {
let (lsp_type_label, style) = match self.kind {
Some(lsp::CompletionItemKind::TEXT) => ("text", Some("ui.text")),
Some(lsp::CompletionItemKind::METHOD) => ("method", Some("function.method")),
Some(lsp::CompletionItemKind::FUNCTION) => ("function", Some("function")),
Some(lsp::CompletionItemKind::CONSTRUCTOR) => ("constructor", Some("constructor")),
Some(lsp::CompletionItemKind::FIELD) => ("field", Some("variable.other.member")),
Some(lsp::CompletionItemKind::VARIABLE) => ("variable", Some("variable")),
Some(lsp::CompletionItemKind::CLASS) => ("class", Some("type")),
Some(lsp::CompletionItemKind::INTERFACE) => ("interface", Some("type")),
Some(lsp::CompletionItemKind::MODULE) => ("module", Some("module")),
Some(lsp::CompletionItemKind::PROPERTY) => ("property", Some("attributes")),
Some(lsp::CompletionItemKind::UNIT) => ("unit", Some("constant")),
Some(lsp::CompletionItemKind::VALUE) => ("value", Some("string")),
Some(lsp::CompletionItemKind::ENUM) => ("enum", Some("type")),
Some(lsp::CompletionItemKind::KEYWORD) => ("keyword", Some("keyword")),
Some(lsp::CompletionItemKind::SNIPPET) => ("snippet", None),
Some(lsp::CompletionItemKind::COLOR) => ("color", None),
Some(lsp::CompletionItemKind::FILE) => ("file", None),
Some(lsp::CompletionItemKind::REFERENCE) => ("reference", None),
Some(lsp::CompletionItemKind::FOLDER) => ("folder", None),
Some(lsp::CompletionItemKind::ENUM_MEMBER) => {
("enum_member", Some("type.enum.variant"))
}
Some(lsp::CompletionItemKind::CONSTANT) => ("constant", Some("constant")),
Some(lsp::CompletionItemKind::STRUCT) => ("struct", Some("type")),
Some(lsp::CompletionItemKind::EVENT) => ("event", None),
Some(lsp::CompletionItemKind::OPERATOR) => ("operator", Some("operator")),
Some(lsp::CompletionItemKind::TYPE_PARAMETER) => {
("type_param", Some("function.parameter"))
}
Some(kind) => unimplemented!("{:?}", kind),
None => ("", None),
};
let mut lsp_type_style = theme
.zip(style)
.map(|(theme, style)| theme.get(style))
.unwrap_or_default()
.remove_modifier(Modifier::all())
.add_modifier(Modifier::ITALIC);
lsp_type_style.bg = None;

let deprecated = self.deprecated.unwrap_or_default()
|| self.tags.as_ref().map_or(false, |tags| {
tags.contains(&lsp::CompletionItemTag::DEPRECATED)
});

menu::Row::new(vec![
menu::Cell::from(Span::styled(
self.label.as_str(),
Expand All @@ -47,38 +93,7 @@ impl menu::Item for CompletionItem {
Style::default()
},
)),
menu::Cell::from(match self.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(kind) => {
log::error!("Received unknown completion item kind: {:?}", kind);
""
}
None => "",
}),
menu::Cell::from(lsp_type_label).style(lsp_type_style),
// self.detail.as_deref().unwrap_or("")
// self.label_details
// .as_ref()
Expand Down
16 changes: 8 additions & 8 deletions helix-term/src/ui/menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@ pub use tui::widgets::{Cell, Row};
use fuzzy_matcher::skim::SkimMatcherV2 as Matcher;
use fuzzy_matcher::FuzzyMatcher;

use helix_view::{graphics::Rect, Editor};
use helix_view::{graphics::Rect, Editor, Theme};
use tui::layout::Constraint;

pub trait Item {
/// Additional editor state that is used for label calculation.
type Data;

fn format(&self, data: &Self::Data) -> Row;
fn format(&self, data: &Self::Data, _theme: Option<&Theme>) -> Row;

fn sort_text(&self, data: &Self::Data) -> Cow<str> {
let label: String = self.format(data).cell_text().collect();
let label: String = self.format(data, None).cell_text().collect();
label.into()
}

fn filter_text(&self, data: &Self::Data) -> Cow<str> {
let label: String = self.format(data).cell_text().collect();
let label: String = self.format(data, None).cell_text().collect();
label.into()
}
}
Expand All @@ -35,7 +35,7 @@ impl Item for PathBuf {
/// Root prefix to strip.
type Data = PathBuf;

fn format(&self, root_path: &Self::Data) -> Row {
fn format(&self, root_path: &Self::Data, _theme: Option<&Theme>) -> Row {
self.strip_prefix(root_path)
.unwrap_or(self)
.to_string_lossy()
Expand Down Expand Up @@ -142,10 +142,10 @@ impl<T: Item> Menu<T> {
let n = self
.options
.first()
.map(|option| option.format(&self.editor_data).cells.len())
.map(|option| option.format(&self.editor_data, None).cells.len())
.unwrap_or_default();
let max_lens = self.options.iter().fold(vec![0; n], |mut acc, option| {
let row = option.format(&self.editor_data);
let row = option.format(&self.editor_data, None);
// maintain max for each column
for (acc, cell) in acc.iter_mut().zip(row.cells.iter()) {
let width = cell.content.width();
Expand Down Expand Up @@ -331,7 +331,7 @@ impl<T: Item + 'static> Component for Menu<T> {

let rows = options
.iter()
.map(|option| option.format(&self.editor_data));
.map(|option| option.format(&self.editor_data, Some(theme)));
let table = Table::new(rows)
.style(style)
.highlight_style(selected)
Expand Down
6 changes: 3 additions & 3 deletions helix-term/src/ui/picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,10 +485,10 @@ impl<T: Item> Picker<T> {
let n = self
.options
.first()
.map(|option| option.format(&self.editor_data).cells.len())
.map(|option| option.format(&self.editor_data, None).cells.len())
.unwrap_or_default();
let max_lens = self.options.iter().fold(vec![0; n], |mut acc, option| {
let row = option.format(&self.editor_data);
let row = option.format(&self.editor_data, None);
// maintain max for each column
for (acc, cell) in acc.iter_mut().zip(row.cells.iter()) {
let width = cell.content.width();
Expand Down Expand Up @@ -779,7 +779,7 @@ impl<T: Item + 'static> Component for Picker<T> {
.skip(offset)
.take(rows as usize)
.map(|pmatch| &self.options[pmatch.index])
.map(|option| option.format(&self.editor_data))
.map(|option| option.format(&self.editor_data, None))
.map(|mut row| {
const TEMP_CELL_SEP: &str = " ";

Expand Down

0 comments on commit 7979f6a

Please sign in to comment.