Skip to content

Commit

Permalink
wip: icon colors
Browse files Browse the repository at this point in the history
  • Loading branch information
lazytanuki committed Nov 11, 2022
1 parent b05b4f2 commit f181f87
Show file tree
Hide file tree
Showing 7 changed files with 346 additions and 275 deletions.
65 changes: 33 additions & 32 deletions helix-term/src/commands/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use tui::text::{Span, Spans};
use super::{align_view, push_jump, Align, Context, Editor, Open};

use helix_core::{path, Selection};
use helix_view::icons::Icon;
use helix_view::{apply_transaction, document::Mode, editor::Action, theme::Style};

use crate::{
Expand Down Expand Up @@ -92,34 +93,34 @@ impl ui::menu::Item for lsp::SymbolInformation {
}
}

fn icon(&self, icons: &helix_view::icons::Icons) -> Option<char> {
fn icon<'a>(&self, icons: &'a helix_view::icons::Icons) -> Option<&'a Icon> {
match self.kind {
SymbolKind::FILE => Some(icons.symbol_kind.file),
SymbolKind::MODULE => Some(icons.symbol_kind.module),
SymbolKind::NAMESPACE => Some(icons.symbol_kind.namespace),
SymbolKind::PACKAGE => Some(icons.symbol_kind.package),
SymbolKind::CLASS => Some(icons.symbol_kind.class),
SymbolKind::METHOD => Some(icons.symbol_kind.method),
SymbolKind::PROPERTY => Some(icons.symbol_kind.property),
SymbolKind::FIELD => Some(icons.symbol_kind.field),
SymbolKind::CONSTRUCTOR => Some(icons.symbol_kind.constructor),
SymbolKind::ENUM => Some(icons.symbol_kind.enumeration),
SymbolKind::INTERFACE => Some(icons.symbol_kind.interface),
SymbolKind::FUNCTION => Some(icons.symbol_kind.function),
SymbolKind::VARIABLE => Some(icons.symbol_kind.variable),
SymbolKind::CONSTANT => Some(icons.symbol_kind.constant),
SymbolKind::STRING => Some(icons.symbol_kind.string),
SymbolKind::NUMBER => Some(icons.symbol_kind.number),
SymbolKind::BOOLEAN => Some(icons.symbol_kind.boolean),
SymbolKind::ARRAY => Some(icons.symbol_kind.array),
SymbolKind::OBJECT => Some(icons.symbol_kind.object),
SymbolKind::KEY => Some(icons.symbol_kind.key),
SymbolKind::NULL => Some(icons.symbol_kind.null),
SymbolKind::ENUM_MEMBER => Some(icons.symbol_kind.enum_member),
SymbolKind::STRUCT => Some(icons.symbol_kind.structure),
SymbolKind::EVENT => Some(icons.symbol_kind.event),
SymbolKind::OPERATOR => Some(icons.symbol_kind.operator),
SymbolKind::TYPE_PARAMETER => Some(icons.symbol_kind.type_parameter),
SymbolKind::FILE => Some(&icons.symbol_kind.file),
SymbolKind::MODULE => Some(&icons.symbol_kind.module),
SymbolKind::NAMESPACE => Some(&icons.symbol_kind.namespace),
SymbolKind::PACKAGE => Some(&icons.symbol_kind.package),
SymbolKind::CLASS => Some(&icons.symbol_kind.class),
SymbolKind::METHOD => Some(&icons.symbol_kind.method),
SymbolKind::PROPERTY => Some(&icons.symbol_kind.property),
SymbolKind::FIELD => Some(&icons.symbol_kind.field),
SymbolKind::CONSTRUCTOR => Some(&icons.symbol_kind.constructor),
SymbolKind::ENUM => Some(&icons.symbol_kind.enumeration),
SymbolKind::INTERFACE => Some(&icons.symbol_kind.interface),
SymbolKind::FUNCTION => Some(&icons.symbol_kind.function),
SymbolKind::VARIABLE => Some(&icons.symbol_kind.variable),
SymbolKind::CONSTANT => Some(&icons.symbol_kind.constant),
SymbolKind::STRING => Some(&icons.symbol_kind.string),
SymbolKind::NUMBER => Some(&icons.symbol_kind.number),
SymbolKind::BOOLEAN => Some(&icons.symbol_kind.boolean),
SymbolKind::ARRAY => Some(&icons.symbol_kind.array),
SymbolKind::OBJECT => Some(&icons.symbol_kind.object),
SymbolKind::KEY => Some(&icons.symbol_kind.key),
SymbolKind::NULL => Some(&icons.symbol_kind.null),
SymbolKind::ENUM_MEMBER => Some(&icons.symbol_kind.enum_member),
SymbolKind::STRUCT => Some(&icons.symbol_kind.structure),
SymbolKind::EVENT => Some(&icons.symbol_kind.event),
SymbolKind::OPERATOR => Some(&icons.symbol_kind.operator),
SymbolKind::TYPE_PARAMETER => Some(&icons.symbol_kind.type_parameter),
_ => None,
}
}
Expand Down Expand Up @@ -181,13 +182,13 @@ impl ui::menu::Item for PickerDiagnostic {
])
}

fn icon(&self, icons: &helix_view::icons::Icons) -> Option<char> {
fn icon<'a>(&self, icons: &'a helix_view::icons::Icons) -> Option<&'a Icon> {
if let Some(severity) = self.diag.severity {
match severity {
DiagnosticSeverity::HINT => Some(icons.diagnostic.hint),
DiagnosticSeverity::INFORMATION => Some(icons.diagnostic.info),
DiagnosticSeverity::WARNING => Some(icons.diagnostic.warning),
DiagnosticSeverity::ERROR => Some(icons.diagnostic.error),
DiagnosticSeverity::HINT => Some(&icons.diagnostic.hint),
DiagnosticSeverity::INFORMATION => Some(&icons.diagnostic.info),
DiagnosticSeverity::WARNING => Some(&icons.diagnostic.warning),
DiagnosticSeverity::ERROR => Some(&icons.diagnostic.error),
_ => None,
}
} else {
Expand Down
28 changes: 15 additions & 13 deletions helix-term/src/ui/menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ pub use tui::widgets::{Cell, Row};
use fuzzy_matcher::skim::SkimMatcherV2 as Matcher;
use fuzzy_matcher::FuzzyMatcher;

use helix_view::{graphics::Rect, icons::Icons, Editor};
use helix_view::{
graphics::Rect,
icons::{Icon, Icons},
Editor,
};
use tui::layout::Constraint;

pub trait Item {
Expand All @@ -34,7 +38,7 @@ pub trait Item {
Row::new(vec![Cell::from(self.label(data))])
}

fn icon(&self, _icons: &Icons) -> Option<char> {
fn icon<'a>(&self, _icons: &'a Icons) -> Option<&'a Icon> {
None
}
}
Expand All @@ -50,20 +54,18 @@ impl Item for PathBuf {
.into()
}

fn icon(&self, icons: &Icons) -> Option<char> {
fn icon<'a>(&self, icons: &'a Icons) -> Option<&'a Icon> {
if let Some(extension) = self.extension().and_then(|e| e.to_str()) {
icons
.mime_type
.get(extension)
.cloned()
.or(Some(icons.symbol_kind.file))
match icons.mime_type.get(extension) {
Some(i) => Some(i),
None => Some(&icons.symbol_kind.file),
}
} else {
if let Some(filename) = self.file_name().and_then(|f| f.to_str()) {
icons
.mime_type
.get(filename)
.cloned()
.or(Some(icons.symbol_kind.file))
match icons.mime_type.get(filename) {
Some(i) => Some(i),
None => Some(&icons.symbol_kind.file),
}
} else {
None
}
Expand Down
11 changes: 9 additions & 2 deletions helix-term/src/ui/picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,12 +661,19 @@ impl<T: Item + 'static> Component for Picker<T> {
pos.x,
pos.y + i as u16,
if let Some(icon) = icon {
format!("{} ", icon)
format!("{} ", icon.icon_char)
} else {
" ".to_string()
},
2,
highlighted,
if let Some(icon) = icon {
match icon.style {
Some(s) => s.patch(span.style),
None => highlighted.patch(span.style),
}
} else {
highlighted.patch(span.style)
},
)
.0;
already_put_icon = true;
Expand Down
10 changes: 8 additions & 2 deletions helix-term/src/ui/statusline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,13 @@ where
if warnings > 0 {
write(
context,
context.editor.icons.diagnostic.warning.to_string(),
context
.editor
.icons
.diagnostic
.warning
.icon_char
.to_string(),
// "●".to_string(),
Some(context.editor.theme.get("warning")),
);
Expand All @@ -236,7 +242,7 @@ where
if errors > 0 {
write(
context,
context.editor.icons.diagnostic.error.to_string(),
context.editor.icons.diagnostic.error.icon_char.to_string(),
// "●".to_string(),
Some(context.editor.theme.get("error")),
);
Expand Down
10 changes: 5 additions & 5 deletions helix-view/src/gutter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ pub fn diagnostic<'doc>(
let diagnostic = diagnostics_on_line.max_by_key(|d| d.severity).unwrap();

let diagnostic_icon = match diagnostic.severity {
Some(Severity::Error) => editor.icons.diagnostic.error,
Some(Severity::Warning) | None => editor.icons.diagnostic.warning,
Some(Severity::Info) => editor.icons.diagnostic.info,
Some(Severity::Hint) => editor.icons.diagnostic.hint,
Some(Severity::Error) => &editor.icons.diagnostic.error,
Some(Severity::Warning) | None => &editor.icons.diagnostic.warning,
Some(Severity::Info) => &editor.icons.diagnostic.info,
Some(Severity::Hint) => &editor.icons.diagnostic.hint,
};
// write!(out, "●").unwrap();
write!(out, "{}", diagnostic_icon).unwrap();
write!(out, "{}", diagnostic_icon.icon_char).unwrap();
return Some(match diagnostic.severity {
Some(Severity::Error) => error,
Some(Severity::Warning) | None => warning,
Expand Down
125 changes: 90 additions & 35 deletions helix-view/src/icons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,109 @@ use serde::Deserialize;
use std::collections::HashMap;
use std::path::{Path, PathBuf};

use crate::graphics::{Color, Style};

#[derive(Debug, Clone, PartialEq, Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct Diagnostic {
pub error: char,
pub warning: char,
pub info: char,
pub hint: char,
pub struct Icon {
#[serde(rename = "icon")]
pub icon_char: char,
#[serde(default)]
#[serde(deserialize_with = "icon_color_to_style", rename = "color")]
pub style: Option<Style>,
}

#[derive(Debug, Clone, PartialEq, Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct SymbolKind {
pub file: char,
pub module: char,
pub namespace: char,
pub package: char,
pub class: char,
pub method: char,
pub property: char,
pub field: char,
pub constructor: char,
pub enumeration: char,
pub interface: char,
pub function: char,
pub variable: char,
pub constant: char,
pub string: char,
pub number: char,
pub boolean: char,
pub array: char,
pub object: char,
pub key: char,
pub null: char,
pub enum_member: char,
pub structure: char,
pub event: char,
pub operator: char,
pub type_parameter: char,
impl Icon {
pub fn plain(icon_char: char) -> Self {
Self {
icon_char,
style: None,
}
}
}

#[derive(Debug, Clone, PartialEq, Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct Icons {
pub mime_type: HashMap<String, char>,
pub mime_type: HashMap<String, Icon>,
pub diagnostic: Diagnostic,
pub symbol_kind: SymbolKind,
}

#[derive(Debug, Clone, PartialEq, Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct Diagnostic {
pub error: Icon,
pub warning: Icon,
pub info: Icon,
pub hint: Icon,
}

#[derive(Debug, Clone, PartialEq, Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct SymbolKind {
pub file: Icon,
pub module: Icon,
pub namespace: Icon,
pub package: Icon,
pub class: Icon,
pub method: Icon,
pub property: Icon,
pub field: Icon,
pub constructor: Icon,
pub enumeration: Icon,
pub interface: Icon,
pub function: Icon,
pub variable: Icon,
pub constant: Icon,
pub string: Icon,
pub number: Icon,
pub boolean: Icon,
pub array: Icon,
pub object: Icon,
pub key: Icon,
pub null: Icon,
pub enum_member: Icon,
pub structure: Icon,
pub event: Icon,
pub operator: Icon,
pub type_parameter: Icon,
}

fn icon_color_to_style<'de, D>(deserializer: D) -> Result<Option<Style>, D::Error>
where
D: serde::Deserializer<'de>,
{
let s: &str = Deserialize::deserialize(deserializer)?;
let mut style = Style::default();
if s.len() != 0 {
match hex_string_to_rgb(s) {
Ok(c) => {
style = style.fg(c);
}
Err(e) => {
log::error!("{}", e);
}
};
Ok(Some(style))
} else {
Ok(None)
}
}

pub fn hex_string_to_rgb(s: &str) -> Result<Color, String> {
if s.starts_with('#') && s.len() >= 7 {
if let (Ok(red), Ok(green), Ok(blue)) = (
u8::from_str_radix(&s[1..3], 16),
u8::from_str_radix(&s[3..5], 16),
u8::from_str_radix(&s[5..7], 16),
) {
return Ok(Color::Rgb(red, green, blue));
}
}
Err(format!("Icon color: malformed hexcode: {}", s))
}

pub struct Loader {
user_dir: PathBuf,
default_dir: PathBuf,
Expand Down
Loading

0 comments on commit f181f87

Please sign in to comment.