Add Italics, Blink, Dim and Hidden text attributes

Text attributes have been rewritten as bit flags, so for example instead of
"BoldUnderline" you'd have to define "Bold | Underline" in your theme
settings.

Requested in #21
master
Manos Pitsidianakis 2020-04-05 12:04:25 +03:00
parent e9a935dbf7
commit 4930d1b46c
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
19 changed files with 314 additions and 247 deletions

View File

@ -50,6 +50,7 @@ rmp = "^0.8"
rmpv = { version = "^0.4.2", features=["with-serde",] } rmpv = { version = "^0.4.2", features=["with-serde",] }
rmp-serde = "^0.14.0" rmp-serde = "^0.14.0"
smallvec = { version = "1.1.0", features = ["serde", ] } smallvec = { version = "1.1.0", features = ["serde", ] }
bitflags = "1.0"
[profile.release] [profile.release]

View File

@ -104,17 +104,19 @@ Case-sensitive.
.It .It
"Bold" "Bold"
.It .It
"Dim"
.It
"Italics"
.It
"Underline" "Underline"
.It .It
"BoldUnderline" "Blink"
.It .It
"Reverse" "Reverse"
.It .It
"BoldReverse" "Hidden"
.It .It
"UnderlineReverse" Any combo of the above separated by a bitwise XOR "\&|" eg "Dim | Italics"
.It
"BoldReverseUnderline"
.El .El
.Sh VALID COLOR VALUES .Sh VALID COLOR VALUES
Color values are of type String with the following valid contents: Color values are of type String with the following valid contents:

View File

@ -45,6 +45,8 @@ extern crate nom;
extern crate serde_json; extern crate serde_json;
extern crate smallvec; extern crate smallvec;
#[macro_use]
extern crate bitflags;
#[global_allocator] #[global_allocator]
static GLOBAL: System = System; static GLOBAL: System = System;

View File

@ -287,13 +287,13 @@ impl ContactList {
if a.name.grapheme_len() + s.len() > width + 1 { if a.name.grapheme_len() + s.len() > width + 1 {
/* Print account name */ /* Print account name */
let (x, y) = let (x, y) =
write_string_to_grid(&a.name, grid, fg_color, bg_color, Attr::Bold, area, None); write_string_to_grid(&a.name, grid, fg_color, bg_color, Attr::BOLD, area, None);
write_string_to_grid( write_string_to_grid(
&s, &s,
grid, grid,
fg_color, fg_color,
bg_color, bg_color,
Attr::Bold, Attr::BOLD,
( (
pos_dec( pos_dec(
(get_x(bottom_right!(area)), get_y(upper_left!(area))), (get_x(bottom_right!(area)), get_y(upper_left!(area))),
@ -308,7 +308,7 @@ impl ContactList {
grid, grid,
fg_color, fg_color,
bg_color, bg_color,
Attr::Bold, Attr::BOLD,
( (
pos_dec( pos_dec(
(get_x(bottom_right!(area)), get_y(upper_left!(area))), (get_x(bottom_right!(area)), get_y(upper_left!(area))),
@ -327,13 +327,13 @@ impl ContactList {
/* Print account name */ /* Print account name */
let (x, y) = let (x, y) =
write_string_to_grid(&a.name, grid, fg_color, bg_color, Attr::Bold, area, None); write_string_to_grid(&a.name, grid, fg_color, bg_color, Attr::BOLD, area, None);
write_string_to_grid( write_string_to_grid(
&s, &s,
grid, grid,
fg_color, fg_color,
bg_color, bg_color,
Attr::Bold, Attr::BOLD,
( (
pos_dec( pos_dec(
(get_x(bottom_right!(area)), get_y(upper_left!(area))), (get_x(bottom_right!(area)), get_y(upper_left!(area))),

View File

@ -457,7 +457,7 @@ impl Component for Composer {
grid, grid,
Color::Byte(189), Color::Byte(189),
Color::Byte(167), Color::Byte(167),
Attr::Default, Attr::DEFAULT,
( (
pos_dec(upper_left!(header_area), (0, 1)), pos_dec(upper_left!(header_area), (0, 1)),
bottom_right!(header_area), bottom_right!(header_area),

View File

@ -1226,7 +1226,7 @@ impl Listing {
grid, grid,
self.theme_default.fg, self.theme_default.fg,
self.theme_default.bg, self.theme_default.bg,
Attr::Bold, Attr::BOLD,
area, area,
None, None,
); );
@ -1262,9 +1262,9 @@ impl Listing {
); );
if !context.settings.terminal.use_color() { if !context.settings.terminal.use_color() {
ret.0.attrs |= Attr::Reverse; ret.0.attrs |= Attr::REVERSE;
ret.1.attrs |= Attr::Reverse; ret.1.attrs |= Attr::REVERSE;
ret.2.attrs |= Attr::Reverse; ret.2.attrs |= Attr::REVERSE;
} }
ret ret
} else { } else {
@ -1349,9 +1349,9 @@ impl Listing {
unread_count_att.bg, unread_count_att.bg,
unread_count_att.attrs unread_count_att.attrs
| if count.unwrap_or(0) > 0 { | if count.unwrap_or(0) > 0 {
Attr::Bold Attr::BOLD
} else { } else {
Attr::Default Attr::DEFAULT
}, },
( (
( (

View File

@ -127,7 +127,7 @@ impl MailListingTrait for CompactListing {
..self.color_cache ..self.color_cache
}; };
if !context.settings.terminal.use_color() { if !context.settings.terminal.use_color() {
self.color_cache.highlighted.attrs |= Attr::Reverse; self.color_cache.highlighted.attrs |= Attr::REVERSE;
} }
// Get mailbox as a reference. // Get mailbox as a reference.
@ -1040,7 +1040,7 @@ impl CompactListing {
&mut columns[0], &mut columns[0],
fg_color, fg_color,
bg_color, bg_color,
Attr::Default, Attr::DEFAULT,
((0, idx), (min_width.0, idx)), ((0, idx), (min_width.0, idx)),
None, None,
); );
@ -1052,7 +1052,7 @@ impl CompactListing {
&mut columns[1], &mut columns[1],
fg_color, fg_color,
bg_color, bg_color,
Attr::Default, Attr::DEFAULT,
((0, idx), (min_width.1.saturating_sub(1), idx)), ((0, idx), (min_width.1.saturating_sub(1), idx)),
None, None,
); );
@ -1064,7 +1064,7 @@ impl CompactListing {
&mut columns[2], &mut columns[2],
fg_color, fg_color,
bg_color, bg_color,
Attr::Default, Attr::DEFAULT,
((0, idx), (min_width.2, idx)), ((0, idx), (min_width.2, idx)),
None, None,
); );
@ -1076,7 +1076,7 @@ impl CompactListing {
&mut columns[3], &mut columns[3],
fg_color, fg_color,
bg_color, bg_color,
Attr::Default, Attr::DEFAULT,
((0, idx), (min_width.3, idx)), ((0, idx), (min_width.3, idx)),
None, None,
); );
@ -1088,7 +1088,7 @@ impl CompactListing {
&mut columns[4], &mut columns[4],
fg_color, fg_color,
bg_color, bg_color,
Attr::Default, Attr::DEFAULT,
((0, idx), (min_width.4, idx)), ((0, idx), (min_width.4, idx)),
None, None,
); );

View File

@ -114,7 +114,7 @@ impl MailListingTrait for ConversationsListing {
}; };
if !context.settings.terminal.use_color() { if !context.settings.terminal.use_color() {
self.color_cache.highlighted.attrs |= Attr::Reverse; self.color_cache.highlighted.attrs |= Attr::REVERSE;
} }
// Get mailbox as a reference. // Get mailbox as a reference.
// //
@ -765,7 +765,7 @@ impl ConversationsListing {
&mut self.content, &mut self.content,
fg_color, fg_color,
bg_color, bg_color,
Attr::Default, Attr::DEFAULT,
((0, 3 * idx), (width - 1, 3 * idx)), ((0, 3 * idx), (width - 1, 3 * idx)),
None, None,
); );
@ -778,7 +778,7 @@ impl ConversationsListing {
&mut self.content, &mut self.content,
fg_color, fg_color,
bg_color, bg_color,
Attr::Bold, Attr::BOLD,
((x, 3 * idx), (width - 1, 3 * idx)), ((x, 3 * idx), (width - 1, 3 * idx)),
None, None,
); );
@ -817,7 +817,7 @@ impl ConversationsListing {
&mut self.content, &mut self.content,
fg_color, fg_color,
bg_color, bg_color,
Attr::Default, Attr::DEFAULT,
((0, 3 * idx + 1), (width - 1, 3 * idx + 1)), ((0, 3 * idx + 1), (width - 1, 3 * idx + 1)),
None, None,
); );
@ -833,7 +833,7 @@ impl ConversationsListing {
&mut self.content, &mut self.content,
fg_color, fg_color,
bg_color, bg_color,
Attr::Default, Attr::DEFAULT,
((x + 4, 3 * idx + 1), (width - 1, 3 * idx + 1)), ((x + 4, 3 * idx + 1), (width - 1, 3 * idx + 1)),
None, None,
); );
@ -971,7 +971,7 @@ impl ConversationsListing {
&mut self.content, &mut self.content,
fg_color, fg_color,
bg_color, bg_color,
Attr::Default, Attr::DEFAULT,
((0, 3 * idx), (width - 1, 3 * idx)), ((0, 3 * idx), (width - 1, 3 * idx)),
None, None,
); );
@ -984,7 +984,7 @@ impl ConversationsListing {
&mut self.content, &mut self.content,
fg_color, fg_color,
bg_color, bg_color,
Attr::Bold, Attr::BOLD,
((x, 3 * idx), (width - 1, 3 * idx)), ((x, 3 * idx), (width - 1, 3 * idx)),
None, None,
); );
@ -1029,7 +1029,7 @@ impl ConversationsListing {
&mut self.content, &mut self.content,
fg_color, fg_color,
bg_color, bg_color,
Attr::Default, Attr::DEFAULT,
((0, 3 * idx + 1), (width - 1, 3 * idx + 1)), ((0, 3 * idx + 1), (width - 1, 3 * idx + 1)),
None, None,
); );
@ -1043,7 +1043,7 @@ impl ConversationsListing {
&mut self.content, &mut self.content,
fg_color, fg_color,
bg_color, bg_color,
Attr::Default, Attr::DEFAULT,
((x + 4, 3 * idx + 1), (width - 1, 3 * idx + 1)), ((x + 4, 3 * idx + 1), (width - 1, 3 * idx + 1)),
None, None,
); );

View File

@ -127,7 +127,7 @@ impl MailListingTrait for PlainListing {
..self.color_cache ..self.color_cache
}; };
if !context.settings.terminal.use_color() { if !context.settings.terminal.use_color() {
self.color_cache.highlighted.attrs |= Attr::Reverse; self.color_cache.highlighted.attrs |= Attr::REVERSE;
} }
// Get mailbox as a reference. // Get mailbox as a reference.
@ -982,7 +982,7 @@ impl Component for PlainListing {
grid, grid,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
area, area,
Some(get_x(upper_left)), Some(get_x(upper_left)),
); );

View File

@ -83,7 +83,7 @@ impl MailListingTrait for ThreadListing {
..self.color_cache ..self.color_cache
}; };
if !context.settings.terminal.use_color() { if !context.settings.terminal.use_color() {
self.color_cache.highlighted.attrs |= Attr::Reverse; self.color_cache.highlighted.attrs |= Attr::REVERSE;
} }
// Get mailbox as a reference. // Get mailbox as a reference.
@ -191,7 +191,7 @@ impl MailListingTrait for ThreadListing {
&mut self.content, &mut self.content,
fg_color, fg_color,
bg_color, bg_color,
Attr::Default, Attr::DEFAULT,
((0, idx), (MAX_COLS - 1, idx)), ((0, idx), (MAX_COLS - 1, idx)),
None, None,
); );

View File

@ -53,7 +53,7 @@ impl Component for StatusPanel {
&mut self.content, &mut self.content,
self.theme_default.fg, self.theme_default.fg,
self.theme_default.bg, self.theme_default.bg,
Attr::Bold, Attr::BOLD,
((1, 1), (width - 1, height - 1)), ((1, 1), (width - 1, height - 1)),
Some(1), Some(1),
); );
@ -91,7 +91,7 @@ impl Component for StatusPanel {
&mut self.content, &mut self.content,
self.theme_default.fg, self.theme_default.fg,
self.theme_default.bg, self.theme_default.bg,
Attr::Bold, Attr::BOLD,
((1, y + 1), (width - 1, height - 1)), ((1, y + 1), (width - 1, height - 1)),
Some(1), Some(1),
); );
@ -276,7 +276,7 @@ impl StatusPanel {
&mut self.content, &mut self.content,
self.theme_default.fg, self.theme_default.fg,
self.theme_default.bg, self.theme_default.bg,
Attr::Bold, Attr::BOLD,
((3, 12 + i * 10), (120 - 2, 12 + i * 10)), ((3, 12 + i * 10), (120 - 2, 12 + i * 10)),
Some(3), Some(3),
); );
@ -356,7 +356,7 @@ impl StatusPanel {
&mut self.content, &mut self.content,
self.theme_default.fg, self.theme_default.fg,
self.theme_default.bg, self.theme_default.bg,
Attr::Bold, Attr::BOLD,
((5 + column_width, y + 2), (120 - 2, y + 2)), ((5 + column_width, y + 2), (120 - 2, y + 2)),
None, None,
); );
@ -395,7 +395,7 @@ impl Component for AccountStatus {
&mut self.content, &mut self.content,
self.theme_default.fg, self.theme_default.fg,
self.theme_default.bg, self.theme_default.bg,
Attr::Bold, Attr::BOLD,
((1, 0), (width - 1, height - 1)), ((1, 0), (width - 1, height - 1)),
None, None,
); );
@ -406,7 +406,7 @@ impl Component for AccountStatus {
&mut self.content, &mut self.content,
self.theme_default.fg, self.theme_default.fg,
self.theme_default.bg, self.theme_default.bg,
Attr::Bold, Attr::BOLD,
((1, line), (width - 1, height - 1)), ((1, line), (width - 1, height - 1)),
None, None,
); );
@ -429,7 +429,7 @@ impl Component for AccountStatus {
&mut self.content, &mut self.content,
self.theme_default.fg, self.theme_default.fg,
self.theme_default.bg, self.theme_default.bg,
Attr::Bold, Attr::BOLD,
((1, line), (width - 1, height - 1)), ((1, line), (width - 1, height - 1)),
None, None,
); );
@ -474,7 +474,7 @@ impl Component for AccountStatus {
&mut self.content, &mut self.content,
self.theme_default.fg, self.theme_default.fg,
self.theme_default.bg, self.theme_default.bg,
Attr::Bold, Attr::BOLD,
((1, line), (width - 1, height - 1)), ((1, line), (width - 1, height - 1)),
None, None,
); );
@ -501,7 +501,7 @@ impl Component for AccountStatus {
&mut self.content, &mut self.content,
self.theme_default.fg, self.theme_default.fg,
self.theme_default.bg, self.theme_default.bg,
Attr::Bold, Attr::BOLD,
((1, line), (width - 1, height - 1)), ((1, line), (width - 1, height - 1)),
None, None,
); );
@ -531,7 +531,7 @@ impl Component for AccountStatus {
&mut self.content, &mut self.content,
self.theme_default.fg, self.theme_default.fg,
self.theme_default.bg, self.theme_default.bg,
Attr::Bold, Attr::BOLD,
((1, line), (width - 1, height - 1)), ((1, line), (width - 1, height - 1)),
None, None,
); );

View File

@ -492,7 +492,7 @@ impl Component for MailView {
grid, grid,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((_x, y), bottom_right), ((_x, y), bottom_right),
None, None,
); );
@ -524,7 +524,7 @@ impl Component for MailView {
grid, grid,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((x, y), bottom_right), ((x, y), bottom_right),
Some(get_x(upper_left)), Some(get_x(upper_left)),
); );
@ -537,7 +537,7 @@ impl Component for MailView {
grid, grid,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((x, y), bottom_right), ((x, y), bottom_right),
Some(get_x(upper_left)), Some(get_x(upper_left)),
); );
@ -550,7 +550,7 @@ impl Component for MailView {
grid, grid,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((x, y), bottom_right), ((x, y), bottom_right),
Some(get_x(upper_left)), Some(get_x(upper_left)),
); );
@ -743,7 +743,7 @@ impl Component for MailView {
grid, grid,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
(set_y(upper_left, y), bottom_right), (set_y(upper_left, y), bottom_right),
Some(get_x(upper_left)), Some(get_x(upper_left)),
); );

View File

@ -241,7 +241,7 @@ impl Component for EnvelopeView {
grid, grid,
Color::Byte(33), Color::Byte(33),
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
area, area,
Some(get_x(upper_left)), Some(get_x(upper_left)),
); );
@ -255,7 +255,7 @@ impl Component for EnvelopeView {
grid, grid,
Color::Byte(33), Color::Byte(33),
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
(set_y(upper_left, y + 1), bottom_right), (set_y(upper_left, y + 1), bottom_right),
Some(get_x(upper_left)), Some(get_x(upper_left)),
); );
@ -269,7 +269,7 @@ impl Component for EnvelopeView {
grid, grid,
Color::Byte(33), Color::Byte(33),
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
(set_y(upper_left, y + 1), bottom_right), (set_y(upper_left, y + 1), bottom_right),
Some(get_x(upper_left)), Some(get_x(upper_left)),
); );
@ -283,7 +283,7 @@ impl Component for EnvelopeView {
grid, grid,
Color::Byte(33), Color::Byte(33),
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
(set_y(upper_left, y + 1), bottom_right), (set_y(upper_left, y + 1), bottom_right),
Some(get_x(upper_left)), Some(get_x(upper_left)),
); );
@ -297,7 +297,7 @@ impl Component for EnvelopeView {
grid, grid,
Color::Byte(33), Color::Byte(33),
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
(set_y(upper_left, y + 1), bottom_right), (set_y(upper_left, y + 1), bottom_right),
Some(get_x(upper_left)), Some(get_x(upper_left)),
); );

View File

@ -266,7 +266,7 @@ impl ThreadView {
} else { } else {
Color::Byte(251) Color::Byte(251)
}, },
Attr::Default, Attr::DEFAULT,
( (
(e.index.0 * 4 + 1, 2 * y), (e.index.0 * 4 + 1, 2 * y),
(e.index.0 * 4 + e.heading.grapheme_width() + 1, height - 1), (e.index.0 * 4 + e.heading.grapheme_width() + 1, height - 1),
@ -348,7 +348,7 @@ impl ThreadView {
} else { } else {
Color::Byte(251) Color::Byte(251)
}, },
Attr::Default, Attr::DEFAULT,
( (
(e.index.0 * 4 + 1, 2 * y), (e.index.0 * 4 + 1, 2 * y),
(e.index.0 * 4 + e.heading.grapheme_width() + 1, height - 1), (e.index.0 * 4 + e.heading.grapheme_width() + 1, height - 1),
@ -668,7 +668,7 @@ impl ThreadView {
grid, grid,
Color::Byte(33), Color::Byte(33),
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
area, area,
Some(get_x(upper_left)), Some(get_x(upper_left)),
); );
@ -771,7 +771,7 @@ impl ThreadView {
grid, grid,
Color::Byte(33), Color::Byte(33),
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
area, area,
Some(get_x(upper_left)), Some(get_x(upper_left)),
); );

View File

@ -495,13 +495,13 @@ impl Pager {
content, content,
colors.fg, colors.fg,
colors.bg, colors.bg,
Attr::Default, Attr::DEFAULT,
((0, i), (width.saturating_sub(1), i)), ((0, i), (width.saturating_sub(1), i)),
None, None,
); );
if l.starts_with("") { if l.starts_with("") {
content[(0, i)].set_fg(Color::Byte(240)); content[(0, i)].set_fg(Color::Byte(240));
content[(0, i)].set_attrs(Attr::Bold); content[(0, i)].set_attrs(Attr::BOLD);
} }
} }
} }
@ -874,7 +874,7 @@ impl StatusBar {
fn draw_status_bar(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { fn draw_status_bar(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
let mut attribute = crate::conf::value(context, "status.bar"); let mut attribute = crate::conf::value(context, "status.bar");
if !context.settings.terminal.use_color() { if !context.settings.terminal.use_color() {
attribute.attrs |= Attr::Reverse; attribute.attrs |= Attr::REVERSE;
} }
let (x, y) = write_string_to_grid( let (x, y) = write_string_to_grid(
&self.status, &self.status,
@ -900,7 +900,7 @@ impl StatusBar {
get_x(bottom_right!(area)), get_x(bottom_right!(area)),
) )
{ {
grid[(x, y)].set_attrs(attribute.attrs | Attr::Bold); grid[(x, y)].set_attrs(attribute.attrs | Attr::BOLD);
} }
} }
@ -923,7 +923,7 @@ impl StatusBar {
grid, grid,
Color::Byte(219), Color::Byte(219),
Color::Byte(88), Color::Byte(88),
Attr::Default, Attr::DEFAULT,
area, area,
None, None,
); );
@ -931,7 +931,7 @@ impl StatusBar {
pos_inc(upper_left!(area), (self.ex_buffer.cursor(), 0)).0, pos_inc(upper_left!(area), (self.ex_buffer.cursor(), 0)).0,
y, y,
) { ) {
cell.set_attrs(Attr::Underline); cell.set_attrs(Attr::UNDERLINE);
} }
change_colors(grid, area, Color::Byte(219), Color::Byte(88)); change_colors(grid, area, Color::Byte(219), Color::Byte(88));
context.dirty_areas.push_back(area); context.dirty_areas.push_back(area);
@ -1125,7 +1125,7 @@ impl Component for StatusBar {
grid, grid,
Color::Byte(88), // DarkRed, Color::Byte(88), // DarkRed,
Color::Byte(174), //LightPink3 Color::Byte(174), //LightPink3
Attr::Default, Attr::DEFAULT,
( (
set_y( set_y(
upper_left!(hist_area), upper_left!(hist_area),
@ -1140,7 +1140,7 @@ impl Component for StatusBar {
grid, grid,
Color::White, Color::White,
Color::Byte(174), Color::Byte(174),
Attr::Default, Attr::DEFAULT,
((x + 2, y), bottom_right!(hist_area)), ((x + 2, y), bottom_right!(hist_area)),
None, None,
); );
@ -1165,7 +1165,7 @@ impl Component for StatusBar {
grid, grid,
Color::Byte(97), // MediumPurple3, Color::Byte(97), // MediumPurple3,
Color::Byte(88), //LightPink3 Color::Byte(88), //LightPink3
Attr::Default, Attr::DEFAULT,
( (
( (
get_x(upper_left) get_x(upper_left)
@ -1482,7 +1482,7 @@ impl Tabbed {
let tab_unfocused_attribute = crate::conf::value(context, "tab.unfocused"); let tab_unfocused_attribute = crate::conf::value(context, "tab.unfocused");
let mut tab_focused_attribute = crate::conf::value(context, "tab.focused"); let mut tab_focused_attribute = crate::conf::value(context, "tab.focused");
if !context.settings.terminal.use_color() { if !context.settings.terminal.use_color() {
tab_focused_attribute.attrs |= Attr::Reverse; tab_focused_attribute.attrs |= Attr::REVERSE;
} }
let mut x = get_x(upper_left); let mut x = get_x(upper_left);
@ -1683,7 +1683,7 @@ impl Component for Tabbed {
&mut self.help_content, &mut self.help_content,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Bold, Attr::BOLD,
((2, 0), (max_width.saturating_sub(2), max_length - 1)), ((2, 0), (max_width.saturating_sub(2), max_length - 1)),
None, None,
); );
@ -1692,7 +1692,7 @@ impl Component for Tabbed {
&mut self.help_content, &mut self.help_content,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((x + 1, y), (max_width.saturating_sub(2), max_length - 1)), ((x + 1, y), (max_width.saturating_sub(2), max_length - 1)),
None, None,
); );
@ -1701,7 +1701,7 @@ impl Component for Tabbed {
&mut self.help_content, &mut self.help_content,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((2, 1), (max_width.saturating_sub(2), max_length - 1)), ((2, 1), (max_width.saturating_sub(2), max_length - 1)),
None, None,
); );
@ -1712,7 +1712,7 @@ impl Component for Tabbed {
&mut self.help_content, &mut self.help_content,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((2, 2), (max_width.saturating_sub(2), max_length - 1)), ((2, 2), (max_width.saturating_sub(2), max_length - 1)),
None, None,
); );
@ -1724,7 +1724,7 @@ impl Component for Tabbed {
&mut self.help_content, &mut self.help_content,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((2, 2 + idx), (max_width.saturating_sub(2), max_length - 1)), ((2, 2 + idx), (max_width.saturating_sub(2), max_length - 1)),
None, None,
); );
@ -1738,7 +1738,7 @@ impl Component for Tabbed {
&mut self.help_content, &mut self.help_content,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Bold, Attr::BOLD,
((2, 2 + idx), (max_width.saturating_sub(2), max_length - 1)), ((2, 2 + idx), (max_width.saturating_sub(2), max_length - 1)),
None, None,
); );
@ -1747,7 +1747,7 @@ impl Component for Tabbed {
&mut self.help_content, &mut self.help_content,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((x + 2, y), (max_width.saturating_sub(2), max_length - 1)), ((x + 2, y), (max_width.saturating_sub(2), max_length - 1)),
None, None,
); );
@ -2167,7 +2167,7 @@ impl<T: 'static + PartialEq + Debug + Clone + Sync + Send> Component for UIDialo
let shortcuts = self.get_shortcuts(context); let shortcuts = self.get_shortcuts(context);
let mut highlighted_attrs = crate::conf::value(context, "widgets.options.highlighted"); let mut highlighted_attrs = crate::conf::value(context, "widgets.options.highlighted");
if !context.settings.terminal.use_color() { if !context.settings.terminal.use_color() {
highlighted_attrs.attrs |= Attr::Reverse; highlighted_attrs.attrs |= Attr::REVERSE;
} }
match (event, self.cursor) { match (event, self.cursor) {
(UIEvent::Input(Key::Char('\n')), _) if self.single_only => { (UIEvent::Input(Key::Char('\n')), _) if self.single_only => {
@ -2188,7 +2188,7 @@ impl<T: 'static + PartialEq + Debug + Clone + Sync + Send> Component for UIDialo
&mut self.content, &mut self.content,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((3, c + 2), (width - 2, c + 2)), ((3, c + 2), (width - 2, c + 2)),
None, None,
); );
@ -2198,7 +2198,7 @@ impl<T: 'static + PartialEq + Debug + Clone + Sync + Send> Component for UIDialo
&mut self.content, &mut self.content,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((3, c + 2), (width - 2, c + 2)), ((3, c + 2), (width - 2, c + 2)),
None, None,
); );
@ -2240,7 +2240,7 @@ impl<T: 'static + PartialEq + Debug + Clone + Sync + Send> Component for UIDialo
self.content[c] self.content[c]
.set_fg(Color::Default) .set_fg(Color::Default)
.set_bg(Color::Default) .set_bg(Color::Default)
.set_attrs(Attr::Default); .set_attrs(Attr::DEFAULT);
} }
for c in self.content.row_iter(2..(width - 2), c + 1) { for c in self.content.row_iter(2..(width - 2), c + 1) {
self.content[c] self.content[c]
@ -2256,7 +2256,7 @@ impl<T: 'static + PartialEq + Debug + Clone + Sync + Send> Component for UIDialo
self.content[c] self.content[c]
.set_fg(Color::Default) .set_fg(Color::Default)
.set_bg(Color::Default) .set_bg(Color::Default)
.set_attrs(Attr::Default); .set_attrs(Attr::DEFAULT);
} }
for c in self.content.row_iter(2..4, c + 1) { for c in self.content.row_iter(2..4, c + 1) {
self.content[c] self.content[c]
@ -2280,14 +2280,14 @@ impl<T: 'static + PartialEq + Debug + Clone + Sync + Send> Component for UIDialo
self.content[c] self.content[c]
.set_fg(Color::Default) .set_fg(Color::Default)
.set_bg(Color::Default) .set_bg(Color::Default)
.set_attrs(Attr::Default); .set_attrs(Attr::DEFAULT);
} }
let c = self.entries.len().saturating_sub(1); let c = self.entries.len().saturating_sub(1);
self.cursor = SelectorCursor::Entry(c); self.cursor = SelectorCursor::Entry(c);
let mut highlighted_attrs = let mut highlighted_attrs =
crate::conf::value(context, "widgets.options.highlighted"); crate::conf::value(context, "widgets.options.highlighted");
if !context.settings.terminal.use_color() { if !context.settings.terminal.use_color() {
highlighted_attrs.attrs |= Attr::Reverse; highlighted_attrs.attrs |= Attr::REVERSE;
} }
for c in self.content.row_iter(2..4, c + 2) { for c in self.content.row_iter(2..4, c + 2) {
self.content[c] self.content[c]
@ -2308,7 +2308,7 @@ impl<T: 'static + PartialEq + Debug + Clone + Sync + Send> Component for UIDialo
self.content[c] self.content[c]
.set_fg(Color::Default) .set_fg(Color::Default)
.set_bg(Color::Default) .set_bg(Color::Default)
.set_attrs(Attr::Default); .set_attrs(Attr::DEFAULT);
} }
for c in self.content.row_iter(2..(width - 2), c + 3) { for c in self.content.row_iter(2..(width - 2), c + 3) {
self.content[c] self.content[c]
@ -2324,7 +2324,7 @@ impl<T: 'static + PartialEq + Debug + Clone + Sync + Send> Component for UIDialo
self.content[c] self.content[c]
.set_fg(Color::Default) .set_fg(Color::Default)
.set_bg(Color::Default) .set_bg(Color::Default)
.set_attrs(Attr::Default); .set_attrs(Attr::DEFAULT);
} }
for c in self.content.row_iter(2..4, c + 3) { for c in self.content.row_iter(2..4, c + 3) {
self.content[c] self.content[c]
@ -2345,7 +2345,7 @@ impl<T: 'static + PartialEq + Debug + Clone + Sync + Send> Component for UIDialo
self.content[c] self.content[c]
.set_fg(Color::Default) .set_fg(Color::Default)
.set_bg(Color::Default) .set_bg(Color::Default)
.set_attrs(Attr::Default); .set_attrs(Attr::DEFAULT);
} }
for c in self.content.row_iter( for c in self.content.row_iter(
((width - "OK Cancel".len()) / 2)..((width - "OK Cancel".len()) / 2 + 1), ((width - "OK Cancel".len()) / 2)..((width - "OK Cancel".len()) / 2 + 1),
@ -2370,7 +2370,7 @@ impl<T: 'static + PartialEq + Debug + Clone + Sync + Send> Component for UIDialo
self.content[c] self.content[c]
.set_fg(Color::Default) .set_fg(Color::Default)
.set_bg(Color::Default) .set_bg(Color::Default)
.set_attrs(Attr::Default); .set_attrs(Attr::DEFAULT);
} }
for c in self.content.row_iter( for c in self.content.row_iter(
((width - "OK Cancel".len()) / 2 + 6) ((width - "OK Cancel".len()) / 2 + 6)
@ -2455,7 +2455,7 @@ impl Component for UIConfirmationDialog {
let shortcuts = self.get_shortcuts(context); let shortcuts = self.get_shortcuts(context);
let mut highlighted_attrs = crate::conf::value(context, "widgets.options.highlighted"); let mut highlighted_attrs = crate::conf::value(context, "widgets.options.highlighted");
if !context.settings.terminal.use_color() { if !context.settings.terminal.use_color() {
highlighted_attrs.attrs |= Attr::Reverse; highlighted_attrs.attrs |= Attr::REVERSE;
} }
match (event, self.cursor) { match (event, self.cursor) {
(UIEvent::Input(Key::Char('\n')), _) if self.single_only => { (UIEvent::Input(Key::Char('\n')), _) if self.single_only => {
@ -2476,7 +2476,7 @@ impl Component for UIConfirmationDialog {
&mut self.content, &mut self.content,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((3, c + 2), (width - 2, c + 2)), ((3, c + 2), (width - 2, c + 2)),
None, None,
); );
@ -2486,7 +2486,7 @@ impl Component for UIConfirmationDialog {
&mut self.content, &mut self.content,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((3, c + 2), (width - 2, c + 2)), ((3, c + 2), (width - 2, c + 2)),
None, None,
); );
@ -2528,7 +2528,7 @@ impl Component for UIConfirmationDialog {
self.content[c] self.content[c]
.set_fg(Color::Default) .set_fg(Color::Default)
.set_bg(Color::Default) .set_bg(Color::Default)
.set_attrs(Attr::Default); .set_attrs(Attr::DEFAULT);
} }
for c in self.content.row_iter(2..(width - 2), c + 1) { for c in self.content.row_iter(2..(width - 2), c + 1) {
self.content[c] self.content[c]
@ -2544,7 +2544,7 @@ impl Component for UIConfirmationDialog {
self.content[c] self.content[c]
.set_fg(Color::Default) .set_fg(Color::Default)
.set_bg(Color::Default) .set_bg(Color::Default)
.set_attrs(Attr::Default); .set_attrs(Attr::DEFAULT);
} }
for c in self.content.row_iter(2..4, c + 1) { for c in self.content.row_iter(2..4, c + 1) {
self.content[c] self.content[c]
@ -2568,14 +2568,14 @@ impl Component for UIConfirmationDialog {
self.content[c] self.content[c]
.set_fg(Color::Default) .set_fg(Color::Default)
.set_bg(Color::Default) .set_bg(Color::Default)
.set_attrs(Attr::Default); .set_attrs(Attr::DEFAULT);
} }
let c = self.entries.len().saturating_sub(1); let c = self.entries.len().saturating_sub(1);
self.cursor = SelectorCursor::Entry(c); self.cursor = SelectorCursor::Entry(c);
let mut highlighted_attrs = let mut highlighted_attrs =
crate::conf::value(context, "widgets.options.highlighted"); crate::conf::value(context, "widgets.options.highlighted");
if !context.settings.terminal.use_color() { if !context.settings.terminal.use_color() {
highlighted_attrs.attrs |= Attr::Reverse; highlighted_attrs.attrs |= Attr::REVERSE;
} }
for c in self.content.row_iter(2..4, c + 2) { for c in self.content.row_iter(2..4, c + 2) {
self.content[c] self.content[c]
@ -2596,7 +2596,7 @@ impl Component for UIConfirmationDialog {
self.content[c] self.content[c]
.set_fg(Color::Default) .set_fg(Color::Default)
.set_bg(Color::Default) .set_bg(Color::Default)
.set_attrs(Attr::Default); .set_attrs(Attr::DEFAULT);
} }
for c in self.content.row_iter(2..(width - 2), c + 3) { for c in self.content.row_iter(2..(width - 2), c + 3) {
self.content[c] self.content[c]
@ -2612,7 +2612,7 @@ impl Component for UIConfirmationDialog {
self.content[c] self.content[c]
.set_fg(Color::Default) .set_fg(Color::Default)
.set_bg(Color::Default) .set_bg(Color::Default)
.set_attrs(Attr::Default); .set_attrs(Attr::DEFAULT);
} }
for c in self.content.row_iter(2..4, c + 3) { for c in self.content.row_iter(2..4, c + 3) {
self.content[c] self.content[c]
@ -2633,7 +2633,7 @@ impl Component for UIConfirmationDialog {
self.content[c] self.content[c]
.set_fg(Color::Default) .set_fg(Color::Default)
.set_bg(Color::Default) .set_bg(Color::Default)
.set_attrs(Attr::Default); .set_attrs(Attr::DEFAULT);
} }
for c in self.content.row_iter( for c in self.content.row_iter(
((width - "OK Cancel".len()) / 2)..((width - "OK Cancel".len()) / 2 + 1), ((width - "OK Cancel".len()) / 2)..((width - "OK Cancel".len()) / 2 + 1),
@ -2658,7 +2658,7 @@ impl Component for UIConfirmationDialog {
self.content[c] self.content[c]
.set_fg(Color::Default) .set_fg(Color::Default)
.set_bg(Color::Default) .set_bg(Color::Default)
.set_attrs(Attr::Default); .set_attrs(Attr::DEFAULT);
} }
for c in self.content.row_iter( for c in self.content.row_iter(
((width - "OK Cancel".len()) / 2 + 6) ((width - "OK Cancel".len()) / 2 + 6)
@ -2767,7 +2767,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send, F: 'static + Sync + Send> Selec
&mut content, &mut content,
Color::Byte(8), Color::Byte(8),
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((0, 0), (width - 1, 0)), ((0, 0), (width - 1, 0)),
None, None,
); );
@ -2776,7 +2776,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send, F: 'static + Sync + Send> Selec
&mut content, &mut content,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((2, 0), (width - 1, 0)), ((2, 0), (width - 1, 0)),
None, None,
); );
@ -2786,7 +2786,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send, F: 'static + Sync + Send> Selec
&mut content, &mut content,
Color::Byte(8), Color::Byte(8),
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((x + i, 0), (width - 1, 0)), ((x + i, 0), (width - 1, 0)),
None, None,
); );
@ -2796,7 +2796,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send, F: 'static + Sync + Send> Selec
&mut content, &mut content,
Color::Byte(8), Color::Byte(8),
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((width - 1, 0), (width - 1, 0)), ((width - 1, 0), (width - 1, 0)),
None, None,
); );
@ -2805,7 +2805,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send, F: 'static + Sync + Send> Selec
&mut content, &mut content,
Color::Byte(8), Color::Byte(8),
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((0, height - 1), (width - 1, height - 1)), ((0, height - 1), (width - 1, height - 1)),
None, None,
); );
@ -2818,7 +2818,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send, F: 'static + Sync + Send> Selec
&mut content, &mut content,
Color::Byte(8), Color::Byte(8),
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((1, height - 1), (width - 2, height - 1)), ((1, height - 1), (width - 2, height - 1)),
None, None,
); );
@ -2827,7 +2827,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send, F: 'static + Sync + Send> Selec
&mut content, &mut content,
Color::Byte(8), Color::Byte(8),
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((width - 1, height - 1), (width - 1, height - 1)), ((width - 1, height - 1), (width - 1, height - 1)),
None, None,
); );
@ -2837,7 +2837,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send, F: 'static + Sync + Send> Selec
&mut content, &mut content,
Color::Byte(8), Color::Byte(8),
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((0, i), (width - 1, i)), ((0, i), (width - 1, i)),
None, None,
); );
@ -2846,14 +2846,14 @@ impl<T: PartialEq + Debug + Clone + Sync + Send, F: 'static + Sync + Send> Selec
&mut content, &mut content,
Color::Byte(8), Color::Byte(8),
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((width - 1, i), (width - 1, i)), ((width - 1, i), (width - 1, i)),
None, None,
); );
} }
let mut highlighted_attrs = crate::conf::value(context, "widgets.options.highlighted"); let mut highlighted_attrs = crate::conf::value(context, "widgets.options.highlighted");
if !context.settings.terminal.use_color() { if !context.settings.terminal.use_color() {
highlighted_attrs.attrs |= Attr::Reverse; highlighted_attrs.attrs |= Attr::REVERSE;
} }
if single_only { if single_only {
for (i, e) in entries.iter().enumerate() { for (i, e) in entries.iter().enumerate() {
@ -2869,7 +2869,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send, F: 'static + Sync + Send> Selec
if i == 0 { if i == 0 {
highlighted_attrs.attrs highlighted_attrs.attrs
} else { } else {
Attr::Default Attr::DEFAULT
}, },
((2, i + 2), (width - 1, i + 2)), ((2, i + 2), (width - 1, i + 2)),
None, None,
@ -2882,7 +2882,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send, F: 'static + Sync + Send> Selec
&mut content, &mut content,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((2, i + 2), (width - 1, i + 2)), ((2, i + 2), (width - 1, i + 2)),
None, None,
); );
@ -2903,7 +2903,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send, F: 'static + Sync + Send> Selec
&mut content, &mut content,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Bold, Attr::BOLD,
( (
((width - "OK Cancel".len()) / 2, height - 3), ((width - "OK Cancel".len()) / 2, height - 3),
(width - 1, height - 3), (width - 1, height - 3),

View File

@ -439,7 +439,7 @@ impl Component for FormWidget {
let mut field_attrs = let mut field_attrs =
crate::conf::value(context, "widgets.form.highlighted"); crate::conf::value(context, "widgets.form.highlighted");
if !context.settings.terminal.use_color() { if !context.settings.terminal.use_color() {
field_attrs.attrs |= Attr::Reverse; field_attrs.attrs |= Attr::REVERSE;
} }
for row in grid.bounds_iter(( for row in grid.bounds_iter((
pos_inc(upper_left, (0, i)), pos_inc(upper_left, (0, i)),
@ -670,7 +670,7 @@ where
} else { } else {
theme_default.bg theme_default.bg
}, },
Attr::Bold, Attr::BOLD,
( (
pos_inc(upper_left, (len, 0)), pos_inc(upper_left, (len, 0)),
pos_inc(upper_left, (cur_len + len, 0)), pos_inc(upper_left, (cur_len + len, 0)),
@ -847,7 +847,7 @@ impl AutoComplete {
.unwrap_or(0) .unwrap_or(0)
+ 1, + 1,
entries.len(), entries.len(),
Cell::with_style(Color::Byte(23), Color::Byte(7), Attr::Default), Cell::with_style(Color::Byte(23), Color::Byte(7), Attr::DEFAULT),
); );
let width = content.cols(); let width = content.cols();
for (i, e) in entries.iter().enumerate() { for (i, e) in entries.iter().enumerate() {
@ -856,7 +856,7 @@ impl AutoComplete {
&mut content, &mut content,
Color::Byte(23), Color::Byte(23),
Color::Byte(7), Color::Byte(7),
Attr::Default, Attr::DEFAULT,
((0, i), (width - 1, i)), ((0, i), (width - 1, i)),
None, None,
); );
@ -865,7 +865,7 @@ impl AutoComplete {
&mut content, &mut content,
Color::Byte(23), Color::Byte(23),
Color::Byte(7), Color::Byte(7),
Attr::Default, Attr::DEFAULT,
((x + 2, i), (width - 1, i)), ((x + 2, i), (width - 1, i)),
None, None,
); );
@ -874,7 +874,7 @@ impl AutoComplete {
&mut content, &mut content,
Color::Byte(23), Color::Byte(23),
Color::Byte(7), Color::Byte(7),
Attr::Default, Attr::DEFAULT,
((width - 1, i), (width - 1, i)), ((width - 1, i), (width - 1, i)),
None, None,
); );

View File

@ -262,7 +262,7 @@ impl Default for ThemeValue<Color> {
impl Default for ThemeValue<Attr> { impl Default for ThemeValue<Attr> {
fn default() -> Self { fn default() -> Self {
ThemeValue::Value(Attr::Default) ThemeValue::Value(Attr::DEFAULT)
} }
} }
@ -272,7 +272,7 @@ impl<'de> Deserialize<'de> for ThemeValue<Attr> {
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
if let Ok(s) = <String>::deserialize(deserializer) { if let Ok(s) = <String>::deserialize(deserializer) {
if let Ok(c) = Attr::from_string_de::<'de, D>(s.clone()) { if let Ok(c) = Attr::from_string_de::<'de, D, String>(s.clone()) {
Ok(ThemeValue::Value(c)) Ok(ThemeValue::Value(c))
} else { } else {
Ok(ThemeValue::Link(s.into())) Ok(ThemeValue::Link(s.into()))
@ -473,7 +473,7 @@ impl Default for Theme {
dark.insert($key.into(), ThemeAttributeInner::default()); dark.insert($key.into(), ThemeAttributeInner::default());
}; };
} }
add!("theme_default", dark = { fg: Color::Default, bg: Color::Default, attrs: Attr::Default }, light = { fg: Color::Default, bg: Color::Default, attrs: Attr::Default }); add!("theme_default", dark = { fg: Color::Default, bg: Color::Default, attrs: Attr::DEFAULT }, light = { fg: Color::Default, bg: Color::Default, attrs: Attr::DEFAULT });
add!("status.bar", dark = { fg: Color::Byte(123), bg: Color::Byte(26) }, light = { fg: Color::Byte(123), bg: Color::Byte(26) }); add!("status.bar", dark = { fg: Color::Byte(123), bg: Color::Byte(26) }, light = { fg: Color::Byte(123), bg: Color::Byte(26) });
add!("status.notification", dark = { fg: Color::Byte(219), bg: Color::Byte(88) }, light = { fg: Color::Byte(219), bg: Color::Byte(88) }); add!("status.notification", dark = { fg: Color::Byte(219), bg: Color::Byte(88) }, light = { fg: Color::Byte(219), bg: Color::Byte(88) });
@ -482,13 +482,13 @@ impl Default for Theme {
add!("tab.bar"); add!("tab.bar");
add!( add!(
"widgets.list.header", "widgets.list.header",
dark = { fg: Color::Black, bg: Color::White, attrs: Attr::Bold }, dark = { fg: Color::Black, bg: Color::White, attrs: Attr::BOLD },
light = {fg: Color::White, bg: Color::Black, attrs: Attr::Bold } light = {fg: Color::White, bg: Color::Black, attrs: Attr::BOLD }
); );
add!( add!(
"widgets.form.label", "widgets.form.label",
dark = { attrs: Attr::Bold }, dark = { attrs: Attr::BOLD },
light = { attrs: Attr::Bold } light = { attrs: Attr::BOLD }
); );
add!("widgets.form.field"); add!("widgets.form.field");
add!("widgets.form.highlighted", light = { bg: Color::Byte(246) }, dark = { bg: Color::Byte(246) }); add!("widgets.form.highlighted", light = { bg: Color::Byte(246) }, dark = { bg: Color::Byte(246) });
@ -567,7 +567,6 @@ impl Default for Theme {
dark = { dark = {
fg: Color::Byte(0), fg: Color::Byte(0),
bg: Color::Byte(251) bg: Color::Byte(251)
}, },
light = { light = {
fg: Color::Byte(0), fg: Color::Byte(0),
@ -725,17 +724,17 @@ impl Default for Theme {
light = { light = {
fg: Color::White, fg: Color::White,
bg: Color::Byte(8), bg: Color::Byte(8),
attrs: Attr::Bold attrs: Attr::BOLD
}, },
dark = { dark = {
fg: Color::White, fg: Color::White,
bg: Color::Byte(8), bg: Color::Byte(8),
attrs: Attr::Bold attrs: Attr::BOLD
} }
); );
add!("pager.highlight_search", light = { fg: Color::White, bg: Color::Byte(6) /* Teal */, attrs: Attr::Bold }, dark = { fg: Color::White, bg: Color::Byte(6) /* Teal */, attrs: Attr::Bold }); add!("pager.highlight_search", light = { fg: Color::White, bg: Color::Byte(6) /* Teal */, attrs: Attr::BOLD }, dark = { fg: Color::White, bg: Color::Byte(6) /* Teal */, attrs: Attr::BOLD });
add!("pager.highlight_search_current", light = { fg: Color::White, bg: Color::Byte(17) /* NavyBlue */, attrs: Attr::Bold }, dark = { fg: Color::White, bg: Color::Byte(17) /* NavyBlue */, attrs: Attr::Bold }); add!("pager.highlight_search_current", light = { fg: Color::White, bg: Color::Byte(17) /* NavyBlue */, attrs: Attr::BOLD }, dark = { fg: Color::White, bg: Color::Byte(17) /* NavyBlue */, attrs: Attr::BOLD });
Theme { Theme {
light, light,
dark, dark,

View File

@ -695,7 +695,7 @@ impl State {
.unwrap(); .unwrap();
let mut current_fg = Color::Default; let mut current_fg = Color::Default;
let mut current_bg = Color::Default; let mut current_bg = Color::Default;
let mut current_attrs = Attr::Default; let mut current_attrs = Attr::DEFAULT;
write!(stdout, "\x1B[m").unwrap(); write!(stdout, "\x1B[m").unwrap();
for x in x_start..=x_end { for x in x_start..=x_end {
let c = &grid[(x, y)]; let c = &grid[(x, y)];
@ -730,7 +730,7 @@ impl State {
cursor::Goto(x_start as u16 + 1, (y + 1) as u16) cursor::Goto(x_start as u16 + 1, (y + 1) as u16)
) )
.unwrap(); .unwrap();
let mut current_attrs = Attr::Default; let mut current_attrs = Attr::DEFAULT;
write!(stdout, "\x1B[m").unwrap(); write!(stdout, "\x1B[m").unwrap();
for x in x_start..=x_end { for x in x_start..=x_end {
let c = &grid[(x, y)]; let c = &grid[(x, y)];

View File

@ -448,11 +448,11 @@ impl Cell {
/// # Examples /// # Examples
/// ///
/// ```no_run /// ```no_run
/// let cell = Cell::new('x', Color::Default, Color::Green, Attr::Default); /// let cell = Cell::new('x', Color::Default, Color::Green, Attr::DEFAULT);
/// assert_eq!(cell.ch(), 'x'); /// assert_eq!(cell.ch(), 'x');
/// assert_eq!(cell.fg(), Color::Default); /// assert_eq!(cell.fg(), Color::Default);
/// assert_eq!(cell.bg(), Color::Green); /// assert_eq!(cell.bg(), Color::Green);
/// assert_eq!(cell.attrs(), Attr::Default); /// assert_eq!(cell.attrs(), Attr::DEFAULT);
/// ``` /// ```
pub fn new(ch: char, fg: Color, bg: Color, attrs: Attr) -> Cell { pub fn new(ch: char, fg: Color, bg: Color, attrs: Attr) -> Cell {
Cell { Cell {
@ -475,10 +475,10 @@ impl Cell {
/// assert_eq!(cell.ch(), 'x'); /// assert_eq!(cell.ch(), 'x');
/// assert_eq!(cell.fg(), Color::Default); /// assert_eq!(cell.fg(), Color::Default);
/// assert_eq!(cell.bg(), Color::Default); /// assert_eq!(cell.bg(), Color::Default);
/// assert_eq!(cell.attrs(), Attr::Default); /// assert_eq!(cell.attrs(), Attr::DEFAULT);
/// ``` /// ```
pub fn with_char(ch: char) -> Cell { pub fn with_char(ch: char) -> Cell {
Cell::new(ch, Color::Default, Color::Default, Attr::Default) Cell::new(ch, Color::Default, Color::Default, Attr::DEFAULT)
} }
/// Creates a new `Cell` with the given style and a blank `char`. /// Creates a new `Cell` with the given style and a blank `char`.
@ -486,10 +486,10 @@ impl Cell {
/// # Examples /// # Examples
/// ///
/// ```no_run /// ```no_run
/// let mut cell = Cell::with_style(Color::Default, Color::Red, Attr::Bold); /// let mut cell = Cell::with_style(Color::Default, Color::Red, Attr::BOLD);
/// assert_eq!(cell.fg(), Color::Default); /// assert_eq!(cell.fg(), Color::Default);
/// assert_eq!(cell.bg(), Color::Red); /// assert_eq!(cell.bg(), Color::Red);
/// assert_eq!(cell.attrs(), Attr::Bold); /// assert_eq!(cell.attrs(), Attr::BOLD);
/// assert_eq!(cell.ch(), ' '); /// assert_eq!(cell.ch(), ' ');
/// ``` /// ```
pub fn with_style(fg: Color, bg: Color, attr: Attr) -> Cell { pub fn with_style(fg: Color, bg: Color, attr: Attr) -> Cell {
@ -531,7 +531,7 @@ impl Cell {
/// # Examples /// # Examples
/// ///
/// ```no_run /// ```no_run
/// let mut cell = Cell::with_style(Color::Blue, Color::Default, Attr::Default); /// let mut cell = Cell::with_style(Color::Blue, Color::Default, Attr::DEFAULT);
/// assert_eq!(cell.fg(), Color::Blue); /// assert_eq!(cell.fg(), Color::Blue);
/// ``` /// ```
pub fn fg(&self) -> Color { pub fn fg(&self) -> Color {
@ -561,7 +561,7 @@ impl Cell {
/// # Examples /// # Examples
/// ///
/// ```no_run /// ```no_run
/// let mut cell = Cell::with_style(Color::Default, Color::Green, Attr::Default); /// let mut cell = Cell::with_style(Color::Default, Color::Green, Attr::DEFAULT);
/// assert_eq!(cell.bg(), Color::Green); /// assert_eq!(cell.bg(), Color::Green);
/// ``` /// ```
pub fn bg(&self) -> Color { pub fn bg(&self) -> Color {
@ -633,7 +633,7 @@ impl Default for Cell {
/// assert_eq!(cell.bg(), Color::Default); /// assert_eq!(cell.bg(), Color::Default);
/// ``` /// ```
fn default() -> Cell { fn default() -> Cell {
Cell::new(' ', Color::Default, Color::Default, Attr::Default) Cell::new(' ', Color::Default, Color::Default, Attr::DEFAULT)
} }
} }
@ -642,7 +642,7 @@ impl Default for Cell {
/// `Color::Default` represents the default color of the underlying terminal. /// `Color::Default` represents the default color of the underlying terminal.
/// ///
/// The eight basic colors may be used directly and correspond to 0x00..0x07 in the 8-bit (256) /// The eight basic colors may be used directly and correspond to 0x00..0x07 in the 8-bit (256)
/// color range; in addition, the eight basic colors coupled with `Attr::Bold` correspond to /// color range; in addition, the eight basic colors coupled with `Attr::BOLD` correspond to
/// 0x08..0x0f in the 8-bit color range. /// 0x08..0x0f in the 8-bit color range.
/// ///
/// `Color::Byte(..)` may be used to specify a color in the 8-bit range. /// `Color::Byte(..)` may be used to specify a color in the 8-bit range.
@ -1362,83 +1362,105 @@ impl Serialize for Color {
} }
} }
/// The attributes of a `Cell`. bitflags::bitflags! {
/// /// The attributes of a `Cell`.
/// `Attr` enumerates all combinations of attributes a given style may have. ///
/// /// `Attr` enumerates all combinations of attributes a given style may have.
/// `Attr::Default` represents no attribute. ///
/// /// `Attr::DEFAULT` represents no attribute.
/// # Examples ///
/// /// # Examples
/// ```no_run ///
/// // Default attribute. /// ```no_run
/// let def = Attr::Default; /// // Default attribute.
/// /// let def = Attr::DEFAULT;
/// // Base attribute. ///
/// let base = Attr::Bold; /// // Base attribute.
/// /// let base = Attr::BOLD;
/// // Combination. ///
/// let comb = Attr::UnderlineReverse; /// // Combination.
/// ``` /// let comb = Attr::UNDERLINE | Attr::REVERSE;
#[derive(Debug, Copy, Clone, PartialEq, Eq)] /// ```
pub enum Attr { pub struct Attr: u8 {
/// Terminal default. /// Terminal default.
Default = 0b000, const DEFAULT = 0b000_0000;
Bold = 0b001, const BOLD = 0b000_0001;
Underline = 0b100, const DIM = 0b000_0010;
BoldUnderline = 0b011, const ITALICS = 0b000_0100;
Reverse = 0b010, const UNDERLINE = 0b000_1000;
BoldReverse = 0b101, const BLINK = 0b001_0000;
UnderlineReverse = 0b110, const REVERSE = 0b010_0000;
BoldReverseUnderline = 0b111, const HIDDEN = 0b100_0000;
}
impl core::ops::BitOr for Attr {
type Output = Attr;
fn bitor(self, rhs: Self) -> Self::Output {
match self as u8 | rhs as u8 {
0b000 => Attr::Default,
0b001 => Attr::Bold,
0b100 => Attr::Underline,
0b011 => Attr::BoldUnderline,
0b010 => Attr::Reverse,
0b101 => Attr::BoldReverse,
0b110 => Attr::UnderlineReverse,
0b111 => Attr::BoldReverseUnderline,
_ => unsafe { std::hint::unreachable_unchecked() },
}
}
}
impl core::ops::BitAnd for Attr {
type Output = bool;
fn bitand(self, rhs: Self) -> Self::Output {
self as u8 & rhs as u8 > 0
}
}
impl core::ops::BitOrAssign for Attr {
fn bitor_assign(&mut self, rhs: Attr) {
use Attr::*;
*self = match *self as u8 | rhs as u8 {
0b000 => Default,
0b001 => Bold,
0b100 => Underline,
0b011 => BoldUnderline,
0b010 => Reverse,
0b101 => BoldReverse,
0b110 => UnderlineReverse,
0b111 => BoldReverseUnderline,
_ => unsafe { std::hint::unreachable_unchecked() },
};
} }
} }
impl Default for Attr { impl Default for Attr {
fn default() -> Self { fn default() -> Self {
Attr::Default Attr::DEFAULT
}
}
impl fmt::Display for Attr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Attr::DEFAULT => write!(f, "Default"),
Attr::BOLD => write!(f, "Bold"),
Attr::DIM => write!(f, "Dim"),
Attr::ITALICS => write!(f, "Italics"),
Attr::UNDERLINE => write!(f, "Underline"),
Attr::BLINK => write!(f, "Blink"),
Attr::REVERSE => write!(f, "Reverse"),
Attr::HIDDEN => write!(f, "Hidden"),
combination => {
let mut ctr = 0;
if combination.intersects(Attr::BOLD) {
ctr += 1;
Attr::BOLD.fmt(f)?;
}
if combination.intersects(Attr::DIM) {
if ctr > 0 {
write!(f, "|")?;
}
ctr += 1;
Attr::DIM.fmt(f)?;
}
if combination.intersects(Attr::ITALICS) {
if ctr > 0 {
write!(f, "|")?;
}
ctr += 1;
Attr::ITALICS.fmt(f)?;
}
if combination.intersects(Attr::UNDERLINE) {
if ctr > 0 {
write!(f, "|")?;
}
ctr += 1;
Attr::UNDERLINE.fmt(f)?;
}
if combination.intersects(Attr::BLINK) {
if ctr > 0 {
write!(f, "|")?;
}
ctr += 1;
Attr::BLINK.fmt(f)?;
}
if combination.intersects(Attr::REVERSE) {
if ctr > 0 {
write!(f, "|")?;
}
ctr += 1;
Attr::REVERSE.fmt(f)?;
}
if combination.intersects(Attr::HIDDEN) {
if ctr > 0 {
write!(f, "|")?;
}
Attr::HIDDEN.fmt(f)?;
}
write!(f, "")
}
}
} }
} }
@ -1448,9 +1470,9 @@ impl<'de> Deserialize<'de> for Attr {
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
if let Ok(s) = <String>::deserialize(deserializer) { if let Ok(s) = <String>::deserialize(deserializer) {
Attr::from_string_de::<'de, D>(s) Attr::from_string_de::<'de, D, String>(s)
} else { } else {
Err(de::Error::custom("invalid attr value")) Err(de::Error::custom("Attributes value must be a string."))
} }
} }
} }
@ -1460,52 +1482,93 @@ impl Serialize for Attr {
where where
S: Serializer, S: Serializer,
{ {
match self { serializer.serialize_str(&self.to_string())
Attr::Default => serializer.serialize_str("Default"),
Attr::Bold => serializer.serialize_str("Bold"),
Attr::Underline => serializer.serialize_str("Underline"),
Attr::BoldUnderline => serializer.serialize_str("BoldUnderline"),
Attr::Reverse => serializer.serialize_str("Reverse"),
Attr::BoldReverse => serializer.serialize_str("BoldReverse"),
Attr::UnderlineReverse => serializer.serialize_str("UnderlineReverse"),
Attr::BoldReverseUnderline => serializer.serialize_str("BoldReverseUnderline"),
}
} }
} }
impl Attr { impl Attr {
pub fn from_string_de<'de, D>(s: String) -> std::result::Result<Self, D::Error> pub fn from_string_de<'de, D, T: AsRef<str>>(s: T) -> std::result::Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
match s.as_str() { match s.as_ref().trim() {
"Default" => Ok(Attr::Default), "Default" => Ok(Attr::DEFAULT),
"Bold" => Ok(Attr::Bold), "Dim" => Ok(Attr::DIM),
"Underline" => Ok(Attr::Underline), "Bold" => Ok(Attr::BOLD),
"BoldUnderline" => Ok(Attr::BoldUnderline), "Italics" => Ok(Attr::ITALICS),
"Reverse" => Ok(Attr::Reverse), "Underline" => Ok(Attr::UNDERLINE),
"BoldReverse" => Ok(Attr::BoldReverse), "Blink" => Ok(Attr::BLINK),
"UnderlineReverse" => Ok(Attr::UnderlineReverse), "Reverse" => Ok(Attr::REVERSE),
"BoldReverseUnderline" => Ok(Attr::BoldReverseUnderline), "Hidden" => Ok(Attr::HIDDEN),
_ => Err(de::Error::custom("invalid attr value")), combination if combination.contains("|") => {
let mut ret = Attr::DEFAULT;
for c in combination.trim().split("|") {
ret |= Self::from_string_de::<'de, D, &str>(c)?;
}
Ok(ret)
}
_ => Err(de::Error::custom(
r#"Text attribute value must either be a single attribute (eg "Bold") or a combination of attributes separated by "|" (eg "Bold|Underline"). Valid attributes are "Default", "Bold", "Italics", "Underline", "Blink", "Reverse" and "Hidden"."#,
)),
} }
} }
pub fn write(self, prev: Attr, stdout: &mut crate::StateStdout) -> std::io::Result<()> { pub fn write(self, prev: Attr, stdout: &mut crate::StateStdout) -> std::io::Result<()> {
use std::io::Write; use std::io::Write;
match (self & Attr::Bold, prev & Attr::Bold) { match (self.intersects(Attr::BOLD), prev.intersects(Attr::BOLD)) {
(true, true) | (false, false) => Ok(()), (true, true) | (false, false) => Ok(()),
(false, true) => write!(stdout, "\x1B[22m"), (false, true) => write!(stdout, "\x1B[22m"),
(true, false) => write!(stdout, "\x1B[1m"), (true, false) => write!(stdout, "\x1B[1m"),
} }
.and_then(|_| match (self & Attr::Underline, prev & Attr::Underline) { .and_then(
(true, true) | (false, false) => Ok(()), |_| match (self.intersects(Attr::DIM), prev.intersects(Attr::DIM)) {
(false, true) => write!(stdout, "\x1B[24m"), (true, true) | (false, false) => Ok(()),
(true, false) => write!(stdout, "\x1B[4m"), (false, true) => write!(stdout, "\x1B[22m"),
(true, false) => write!(stdout, "\x1B[2m"),
},
)
.and_then(|_| {
match (
self.intersects(Attr::ITALICS),
prev.intersects(Attr::ITALICS),
) {
(true, true) | (false, false) => Ok(()),
(false, true) => write!(stdout, "\x1B[23m"),
(true, false) => write!(stdout, "\x1B[3m"),
}
}) })
.and_then(|_| match (self & Attr::Reverse, prev & Attr::Reverse) { .and_then(|_| {
(true, true) | (false, false) => Ok(()), match (
(false, true) => write!(stdout, "\x1B[27m"), self.intersects(Attr::UNDERLINE),
(true, false) => write!(stdout, "\x1B[7m"), prev.intersects(Attr::UNDERLINE),
) {
(true, true) | (false, false) => Ok(()),
(false, true) => write!(stdout, "\x1B[24m"),
(true, false) => write!(stdout, "\x1B[4m"),
}
})
.and_then(
|_| match (self.intersects(Attr::BLINK), prev.intersects(Attr::BLINK)) {
(true, true) | (false, false) => Ok(()),
(false, true) => write!(stdout, "\x1B[25m"),
(true, false) => write!(stdout, "\x1B[5m"),
},
)
.and_then(|_| {
match (
self.intersects(Attr::REVERSE),
prev.intersects(Attr::REVERSE),
) {
(true, true) | (false, false) => Ok(()),
(false, true) => write!(stdout, "\x1B[27m"),
(true, false) => write!(stdout, "\x1B[7m"),
}
})
.and_then(|_| {
match (self.intersects(Attr::HIDDEN), prev.intersects(Attr::HIDDEN)) {
(true, true) | (false, false) => Ok(()),
(false, true) => write!(stdout, "\x1B[28m"),
(true, false) => write!(stdout, "\x1B[8m"),
}
}) })
} }
} }
@ -2493,7 +2556,7 @@ fn test_cellbuffer_search() {
&mut buf, &mut buf,
Color::Default, Color::Default,
Color::Default, Color::Default,
Attr::Default, Attr::DEFAULT,
((0, i), (width.saturating_sub(1), i)), ((0, i), (width.saturating_sub(1), i)),
None, None,
); );