diff --git a/README.md b/README.md
index d7a8f37..4b60828 100644
--- a/README.md
+++ b/README.md
@@ -68,8 +68,8 @@ Table of content
-
-
+
+
diff --git a/src/config.rs b/src/config.rs
index f36ded7..017c7dd 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -4,6 +4,7 @@ use crate::app::NodeFilter;
use crate::app::NodeSorter;
use crate::app::NodeSorterApplicable;
use crate::default_config;
+use crate::ui::Border;
use crate::ui::Style;
use anyhow::Result;
use indexmap::IndexSet;
@@ -12,7 +13,6 @@ use std::collections::BTreeMap;
use std::collections::HashMap;
use tui::layout::Constraint as TuiConstraint;
use tui::layout::Rect;
-use tui::widgets::Borders as TuiBorders;
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
@@ -74,8 +74,8 @@ impl NodeTypeConfig {
}
/// Get a reference to the node type config's style.
- pub fn style(&self) -> Style {
- self.style
+ pub fn style(&self) -> &Style {
+ &self.style
}
/// Get a reference to the node type config's meta.
@@ -180,8 +180,8 @@ impl UiConfig {
}
/// Get a reference to the ui config's style.
- pub fn style(&self) -> Style {
- self.style
+ pub fn style(&self) -> &Style {
+ &self.style
}
}
@@ -208,8 +208,8 @@ impl UiElement {
}
/// Get a reference to the ui element's style.
- pub fn style(&self) -> Style {
- self.style
+ pub fn style(&self) -> &Style {
+ &self.style
}
}
@@ -240,8 +240,8 @@ impl TableRowConfig {
}
/// Get a reference to the table row config's style.
- pub fn style(&self) -> Style {
- self.style
+ pub fn style(&self) -> &Style {
+ &self.style
}
/// Get a reference to the table row config's height.
@@ -348,8 +348,8 @@ impl TableConfig {
}
/// Get a reference to the table config's style.
- pub fn style(&self) -> Style {
- self.style
+ pub fn style(&self) -> &Style {
+ &self.style
}
/// Get a reference to the table config's tree.
@@ -1027,26 +1027,6 @@ impl ModesConfig {
}
}
-#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
-#[serde(deny_unknown_fields)]
-pub enum Border {
- Top,
- Right,
- Bottom,
- Left,
-}
-
-impl Border {
- pub fn bits(self) -> u32 {
- match self {
- Self::Top => TuiBorders::TOP.bits(),
- Self::Right => TuiBorders::RIGHT.bits(),
- Self::Bottom => TuiBorders::BOTTOM.bits(),
- Self::Left => TuiBorders::LEFT.bits(),
- }
- }
-}
-
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct LayoutOptions {
@@ -1115,8 +1095,8 @@ impl BlockConfig {
}
/// Get a reference to the block config's style.
- pub fn style(&self) -> Style {
- self.style
+ pub fn style(&self) -> &Style {
+ &self.style
}
}
diff --git a/src/config.yml b/src/config.yml
index 5c58c3e..32a2343 100644
--- a/src/config.yml
+++ b/src/config.yml
@@ -22,9 +22,6 @@ layouts:
- SortAndFilter:
borders: [Top, Right, Bottom, Left]
- Table:
- title:
- style:
- fg: Red
borders: [Top, Right, Bottom, Left]
- InputAndLogs:
borders: [Top, Right, Bottom, Left]
@@ -110,7 +107,7 @@ general:
- sorter: ByIRelativePath
reverse: false
prompt:
- format: "> "
+ format: "❯ "
cursor:
format: █
logs:
@@ -133,20 +130,13 @@ general:
style:
fg: null
bg: null
- add_modifier:
- bits: 0
- sub_modifier:
- bits: 0
+ add_modifiers: null
+ sub_modifiers: null
- format: '╭──── path'
- format: size
- format: type
style:
- fg: null
- bg: null
- add_modifier:
- bits: 1
- sub_modifier:
- bits: 0
+ add_modifiers: [Bold]
height: 1
row:
cols:
@@ -154,78 +144,35 @@ general:
- format: >
{{{tree}}}{{{prefix}}}{{{meta.icon}}}{{#if (ne meta.icon "")}} {{/if}}{{{relativePath}}}{{#if isDir}}/{{/if}}{{{suffix}}}
{{#if isSymlink}}-> {{#if isBroken}}×{{else}}{{{symlink.absolutePath}}}{{/if}}{{#if symlink.isDir}}/{{/if}}{{/if}}
- style:
- fg: null
- bg: null
- add_modifier:
- bits: 0
- sub_modifier:
- bits: 0
- format: '{{#unless isDir}}{{humansize size}}{{/unless}}'
- format: '{{#if isSymlink}}{{{symlink.mimeEssence}}}{{else}}{{{mimeEssence}}}{{/if}}'
- style:
- fg: null
- bg: null
- add_modifier:
- bits: 0
- sub_modifier:
- bits: 0
height: 0
- style:
- fg: null
- bg: null
- add_modifier:
- bits: 0
- sub_modifier:
- bits: 0
tree:
- format: ├─
- style:
- fg: null
- bg: null
- add_modifier:
- bits: 0
- sub_modifier:
- bits: 0
- format: ├─
- format: ╰─
- col_spacing: 1
+ col_spacing: 0
col_widths:
- Percentage: 10
- Percentage: 50
- Percentage: 20
- Percentage: 20
+
default_ui:
prefix: ' '
suffix: ''
- style:
- fg: null
- bg: null
- add_modifier:
- bits: 0
- sub_modifier:
- bits: 0
focus_ui:
prefix: ▸[
suffix: ']'
style:
fg: Blue
- bg: null
- add_modifier:
- bits: 1
- sub_modifier:
- bits: 0
+ add_modifiers: [Bold]
selection_ui:
prefix: ' {'
suffix: '}'
style:
fg: LightGreen
- bg: null
- add_modifier:
- bits: 1
- sub_modifier:
- bits: 0
-
+ add_modifiers: [Bold]
sort_and_filter_ui:
separator:
format: " › "
@@ -359,31 +306,16 @@ node_types:
directory:
style:
fg: Cyan
- bg: null
- add_modifier:
- bits: 1
- sub_modifier:
- bits: 0
+ add_modifiers: [Bold]
meta:
icon: ð
file:
- style:
- fg: null
- bg: null
- add_modifier:
- bits: 0
- sub_modifier:
- bits: 0
meta:
icon: ƒ
symlink:
style:
fg: Magenta
- bg: null
- add_modifier:
- bits: 4
- sub_modifier:
- bits: 0
+ add_modifiers: [Italic]
meta:
icon: §
mime_essence: {}
diff --git a/src/ui.rs b/src/ui.rs
index fe399c7..8996c26 100644
--- a/src/ui.rs
+++ b/src/ui.rs
@@ -4,6 +4,7 @@ use crate::app::{Node, ResolvedNode};
use crate::config::BlockConfig;
use crate::config::Layout;
use handlebars::Handlebars;
+use indexmap::IndexSet;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
@@ -12,7 +13,7 @@ use std::env;
use tui::backend::Backend;
use tui::layout::Rect;
use tui::layout::{Constraint as TuiConstraint, Direction, Layout as TuiLayout};
-use tui::style::{Color, Modifier, Style as TuiStyle};
+use tui::style::{Color, Modifier as TuiModifier, Style as TuiStyle};
use tui::text::{Span, Spans};
use tui::widgets::{Block, Borders as TuiBorders, Cell, List, ListItem, Paragraph, Row, Table};
use tui::Frame;
@@ -22,36 +23,84 @@ lazy_static! {
pub static ref DEFAULT_STYLE: TuiStyle = TuiStyle::default();
}
-#[derive(Debug, Copy, Clone, Default, PartialEq, Serialize, Deserialize)]
+#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Serialize, Deserialize)]
+#[serde(deny_unknown_fields)]
+pub enum Border {
+ Top,
+ Right,
+ Bottom,
+ Left,
+}
+
+impl Border {
+ pub fn bits(self) -> u32 {
+ match self {
+ Self::Top => TuiBorders::TOP.bits(),
+ Self::Right => TuiBorders::RIGHT.bits(),
+ Self::Bottom => TuiBorders::BOTTOM.bits(),
+ Self::Left => TuiBorders::LEFT.bits(),
+ }
+ }
+}
+
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Serialize, Deserialize)]
+#[serde(deny_unknown_fields)]
+pub enum Modifier {
+ Bold,
+ Dim,
+ Italic,
+ Underlined,
+ SlowBlink,
+ RapidBlink,
+ Reversed,
+ Hidden,
+ CrossedOut,
+}
+
+impl Modifier {
+ pub fn bits(self) -> u16 {
+ match self {
+ Self::Bold => TuiModifier::BOLD.bits(),
+ Self::Dim => TuiModifier::DIM.bits(),
+ Self::Italic => TuiModifier::ITALIC.bits(),
+ Self::Underlined => TuiModifier::UNDERLINED.bits(),
+ Self::SlowBlink => TuiModifier::SLOW_BLINK.bits(),
+ Self::RapidBlink => TuiModifier::RAPID_BLINK.bits(),
+ Self::Reversed => TuiModifier::REVERSED.bits(),
+ Self::Hidden => TuiModifier::HIDDEN.bits(),
+ Self::CrossedOut => TuiModifier::CROSSED_OUT.bits(),
+ }
+ }
+}
+
+#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Style {
fg: Option,
bg: Option,
- add_modifier: Option,
- sub_modifier: Option,
+ add_modifiers: Option>,
+ sub_modifiers: Option>,
+}
+
+impl PartialEq for Style {
+ fn eq(&self, other: &Self) -> bool {
+ self.fg == other.fg
+ && self.bg == other.bg
+ && self.add_modifiers == other.add_modifiers
+ && self.sub_modifiers == other.sub_modifiers
+ }
}
impl Style {
pub fn extend(mut self, other: Self) -> Self {
self.fg = other.fg.or(self.fg);
self.bg = other.bg.or(self.bg);
- self.add_modifier = other.add_modifier.or(self.add_modifier);
- self.sub_modifier = other.sub_modifier.or(self.sub_modifier);
+ self.add_modifiers = other.add_modifiers.or(self.add_modifiers);
+ self.sub_modifiers = other.sub_modifiers.or(self.sub_modifiers);
self
}
}
-impl From for Style {
- fn from(s: TuiStyle) -> Self {
- Self {
- fg: s.fg,
- bg: s.bg,
- add_modifier: Some(s.add_modifier),
- sub_modifier: Some(s.sub_modifier),
- }
- }
-}
-
impl Into for Style {
fn into(self) -> TuiStyle {
if *NO_COLOR {
@@ -60,8 +109,23 @@ impl Into for Style {
TuiStyle {
fg: self.fg,
bg: self.bg,
- add_modifier: self.add_modifier.unwrap_or_else(Modifier::empty),
- sub_modifier: self.sub_modifier.unwrap_or_else(Modifier::empty),
+ add_modifier: TuiModifier::from_bits_truncate(
+ self.add_modifiers
+ .unwrap_or_default()
+ .into_iter()
+ .map(|m| m.bits())
+ .reduce(|a, b| (a ^ b))
+ .unwrap_or_else(|| TuiModifier::empty().bits()),
+ ),
+
+ sub_modifier: TuiModifier::from_bits_truncate(
+ self.sub_modifiers
+ .unwrap_or_default()
+ .into_iter()
+ .map(|m| m.bits())
+ .reduce(|a, b| (a ^ b))
+ .unwrap_or_else(|| TuiModifier::empty().bits()),
+ ),
}
}
}
@@ -183,9 +247,9 @@ fn block<'a>(config: BlockConfig, default_title: String) -> Block<'a> {
))
.title(Span::styled(
config.title().format().clone().unwrap_or(default_title),
- config.title().style().into(),
+ config.title().style().clone().into(),
))
- .style(config.style().into())
+ .style(config.style().clone().into())
}
fn draw_table(
@@ -266,7 +330,7 @@ fn draw_table(
(
ui.prefix().clone(),
ui.suffix().clone(),
- ui.style().extend(node_type.style()),
+ ui.style().clone().extend(node_type.style().clone()),
)
};
@@ -274,14 +338,14 @@ fn draw_table(
let ui = app_config.general().selection_ui().clone();
prefix = ui.prefix().clone().or(prefix);
suffix = ui.suffix().clone().or(suffix);
- style = style.extend(ui.style());
+ style = style.extend(ui.style().clone());
};
if is_focused {
let ui = app_config.general().focus_ui().clone();
prefix = ui.prefix().clone().or(prefix);
suffix = ui.suffix().clone().or(suffix);
- style = style.extend(ui.style());
+ style = style.extend(ui.style().clone());
};
let meta = NodeUiMetadata::new(
@@ -325,8 +389,8 @@ fn draw_table(
let table = Table::new(rows)
.widths(&table_constraints)
- .style(app_config.general().table().style().into())
- .highlight_style(app_config.general().focus_ui().style().into())
+ .style(app_config.general().table().style().clone().into())
+ .highlight_style(app_config.general().focus_ui().style().clone().into())
.column_spacing(
app_config
.general()
@@ -359,7 +423,7 @@ fn draw_table(
.collect::>(),
)
.height(header_height)
- .style(app_config.general().table().header().style().into()),
+ .style(app_config.general().table().header().style().clone().into()),
);
f.render_widget(table, layout_size);
@@ -456,7 +520,7 @@ fn draw_input_buffer(
.format()
.clone()
.unwrap_or_default(),
- app.config().general().prompt().style().into(),
+ app.config().general().prompt().style().clone().into(),
),
Span::raw(app.input_buffer().unwrap_or_else(|| "".into())),
Span::styled(
@@ -466,7 +530,7 @@ fn draw_input_buffer(
.format()
.clone()
.unwrap_or_default(),
- app.config().general().cursor().style().into(),
+ app.config().general().cursor().style().clone().into(),
),
]))
.block(block(config, " Input ".into()));
@@ -490,7 +554,11 @@ fn draw_sort_n_filter(
.format()
.to_owned()
.unwrap_or_default(),
- ui.sort_direction_identifiers().forward().style().into(),
+ ui.sort_direction_identifiers()
+ .forward()
+ .style()
+ .clone()
+ .into(),
);
let reverse = Span::styled(
@@ -499,7 +567,11 @@ fn draw_sort_n_filter(
.format()
.to_owned()
.unwrap_or_default(),
- ui.sort_direction_identifiers().reverse().style().into(),
+ ui.sort_direction_identifiers()
+ .reverse()
+ .style()
+ .clone()
+ .into(),
);
let mut spans = filter_by
@@ -509,7 +581,10 @@ fn draw_sort_n_filter(
.get(&f.filter())
.map(|u| {
(
- Span::styled(u.format().to_owned().unwrap_or_default(), u.style().into()),
+ Span::styled(
+ u.format().to_owned().unwrap_or_default(),
+ u.style().clone().into(),
+ ),
Span::raw(f.input().clone()),
)
})
@@ -526,7 +601,10 @@ fn draw_sort_n_filter(
.get(&s.sorter())
.map(|u| {
(
- Span::styled(u.format().to_owned().unwrap_or_default(), u.style().into()),
+ Span::styled(
+ u.format().to_owned().unwrap_or_default(),
+ u.style().clone().into(),
+ ),
direction.clone(),
)
})
@@ -534,7 +612,7 @@ fn draw_sort_n_filter(
}))
.zip(std::iter::repeat(Span::styled(
ui.separator().format().to_owned().unwrap_or_default(),
- ui.separator().style().into(),
+ ui.separator().style().clone().into(),
)))
.map(|((a, b), c)| vec![a, b, c])
.flatten()
@@ -573,7 +651,7 @@ fn draw_logs(
&logs_config.info().format().to_owned().unwrap_or_default(),
l.message()
))
- .style(logs_config.info().style().into()),
+ .style(logs_config.info().style().clone().into()),
app::LogLevel::Success => ListItem::new(format!(
"{} | {} | {}",
&time,
@@ -584,14 +662,14 @@ fn draw_logs(
.unwrap_or_default(),
l.message()
))
- .style(logs_config.success().style().into()),
+ .style(logs_config.success().style().clone().into()),
app::LogLevel::Error => ListItem::new(format!(
"{} | {} | {}",
&time,
&logs_config.error().format().to_owned().unwrap_or_default(),
l.message()
))
- .style(logs_config.error().style().into()),
+ .style(logs_config.error().style().clone().into()),
}
})
.collect::>();
@@ -714,29 +792,34 @@ mod test {
use super::*;
use crate::config;
use tui::style::Color;
- use tui::style::Modifier;
+
+ fn modifier(m: Modifier) -> Option> {
+ let mut x = IndexSet::new();
+ x.insert(m);
+ Some(x)
+ }
#[test]
fn test_extend_style() {
let a = Style {
fg: Some(Color::Red),
bg: None,
- add_modifier: Some(Modifier::BOLD),
- sub_modifier: None,
+ add_modifiers: modifier(Modifier::Bold),
+ sub_modifiers: None,
};
let b = Style {
fg: None,
bg: Some(Color::Blue),
- add_modifier: None,
- sub_modifier: Some(Modifier::DIM),
+ add_modifiers: None,
+ sub_modifiers: modifier(Modifier::Dim),
};
let c = Style {
fg: Some(Color::Cyan),
bg: Some(Color::Magenta),
- add_modifier: Some(Modifier::CROSSED_OUT),
- sub_modifier: Some(Modifier::ITALIC),
+ add_modifiers: modifier(Modifier::CrossedOut),
+ sub_modifiers: modifier(Modifier::Italic),
};
assert_eq!(
@@ -744,8 +827,8 @@ mod test {
Style {
fg: Some(Color::Red),
bg: Some(Color::Blue),
- add_modifier: Some(Modifier::BOLD),
- sub_modifier: Some(Modifier::DIM),
+ add_modifiers: modifier(Modifier::Bold),
+ sub_modifiers: modifier(Modifier::Dim),
}
);
@@ -754,8 +837,8 @@ mod test {
Style {
fg: Some(Color::Red),
bg: Some(Color::Blue),
- add_modifier: Some(Modifier::BOLD),
- sub_modifier: Some(Modifier::DIM),
+ add_modifiers: modifier(Modifier::Bold),
+ sub_modifiers: modifier(Modifier::Dim),
}
);
@@ -764,8 +847,8 @@ mod test {
Style {
fg: Some(Color::Cyan),
bg: Some(Color::Magenta),
- add_modifier: Some(Modifier::CROSSED_OUT),
- sub_modifier: Some(Modifier::ITALIC),
+ add_modifiers: modifier(Modifier::CrossedOut),
+ sub_modifiers: modifier(Modifier::Italic),
}
);
@@ -774,8 +857,8 @@ mod test {
Style {
fg: Some(Color::Red),
bg: Some(Color::Magenta),
- add_modifier: Some(Modifier::BOLD),
- sub_modifier: Some(Modifier::ITALIC),
+ add_modifiers: modifier(Modifier::Bold),
+ sub_modifiers: modifier(Modifier::Italic),
}
);
}
@@ -788,8 +871,8 @@ mod test {
style: Style {
fg: Some(Color::Red),
bg: None,
- add_modifier: Some(Modifier::BOLD),
- sub_modifier: None,
+ add_modifiers: modifier(Modifier::Bold),
+ sub_modifiers: None,
},
};
@@ -799,8 +882,8 @@ mod test {
style: Style {
fg: None,
bg: Some(Color::Blue),
- add_modifier: None,
- sub_modifier: Some(Modifier::DIM),
+ add_modifiers: None,
+ sub_modifiers: modifier(Modifier::Dim),
},
};
@@ -810,8 +893,8 @@ mod test {
style: Style {
fg: Some(Color::Cyan),
bg: Some(Color::Magenta),
- add_modifier: Some(Modifier::CROSSED_OUT),
- sub_modifier: Some(Modifier::ITALIC),
+ add_modifiers: modifier(Modifier::CrossedOut),
+ sub_modifiers: modifier(Modifier::Italic),
},
};
@@ -823,8 +906,8 @@ mod test {
style: Style {
fg: Some(Color::Red),
bg: Some(Color::Blue),
- add_modifier: Some(Modifier::BOLD),
- sub_modifier: Some(Modifier::DIM),
+ add_modifiers: modifier(Modifier::Bold),
+ sub_modifiers: modifier(Modifier::Dim),
},
}
);
@@ -837,8 +920,8 @@ mod test {
style: Style {
fg: Some(Color::Red),
bg: Some(Color::Blue),
- add_modifier: Some(Modifier::BOLD),
- sub_modifier: Some(Modifier::DIM),
+ add_modifiers: modifier(Modifier::Bold),
+ sub_modifiers: modifier(Modifier::Dim),
},
}
);
@@ -851,8 +934,8 @@ mod test {
style: Style {
fg: Some(Color::Cyan),
bg: Some(Color::Magenta),
- add_modifier: Some(Modifier::CROSSED_OUT),
- sub_modifier: Some(Modifier::ITALIC),
+ add_modifiers: modifier(Modifier::CrossedOut),
+ sub_modifiers: modifier(Modifier::Italic),
},
}
);