use std::ops;
use crate::{ColorScheme, FontShape, FontStyle, Item, Menu};
use colored::*;
pub(crate) fn colorize(s: &str, style: &FontStyle) -> String {
let mut colored = s.to_string();
if let Some(shape) = style.shape {
if shape & FontShape::Bold != 0 {
colored = colored.bold().to_string();
}
if shape & FontShape::Italic != 0 {
colored = colored.italic().to_string();
}
if shape & FontShape::Underline != 0 {
colored = colored.underline().to_string();
}
}
if let Some(fg_color) = style.fg_color {
colored = colored.color(fg_color).to_string();
} else if let Some(fg_color_256) = style.fg_color_256 {
colored = colored
.truecolor(fg_color_256.0, fg_color_256.1, fg_color_256.2)
.to_string();
}
if let Some(bg_color) = style.bg_color {
colored = colored.on_color(bg_color).to_string();
} else if let Some(bg_color_256) = style.bg_color_256 {
colored = colored
.on_truecolor(bg_color_256.0, bg_color_256.1, bg_color_256.2)
.to_string();
}
colored
}
impl<T: Send + Sync> Menu<T> {
pub fn set_colorscheme(&mut self, cs: ColorScheme) -> &mut Self {
self.colorscheme = cs;
self
}
}
impl<T: Send + Sync> Item<T> {
pub(crate) fn get_colored_alias_for_normal_mode(&self, colorscheme: &ColorScheme) -> String {
colorize(&self.alias, &colorscheme.items)
}
pub(crate) fn get_colored_alias_for_query_mode(&self, colorscheme: &ColorScheme) -> String {
if self.matched_indices.is_none() || self.matched_indices.as_ref().unwrap().is_empty() {
return colorize(&self.alias, &colorscheme.items);
}
let mut display = String::new();
let indices = self.matched_indices.as_ref().unwrap();
let alias_chars: Vec<char> = self.alias.chars().collect();
let len = alias_chars.len();
let mut left = 0;
for &idx in indices.iter() {
let prefix: String = alias_chars[left..idx].iter().collect();
display.push_str(&prefix);
let cur_char: String = alias_chars[idx..=idx].iter().collect();
let ch = colorize(&cur_char, &colorscheme.matched);
display.push_str(&ch);
left = idx + 1;
}
if left < len {
let rest: String = alias_chars[left..].iter().collect();
display.push_str(&rest);
}
display
}
}
impl ops::BitOr for FontShape {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
unsafe { std::mem::transmute((self as u8) | (rhs as u8)) }
}
}
impl ops::BitAnd for FontShape {
type Output = u8;
fn bitand(self, rhs: FontShape) -> u8 {
(self as u8) & (rhs as u8)
}
}
impl FontStyle {
fn default_matched() -> Self {
Self {
shape: None,
fg_color: Some(Color::Yellow),
bg_color: None,
fg_color_256: None,
bg_color_256: None,
}
}
pub fn set_shape(&mut self, shape: FontShape) -> &mut Self {
self.shape = Some(shape);
self
}
pub fn set_fg_color(&mut self, color: Color) -> &mut Self {
self.fg_color = Some(color);
self
}
pub fn set_bg_color(&mut self, color: Color) -> &mut Self {
self.bg_color = Some(color);
self
}
pub fn set_fg_color_256(&mut self, color: (u8, u8, u8)) -> &mut Self {
self.fg_color_256 = Some(color);
self
}
pub fn set_bg_color_256(&mut self, color: (u8, u8, u8)) -> &mut Self {
self.bg_color_256 = Some(color);
self
}
pub fn build(&mut self) -> Self {
*self
}
}
impl ColorScheme {
pub fn new() -> Self {
Self::default()
}
pub fn set_title_style(&mut self, style: FontStyle) -> &mut Self {
self.title = style;
self
}
pub fn set_query_style(&mut self, style: FontStyle) -> &mut Self {
self.query = style;
self
}
pub fn set_items_style(&mut self, style: FontStyle) -> &mut Self {
self.items = style;
self
}
pub fn set_chosen_ln_style(&mut self, style: FontStyle) -> &mut Self {
self.chosen_ln = style;
self
}
pub fn set_matched_style(&mut self, style: FontStyle) -> &mut Self {
self.matched = style;
self
}
pub fn set_more_tag_style(&mut self, style: FontStyle) -> &mut Self {
self.more_tag = style;
self
}
}
impl Default for ColorScheme {
fn default() -> Self {
Self {
title: FontStyle::default(),
query: FontStyle::default(),
items: FontStyle::default(),
matched: FontStyle::default_matched(),
chosen_ln: FontStyle::default_matched(),
more_tag: FontStyle::default(),
}
}
}