parent
ee65f355c7
commit
6a7cae0988
4
meli.1
4
meli.1
|
@ -402,6 +402,10 @@ catchall for general errors
|
|||
Specifies the editor to use
|
||||
.It Ev MELI_CONFIG
|
||||
Override the configuration file
|
||||
.It Ev NO_COLOR
|
||||
When present (regardless of its value), prevents the addition of ANSI color. The configuration value
|
||||
.Ic use_color
|
||||
overrides this.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Nm
|
||||
|
|
|
@ -1050,49 +1050,38 @@ impl Listing {
|
|||
if idx == lines_len {
|
||||
break;
|
||||
}
|
||||
let (
|
||||
fg_color,
|
||||
bg_color,
|
||||
index_fg_color,
|
||||
index_bg_color,
|
||||
unread_count_fg,
|
||||
unread_count_bg,
|
||||
) = if must_highlight_account {
|
||||
let (att, index_att, unread_count_att) = if must_highlight_account {
|
||||
if self.cursor_pos.1 == idx {
|
||||
(
|
||||
crate::conf::value(context, "mail.sidebar_highlighted").fg,
|
||||
crate::conf::value(context, "mail.sidebar_highlighted").bg,
|
||||
crate::conf::value(context, "mail.sidebar_highlighted_index").fg,
|
||||
crate::conf::value(context, "mail.sidebar_highlighted_index").bg,
|
||||
crate::conf::value(context, "mail.sidebar_highlighted_unread_count").fg,
|
||||
crate::conf::value(context, "mail.sidebar_highlighted_unread_count").bg,
|
||||
)
|
||||
let mut ret = (
|
||||
crate::conf::value(context, "mail.sidebar_highlighted"),
|
||||
crate::conf::value(context, "mail.sidebar_highlighted_index"),
|
||||
crate::conf::value(context, "mail.sidebar_highlighted_unread_count"),
|
||||
);
|
||||
|
||||
if std::env::var("NO_COLOR").is_ok()
|
||||
&& (context.settings.terminal.use_color.is_false()
|
||||
|| context.settings.terminal.use_color.is_internal())
|
||||
{
|
||||
ret.0.attrs |= Attr::Reverse;
|
||||
ret.1.attrs |= Attr::Reverse;
|
||||
ret.2.attrs |= Attr::Reverse;
|
||||
}
|
||||
ret
|
||||
} else {
|
||||
(
|
||||
crate::conf::value(context, "mail.sidebar_highlighted_account").fg,
|
||||
crate::conf::value(context, "mail.sidebar_highlighted_account").bg,
|
||||
crate::conf::value(context, "mail.sidebar_highlighted_account_index").fg,
|
||||
crate::conf::value(context, "mail.sidebar_highlighted_account_index").bg,
|
||||
crate::conf::value(context, "mail.sidebar_highlighted_account"),
|
||||
crate::conf::value(context, "mail.sidebar_highlighted_account_index"),
|
||||
crate::conf::value(
|
||||
context,
|
||||
"mail.sidebar_highlighted_account_unread_count",
|
||||
)
|
||||
.fg,
|
||||
crate::conf::value(
|
||||
context,
|
||||
"mail.sidebar_highlighted_account_unread_count",
|
||||
)
|
||||
.bg,
|
||||
),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
(
|
||||
crate::conf::value(context, "mail.sidebar").fg,
|
||||
crate::conf::value(context, "mail.sidebar").bg,
|
||||
crate::conf::value(context, "mail.sidebar_index").fg,
|
||||
crate::conf::value(context, "mail.sidebar_index").bg,
|
||||
crate::conf::value(context, "mail.sidebar_unread_count").fg,
|
||||
crate::conf::value(context, "mail.sidebar_unread_count").bg,
|
||||
crate::conf::value(context, "mail.sidebar"),
|
||||
crate::conf::value(context, "mail.sidebar_index"),
|
||||
crate::conf::value(context, "mail.sidebar_unread_count"),
|
||||
)
|
||||
};
|
||||
|
||||
|
@ -1117,27 +1106,27 @@ impl Listing {
|
|||
let (x, _) = write_string_to_grid(
|
||||
&format!("{:>width$}", inc, width = total_folder_no_digits),
|
||||
grid,
|
||||
index_fg_color,
|
||||
index_bg_color,
|
||||
Attr::Default,
|
||||
index_att.fg,
|
||||
index_att.bg,
|
||||
index_att.attrs,
|
||||
(set_y(upper_left, y), bottom_right),
|
||||
None,
|
||||
);
|
||||
let (x, _) = write_string_to_grid(
|
||||
&" ".repeat(depth + 1),
|
||||
grid,
|
||||
fg_color,
|
||||
bg_color,
|
||||
Attr::Default,
|
||||
att.fg,
|
||||
att.bg,
|
||||
att.attrs,
|
||||
((x, y), bottom_right),
|
||||
None,
|
||||
);
|
||||
let (x, _) = write_string_to_grid(
|
||||
entries[&folder_idx].name(),
|
||||
grid,
|
||||
fg_color,
|
||||
bg_color,
|
||||
Attr::Default,
|
||||
att.fg,
|
||||
att.bg,
|
||||
att.attrs,
|
||||
((x, y), bottom_right),
|
||||
None,
|
||||
);
|
||||
|
@ -1156,13 +1145,14 @@ impl Listing {
|
|||
let (x, _) = write_string_to_grid(
|
||||
&count_string,
|
||||
grid,
|
||||
unread_count_fg,
|
||||
unread_count_bg,
|
||||
if count.unwrap_or(0) > 0 {
|
||||
Attr::Bold
|
||||
} else {
|
||||
Attr::Default
|
||||
},
|
||||
unread_count_att.fg,
|
||||
unread_count_att.bg,
|
||||
unread_count_att.attrs
|
||||
| if count.unwrap_or(0) > 0 {
|
||||
Attr::Bold
|
||||
} else {
|
||||
Attr::Default
|
||||
},
|
||||
(
|
||||
(
|
||||
/* Hide part of folder name if need be to fit the message count */
|
||||
|
@ -1173,7 +1163,9 @@ impl Listing {
|
|||
),
|
||||
None,
|
||||
);
|
||||
change_colors(grid, ((x, y), set_y(bottom_right, y)), fg_color, bg_color);
|
||||
for c in grid.row_iter(x..(get_x(bottom_right) + 1), y) {
|
||||
grid[c].set_fg(att.fg).set_bg(att.bg).set_attrs(att.attrs);
|
||||
}
|
||||
idx += 1;
|
||||
}
|
||||
if idx == 0 {
|
||||
|
|
|
@ -146,15 +146,32 @@ impl ListingTrait for CompactListing {
|
|||
} else {
|
||||
self.color_cache.odd.bg
|
||||
};
|
||||
let attrs = if self.cursor_pos.2 == idx {
|
||||
self.color_cache.highlighted.attrs
|
||||
} else if self.selection[&thread_hash] {
|
||||
self.color_cache.selected.attrs
|
||||
} else if thread.unseen() > 0 {
|
||||
self.color_cache.unseen.attrs
|
||||
} else if idx % 2 == 0 {
|
||||
self.color_cache.even.attrs
|
||||
} else {
|
||||
self.color_cache.odd.attrs
|
||||
};
|
||||
|
||||
let (upper_left, bottom_right) = area;
|
||||
change_colors(grid, area, fg_color, bg_color);
|
||||
let x = get_x(upper_left)
|
||||
+ self.data_columns.widths[0]
|
||||
+ self.data_columns.widths[1]
|
||||
+ self.data_columns.widths[2]
|
||||
+ 3 * 2;
|
||||
|
||||
for c in grid.row_iter(
|
||||
get_x(upper_left)..(get_x(bottom_right) + 1),
|
||||
get_y(upper_left),
|
||||
) {
|
||||
grid[c].set_fg(fg_color).set_bg(bg_color).set_attrs(attrs);
|
||||
}
|
||||
|
||||
copy_area(
|
||||
grid,
|
||||
&self.data_columns.columns[3],
|
||||
|
@ -165,7 +182,7 @@ impl ListingTrait for CompactListing {
|
|||
),
|
||||
);
|
||||
for c in grid.row_iter(x..(self.data_columns.widths[3] + x), get_y(upper_left)) {
|
||||
grid[c].set_bg(bg_color);
|
||||
grid[c].set_bg(bg_color).set_attrs(attrs);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -641,6 +658,12 @@ impl CompactListing {
|
|||
thread_snooze_flag: crate::conf::value(context, "mail.listing.thread_snooze_flag"),
|
||||
..self.color_cache
|
||||
};
|
||||
if std::env::var("NO_COLOR").is_ok()
|
||||
&& (context.settings.terminal.use_color.is_false()
|
||||
|| context.settings.terminal.use_color.is_internal())
|
||||
{
|
||||
self.color_cache.highlighted.attrs |= Attr::Reverse;
|
||||
}
|
||||
|
||||
// Get mailbox as a reference.
|
||||
//
|
||||
|
|
|
@ -119,6 +119,15 @@ impl ListingTrait for ConversationsListing {
|
|||
} else {
|
||||
self.color_cache.theme_default.bg
|
||||
};
|
||||
let attrs = if self.cursor_pos.2 == idx {
|
||||
self.color_cache.highlighted.attrs
|
||||
} else if self.selection[&thread_hash] {
|
||||
self.color_cache.selected.attrs
|
||||
} else if thread.unseen() > 0 {
|
||||
self.color_cache.unseen.attrs
|
||||
} else {
|
||||
self.color_cache.theme_default.attrs
|
||||
};
|
||||
|
||||
copy_area(
|
||||
grid,
|
||||
|
@ -134,26 +143,38 @@ impl ListingTrait for ConversationsListing {
|
|||
let (x, y) = upper_left;
|
||||
if self.cursor_pos.2 == idx || self.selection[&thread_hash] {
|
||||
for x in x..=get_x(bottom_right) {
|
||||
grid[(x, y)].set_fg(fg_color);
|
||||
grid[(x, y)].set_bg(bg_color);
|
||||
grid[(x, y)]
|
||||
.set_fg(fg_color)
|
||||
.set_bg(bg_color)
|
||||
.set_attrs(attrs);
|
||||
|
||||
grid[(x, y + 1)].set_fg(fg_color);
|
||||
grid[(x, y + 1)].set_bg(bg_color);
|
||||
grid[(x, y + 1)]
|
||||
.set_fg(fg_color)
|
||||
.set_bg(bg_color)
|
||||
.set_attrs(attrs);
|
||||
|
||||
grid[(x, y + 2)].set_fg(padding_fg);
|
||||
grid[(x, y + 2)].set_bg(bg_color);
|
||||
grid[(x, y + 2)]
|
||||
.set_fg(padding_fg)
|
||||
.set_bg(bg_color)
|
||||
.set_attrs(attrs);
|
||||
}
|
||||
} else if width < width!(area) {
|
||||
/* fill any remaining columns, if our view is wider than self.content */
|
||||
for x in (x + width)..=get_x(bottom_right) {
|
||||
grid[(x, y)].set_fg(fg_color);
|
||||
grid[(x, y)].set_bg(bg_color);
|
||||
grid[(x, y)]
|
||||
.set_fg(fg_color)
|
||||
.set_bg(bg_color)
|
||||
.set_attrs(attrs);
|
||||
|
||||
grid[(x, y + 1)].set_fg(fg_color);
|
||||
grid[(x, y + 1)].set_bg(bg_color);
|
||||
grid[(x, y + 1)]
|
||||
.set_fg(fg_color)
|
||||
.set_bg(bg_color)
|
||||
.set_attrs(attrs);
|
||||
|
||||
grid[(x, y + 2)].set_fg(padding_fg);
|
||||
grid[(x, y + 2)].set_bg(bg_color);
|
||||
grid[(x, y + 2)]
|
||||
.set_fg(padding_fg)
|
||||
.set_bg(bg_color)
|
||||
.set_attrs(attrs);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -570,6 +591,12 @@ impl ConversationsListing {
|
|||
..self.color_cache
|
||||
};
|
||||
|
||||
if std::env::var("NO_COLOR").is_ok()
|
||||
&& (context.settings.terminal.use_color.is_false()
|
||||
|| context.settings.terminal.use_color.is_internal())
|
||||
{
|
||||
self.color_cache.highlighted.attrs |= Attr::Reverse;
|
||||
}
|
||||
// Get mailbox as a reference.
|
||||
//
|
||||
match context.accounts[self.cursor_pos.0].status(self.folder_hash) {
|
||||
|
|
|
@ -73,6 +73,7 @@ pub struct PlainListing {
|
|||
view: MailView,
|
||||
row_updates: SmallVec<[EnvelopeHash; 8]>,
|
||||
_row_updates: SmallVec<[ThreadHash; 8]>,
|
||||
color_cache: ColorCache,
|
||||
|
||||
movement: Option<PageMovement>,
|
||||
id: ComponentId,
|
||||
|
@ -125,37 +126,51 @@ impl ListingTrait for PlainListing {
|
|||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let envelope: EnvelopeRef = account.collection.get_env(i);
|
||||
|
||||
let fg_color = self.data_columns.columns[0][(0, idx)].fg();
|
||||
let bg_color = if context.settings.terminal.theme == "light" {
|
||||
if self.cursor_pos.2 == idx {
|
||||
Color::Byte(244)
|
||||
} else if self.selection[&i] {
|
||||
Color::Byte(210)
|
||||
} else if !envelope.is_seen() {
|
||||
Color::Byte(251)
|
||||
} else {
|
||||
self.data_columns.columns[0][(0, idx)].bg()
|
||||
}
|
||||
let fg_color = if !envelope.is_seen() {
|
||||
self.color_cache.unseen.fg
|
||||
} else if self.cursor_pos.2 == idx {
|
||||
self.color_cache.highlighted.fg
|
||||
} else if idx % 2 == 0 {
|
||||
self.color_cache.even.fg
|
||||
} else {
|
||||
if self.cursor_pos.2 == idx {
|
||||
Color::Byte(246)
|
||||
} else if self.selection[&i] {
|
||||
Color::Byte(210)
|
||||
} else if !envelope.is_seen() {
|
||||
Color::Byte(251)
|
||||
} else {
|
||||
self.data_columns.columns[0][(0, idx)].bg()
|
||||
}
|
||||
self.color_cache.odd.fg
|
||||
};
|
||||
let bg_color = if self.cursor_pos.2 == idx {
|
||||
self.color_cache.highlighted.bg
|
||||
} else if self.selection[&i] {
|
||||
self.color_cache.selected.bg
|
||||
} else if !envelope.is_seen() {
|
||||
self.color_cache.unseen.bg
|
||||
} else if idx % 2 == 0 {
|
||||
self.color_cache.even.bg
|
||||
} else {
|
||||
self.color_cache.odd.bg
|
||||
};
|
||||
let attrs = if self.cursor_pos.2 == idx {
|
||||
self.color_cache.highlighted.attrs
|
||||
} else if self.selection[&i] {
|
||||
self.color_cache.selected.attrs
|
||||
} else if !envelope.is_seen() {
|
||||
self.color_cache.unseen.attrs
|
||||
} else if idx % 2 == 0 {
|
||||
self.color_cache.even.attrs
|
||||
} else {
|
||||
self.color_cache.odd.attrs
|
||||
};
|
||||
|
||||
let (upper_left, bottom_right) = area;
|
||||
change_colors(grid, area, fg_color, bg_color);
|
||||
let x = get_x(upper_left)
|
||||
+ self.data_columns.widths[0]
|
||||
+ self.data_columns.widths[1]
|
||||
+ self.data_columns.widths[2]
|
||||
+ 3 * 2;
|
||||
|
||||
for c in grid.row_iter(
|
||||
get_x(upper_left)..(get_x(bottom_right) + 1),
|
||||
get_y(upper_left),
|
||||
) {
|
||||
grid[c].set_fg(fg_color).set_bg(bg_color).set_attrs(attrs);
|
||||
}
|
||||
copy_area(
|
||||
grid,
|
||||
&self.data_columns.columns[3],
|
||||
|
@ -166,7 +181,7 @@ impl ListingTrait for PlainListing {
|
|||
),
|
||||
);
|
||||
for c in grid.row_iter(x..(x + self.data_columns.widths[3]), get_y(upper_left)) {
|
||||
grid[c].set_bg(bg_color);
|
||||
grid[c].set_bg(bg_color).set_attrs(attrs);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -495,6 +510,7 @@ impl PlainListing {
|
|||
force_draw: true,
|
||||
unfocused: false,
|
||||
view: MailView::default(),
|
||||
color_cache: ColorCache::default(),
|
||||
|
||||
movement: None,
|
||||
id: ComponentId::new_v4(),
|
||||
|
@ -571,6 +587,23 @@ impl PlainListing {
|
|||
return;
|
||||
};
|
||||
|
||||
self.color_cache = ColorCache {
|
||||
unseen: crate::conf::value(context, "mail.listing.plain.unseen"),
|
||||
highlighted: crate::conf::value(context, "mail.listing.plain.highlighted"),
|
||||
even: crate::conf::value(context, "mail.listing.plain.even"),
|
||||
odd: crate::conf::value(context, "mail.listing.plain.odd"),
|
||||
selected: crate::conf::value(context, "mail.listing.plain.selected"),
|
||||
attachment_flag: crate::conf::value(context, "mail.listing.attachment_flag"),
|
||||
thread_snooze_flag: crate::conf::value(context, "mail.listing.thread_snooze_flag"),
|
||||
..self.color_cache
|
||||
};
|
||||
if std::env::var("NO_COLOR").is_ok()
|
||||
&& (context.settings.terminal.use_color.is_false()
|
||||
|| context.settings.terminal.use_color.is_internal())
|
||||
{
|
||||
self.color_cache.highlighted.attrs |= Attr::Reverse;
|
||||
}
|
||||
|
||||
// Get mailbox as a reference.
|
||||
//
|
||||
match context.accounts[self.cursor_pos.0].status(self.folder_hash) {
|
||||
|
|
|
@ -764,7 +764,13 @@ impl StatusBar {
|
|||
}
|
||||
}
|
||||
fn draw_status_bar(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
let attribute = crate::conf::value(context, "status.bar");
|
||||
let mut attribute = crate::conf::value(context, "status.bar");
|
||||
if std::env::var("NO_COLOR").is_ok()
|
||||
&& (context.settings.terminal.use_color.is_false()
|
||||
|| context.settings.terminal.use_color.is_internal())
|
||||
{
|
||||
attribute.attrs |= Attr::Reverse;
|
||||
}
|
||||
let (x, y) = write_string_to_grid(
|
||||
&self.status,
|
||||
grid,
|
||||
|
@ -774,7 +780,7 @@ impl StatusBar {
|
|||
area,
|
||||
None,
|
||||
);
|
||||
for c in grid.row_iter_from(x.., y) {
|
||||
for c in grid.row_iter(x..(get_x(bottom_right!(area)) + 1), y) {
|
||||
grid[c]
|
||||
.set_ch(' ')
|
||||
.set_fg(attribute.fg)
|
||||
|
@ -789,7 +795,7 @@ impl StatusBar {
|
|||
get_x(bottom_right!(area)),
|
||||
)
|
||||
{
|
||||
grid[(x, y)].set_attrs(Attr::Bold);
|
||||
grid[(x, y)].set_attrs(attribute.attrs | Attr::Bold);
|
||||
}
|
||||
}
|
||||
let noto_colors = crate::conf::value(context, "status.notification");
|
||||
|
@ -1369,21 +1375,29 @@ impl Tabbed {
|
|||
clear_area(grid, area);
|
||||
return;
|
||||
}
|
||||
let mut tab_focused_attribute = crate::conf::value(context, "tab.focused");
|
||||
let tab_unfocused_attribute = crate::conf::value(context, "tab.unfocused");
|
||||
if std::env::var("NO_COLOR").is_ok()
|
||||
&& (context.settings.terminal.use_color.is_false()
|
||||
|| context.settings.terminal.use_color.is_internal())
|
||||
{
|
||||
tab_focused_attribute.attrs |= Attr::Reverse;
|
||||
}
|
||||
|
||||
let mut x = get_x(upper_left);
|
||||
let y: usize = get_y(upper_left);
|
||||
for (idx, c) in self.children.iter().enumerate() {
|
||||
let (fg, bg) = if idx == self.cursor_pos {
|
||||
(Color::Default, Color::Default)
|
||||
let ThemeAttribute { fg, bg, attrs } = if idx == self.cursor_pos {
|
||||
tab_focused_attribute
|
||||
} else {
|
||||
(Color::Byte(15), Color::Byte(8))
|
||||
tab_unfocused_attribute
|
||||
};
|
||||
let (x_, _y_) = write_string_to_grid(
|
||||
&format!(" {} ", c),
|
||||
grid,
|
||||
fg,
|
||||
bg,
|
||||
Attr::Default,
|
||||
attrs,
|
||||
(set_x(upper_left, x), bottom_right!(area)),
|
||||
None,
|
||||
);
|
||||
|
@ -1408,9 +1422,11 @@ impl Tabbed {
|
|||
}
|
||||
|
||||
if self.cursor_pos == self.children.len() - 1 {
|
||||
cslice[(y * cols) + x].set_ch('▍');
|
||||
cslice[(y * cols) + x].set_fg(Color::Byte(8));
|
||||
cslice[(y * cols) + x].set_bg(Color::Default);
|
||||
cslice[(y * cols) + x]
|
||||
.set_ch('▍')
|
||||
.set_fg(tab_unfocused_attribute.bg)
|
||||
.set_bg(tab_unfocused_attribute.fg)
|
||||
.set_attrs(tab_unfocused_attribute.attrs);
|
||||
}
|
||||
|
||||
context.dirty_areas.push_back(area);
|
||||
|
@ -1838,6 +1854,13 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Component for Selector<T> {
|
|||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||
let (width, height) = self.content.size();
|
||||
let shortcuts = self.get_shortcuts(context);
|
||||
let mut highlighted_attrs = crate::conf::value(context, "widgets.options.highlighted");
|
||||
if std::env::var("NO_COLOR").is_ok()
|
||||
&& (context.settings.terminal.use_color.is_false()
|
||||
|| context.settings.terminal.use_color.is_internal())
|
||||
{
|
||||
highlighted_attrs.attrs |= Attr::Reverse;
|
||||
}
|
||||
match (event, self.cursor) {
|
||||
(UIEvent::Input(Key::Char('\n')), _) if self.single_only => {
|
||||
/* User can only select one entry, so Enter key finalises the selection */
|
||||
|
@ -1893,34 +1916,34 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Component for Selector<T> {
|
|||
(UIEvent::Input(Key::Up), SelectorCursor::Entry(c)) if c > 0 => {
|
||||
if self.single_only {
|
||||
// Redraw selection
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
((2, c + 2), (width - 2, c + 2)),
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
);
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
((2, c + 1), (width - 2, c + 1)),
|
||||
Color::Default,
|
||||
Color::Byte(8),
|
||||
);
|
||||
for c in self.content.row_iter(2..(width - 2), c + 2) {
|
||||
self.content[c]
|
||||
.set_fg(Color::Default)
|
||||
.set_bg(Color::Default)
|
||||
.set_attrs(Attr::Default);
|
||||
}
|
||||
for c in self.content.row_iter(2..(width - 2), c + 1) {
|
||||
self.content[c]
|
||||
.set_fg(highlighted_attrs.fg)
|
||||
.set_bg(highlighted_attrs.bg)
|
||||
.set_attrs(highlighted_attrs.attrs);
|
||||
}
|
||||
self.entries[c].1 = false;
|
||||
self.entries[c - 1].1 = true;
|
||||
} else {
|
||||
// Redraw cursor
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
((2, c + 2), (4, c + 2)),
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
);
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
((2, c + 1), (4, c + 1)),
|
||||
Color::Default,
|
||||
Color::Byte(8),
|
||||
);
|
||||
for c in self.content.row_iter(2..4, c + 2) {
|
||||
self.content[c]
|
||||
.set_fg(Color::Default)
|
||||
.set_bg(Color::Default)
|
||||
.set_attrs(Attr::Default);
|
||||
}
|
||||
for c in self.content.row_iter(2..4, c + 1) {
|
||||
self.content[c]
|
||||
.set_fg(highlighted_attrs.fg)
|
||||
.set_bg(highlighted_attrs.bg)
|
||||
.set_attrs(highlighted_attrs.attrs);
|
||||
}
|
||||
}
|
||||
self.cursor = SelectorCursor::Entry(c - 1);
|
||||
self.dirty = true;
|
||||
|
@ -1930,23 +1953,31 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Component for Selector<T> {
|
|||
| (UIEvent::Input(ref key), SelectorCursor::Cancel)
|
||||
if shortcut!(key == shortcuts["general"]["scroll_up"]) =>
|
||||
{
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
(
|
||||
((width - "OK Cancel".len()) / 2, height - 3),
|
||||
(width - 1, height - 3),
|
||||
),
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
);
|
||||
for c in self.content.row_iter(
|
||||
((width - "OK Cancel".len()) / 2)..(width - 1),
|
||||
height - 3,
|
||||
) {
|
||||
self.content[c]
|
||||
.set_fg(Color::Default)
|
||||
.set_bg(Color::Default)
|
||||
.set_attrs(Attr::Default);
|
||||
}
|
||||
let c = self.entries.len().saturating_sub(1);
|
||||
self.cursor = SelectorCursor::Entry(c);
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
((2, c + 2), (4, c + 2)),
|
||||
Color::Default,
|
||||
Color::Byte(8),
|
||||
);
|
||||
let mut highlighted_attrs =
|
||||
crate::conf::value(context, "widgets.options.highlighted");
|
||||
if std::env::var("NO_COLOR").is_ok()
|
||||
&& (context.settings.terminal.use_color.is_false()
|
||||
|| context.settings.terminal.use_color.is_internal())
|
||||
{
|
||||
highlighted_attrs.attrs |= Attr::Reverse;
|
||||
}
|
||||
for c in self.content.row_iter(2..4, c + 2) {
|
||||
self.content[c]
|
||||
.set_fg(highlighted_attrs.fg)
|
||||
.set_bg(highlighted_attrs.bg)
|
||||
.set_attrs(highlighted_attrs.attrs);
|
||||
}
|
||||
self.dirty = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -1956,34 +1987,34 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Component for Selector<T> {
|
|||
{
|
||||
if self.single_only {
|
||||
// Redraw selection
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
((2, c + 2), (width - 2, c + 2)),
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
);
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
((2, c + 3), (width - 2, c + 3)),
|
||||
Color::Default,
|
||||
Color::Byte(8),
|
||||
);
|
||||
for c in self.content.row_iter(2..(width - 2), c + 2) {
|
||||
self.content[c]
|
||||
.set_fg(Color::Default)
|
||||
.set_bg(Color::Default)
|
||||
.set_attrs(Attr::Default);
|
||||
}
|
||||
for c in self.content.row_iter(2..(width - 2), c + 3) {
|
||||
self.content[c]
|
||||
.set_fg(highlighted_attrs.fg)
|
||||
.set_bg(highlighted_attrs.bg)
|
||||
.set_attrs(highlighted_attrs.attrs);
|
||||
}
|
||||
self.entries[c].1 = false;
|
||||
self.entries[c + 1].1 = true;
|
||||
} else {
|
||||
// Redraw cursor
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
((2, c + 2), (4, c + 2)),
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
);
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
((2, c + 3), (4, c + 3)),
|
||||
Color::Default,
|
||||
Color::Byte(8),
|
||||
);
|
||||
for c in self.content.row_iter(2..4, c + 2) {
|
||||
self.content[c]
|
||||
.set_fg(Color::Default)
|
||||
.set_bg(Color::Default)
|
||||
.set_attrs(Attr::Default);
|
||||
}
|
||||
for c in self.content.row_iter(2..4, c + 3) {
|
||||
self.content[c]
|
||||
.set_fg(highlighted_attrs.fg)
|
||||
.set_bg(highlighted_attrs.bg)
|
||||
.set_attrs(highlighted_attrs.attrs);
|
||||
}
|
||||
}
|
||||
self.cursor = SelectorCursor::Entry(c + 1);
|
||||
self.dirty = true;
|
||||
|
@ -1993,21 +2024,21 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Component for Selector<T> {
|
|||
if !self.single_only && shortcut!(key == shortcuts["general"]["scroll_down"]) =>
|
||||
{
|
||||
self.cursor = SelectorCursor::Ok;
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
((2, c + 2), (4, c + 2)),
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
);
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
(
|
||||
((width - "OK Cancel".len()) / 2, height - 3),
|
||||
((width - "OK Cancel".len()) / 2 + 1, height - 3),
|
||||
),
|
||||
Color::Default,
|
||||
Color::Byte(8),
|
||||
);
|
||||
for c in self.content.row_iter(2..4, c + 2) {
|
||||
self.content[c]
|
||||
.set_fg(Color::Default)
|
||||
.set_bg(Color::Default)
|
||||
.set_attrs(Attr::Default);
|
||||
}
|
||||
for c in self.content.row_iter(
|
||||
((width - "OK Cancel".len()) / 2)..((width - "OK Cancel".len()) / 2 + 1),
|
||||
height - 3,
|
||||
) {
|
||||
self.content[c]
|
||||
.set_fg(highlighted_attrs.fg)
|
||||
.set_bg(highlighted_attrs.bg)
|
||||
.set_attrs(highlighted_attrs.attrs);
|
||||
}
|
||||
self.dirty = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -2015,24 +2046,25 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Component for Selector<T> {
|
|||
if shortcut!(key == shortcuts["general"]["scroll_right"]) =>
|
||||
{
|
||||
self.cursor = SelectorCursor::Cancel;
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
(
|
||||
((width - "OK Cancel".len()) / 2, height - 3),
|
||||
((width - "OK Cancel".len()) / 2 + 1, height - 3),
|
||||
),
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
);
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
(
|
||||
((width - "OK Cancel".len()) / 2 + 6, height - 3),
|
||||
((width - "OK Cancel".len()) / 2 + 11, height - 3),
|
||||
),
|
||||
Color::Default,
|
||||
Color::Byte(8),
|
||||
);
|
||||
for c in self.content.row_iter(
|
||||
((width - "OK Cancel".len()) / 2)..((width - "OK Cancel".len()) / 2 + 1),
|
||||
height - 3,
|
||||
) {
|
||||
self.content[c]
|
||||
.set_fg(Color::Default)
|
||||
.set_bg(Color::Default)
|
||||
.set_attrs(Attr::Default);
|
||||
}
|
||||
for c in self.content.row_iter(
|
||||
((width - "OK Cancel".len()) / 2 + 6)
|
||||
..((width - "OK Cancel".len()) / 2 + 11),
|
||||
height - 3,
|
||||
) {
|
||||
self.content[c]
|
||||
.set_fg(highlighted_attrs.fg)
|
||||
.set_bg(highlighted_attrs.bg)
|
||||
.set_attrs(highlighted_attrs.attrs);
|
||||
}
|
||||
self.dirty = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -2040,15 +2072,15 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Component for Selector<T> {
|
|||
if shortcut!(key == shortcuts["general"]["scroll_left"]) =>
|
||||
{
|
||||
self.cursor = SelectorCursor::Ok;
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
(
|
||||
((width - "OK Cancel".len()) / 2, height - 3),
|
||||
((width - "OK Cancel".len()) / 2 + 1, height - 3),
|
||||
),
|
||||
Color::Default,
|
||||
Color::Byte(8),
|
||||
);
|
||||
for c in self.content.row_iter(
|
||||
((width - "OK Cancel".len()) / 2)..((width - "OK Cancel".len()) / 2 + 1),
|
||||
height - 3,
|
||||
) {
|
||||
self.content[c]
|
||||
.set_fg(highlighted_attrs.fg)
|
||||
.set_bg(highlighted_attrs.bg)
|
||||
.set_attrs(highlighted_attrs.attrs);
|
||||
}
|
||||
change_colors(
|
||||
&mut self.content,
|
||||
(
|
||||
|
@ -2213,6 +2245,13 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Selector<T> {
|
|||
None,
|
||||
);
|
||||
}
|
||||
let mut highlighted_attrs = crate::conf::value(context, "widgets.options.highlighted");
|
||||
if std::env::var("NO_COLOR").is_ok()
|
||||
&& (context.settings.terminal.use_color.is_false()
|
||||
|| context.settings.terminal.use_color.is_internal())
|
||||
{
|
||||
highlighted_attrs.attrs |= Attr::Reverse;
|
||||
}
|
||||
if single_only {
|
||||
for (i, e) in entries.iter().enumerate() {
|
||||
write_string_to_grid(
|
||||
|
@ -2220,11 +2259,15 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Selector<T> {
|
|||
&mut content,
|
||||
Color::Default,
|
||||
if i == 0 {
|
||||
Color::Byte(8)
|
||||
highlighted_attrs.bg
|
||||
} else {
|
||||
Color::Default
|
||||
},
|
||||
Attr::Default,
|
||||
if i == 0 {
|
||||
highlighted_attrs.attrs
|
||||
} else {
|
||||
Attr::Default
|
||||
},
|
||||
((2, i + 2), (width - 1, i + 2)),
|
||||
None,
|
||||
);
|
||||
|
@ -2241,9 +2284,15 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Selector<T> {
|
|||
None,
|
||||
);
|
||||
if i == 0 {
|
||||
content[(2, i + 2)].set_bg(Color::Byte(8));
|
||||
content[(3, i + 2)].set_bg(Color::Byte(8));
|
||||
content[(4, i + 2)].set_bg(Color::Byte(8));
|
||||
content[(2, i + 2)]
|
||||
.set_bg(highlighted_attrs.bg)
|
||||
.set_attrs(highlighted_attrs.attrs);
|
||||
content[(3, i + 2)]
|
||||
.set_bg(highlighted_attrs.bg)
|
||||
.set_attrs(highlighted_attrs.attrs);
|
||||
content[(4, i + 2)]
|
||||
.set_bg(highlighted_attrs.bg)
|
||||
.set_attrs(highlighted_attrs.attrs);
|
||||
}
|
||||
}
|
||||
write_string_to_grid(
|
||||
|
|
|
@ -375,15 +375,16 @@ impl Component for FormWidget {
|
|||
),
|
||||
);
|
||||
|
||||
let label_attrs = crate::conf::value(context, "widgets.form.label");
|
||||
for (i, k) in self.layout.iter().enumerate() {
|
||||
let v = self.fields.get_mut(k).unwrap();
|
||||
/* Write field label */
|
||||
write_string_to_grid(
|
||||
k.as_str(),
|
||||
grid,
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
Attr::Bold,
|
||||
label_attrs.fg,
|
||||
label_attrs.bg,
|
||||
label_attrs.attrs,
|
||||
(
|
||||
pos_inc(upper_left, (1, i)),
|
||||
set_y(bottom_right, i + get_y(upper_left)),
|
||||
|
@ -403,15 +404,25 @@ impl Component for FormWidget {
|
|||
/* Highlight if necessary */
|
||||
if i == self.cursor {
|
||||
if self.focus == FormFocus::Fields {
|
||||
change_colors(
|
||||
grid,
|
||||
(
|
||||
pos_inc(upper_left, (0, i)),
|
||||
set_y(bottom_right, i + get_y(upper_left)),
|
||||
),
|
||||
Color::Default,
|
||||
Color::Byte(246),
|
||||
);
|
||||
let mut field_attrs =
|
||||
crate::conf::value(context, "widgets.form.highlighted");
|
||||
if std::env::var("NO_COLOR").is_ok()
|
||||
&& (context.settings.terminal.use_color.is_false()
|
||||
|| context.settings.terminal.use_color.is_internal())
|
||||
{
|
||||
field_attrs.attrs |= Attr::Reverse;
|
||||
}
|
||||
for row in grid.bounds_iter((
|
||||
pos_inc(upper_left, (0, i)),
|
||||
set_y(bottom_right, i + get_y(upper_left)),
|
||||
)) {
|
||||
for c in row {
|
||||
grid[c]
|
||||
.set_fg(field_attrs.fg)
|
||||
.set_bg(field_attrs.bg)
|
||||
.set_attrs(field_attrs.attrs);
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.focus == FormFocus::TextInput {
|
||||
v.draw_cursor(
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
use super::deserializers::non_empty_string;
|
||||
use super::Theme;
|
||||
use super::ToggleFlag;
|
||||
|
||||
/// Settings for terminal display
|
||||
#[derive(Debug, Deserialize, Clone, Serialize)]
|
||||
|
@ -30,6 +31,7 @@ pub struct TerminalSettings {
|
|||
pub theme: String,
|
||||
pub themes: Theme,
|
||||
pub ascii_drawing: bool,
|
||||
pub use_color: ToggleFlag,
|
||||
#[serde(deserialize_with = "non_empty_string")]
|
||||
pub window_title: Option<String>,
|
||||
}
|
||||
|
@ -40,6 +42,7 @@ impl Default for TerminalSettings {
|
|||
theme: "dark".to_string(),
|
||||
themes: Theme::default(),
|
||||
ascii_drawing: false,
|
||||
use_color: ToggleFlag::InternalVal(true),
|
||||
window_title: Some("meli".to_string()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,6 +149,10 @@ const DEFAULT_KEYS: &'static [&'static str] = &[
|
|||
"tab.focused",
|
||||
"tab.unfocused",
|
||||
"tab.bar",
|
||||
"widgets.form.label",
|
||||
"widgets.form.field",
|
||||
"widgets.form.highlighted",
|
||||
"widgets.options.highlighted",
|
||||
"mail.sidebar",
|
||||
"mail.sidebar_unread_count",
|
||||
"mail.sidebar_index",
|
||||
|
@ -166,6 +170,8 @@ const DEFAULT_KEYS: &'static [&'static str] = &[
|
|||
"mail.listing.plain.even",
|
||||
"mail.listing.plain.odd",
|
||||
"mail.listing.plain.unseen",
|
||||
"mail.listing.plain.selected",
|
||||
"mail.listing.plain.highlighted",
|
||||
"mail.listing.conversations",
|
||||
"mail.listing.conversations.subject",
|
||||
"mail.listing.conversations.from",
|
||||
|
@ -216,6 +222,12 @@ impl From<Color> for ThemeValue<Color> {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Attr> for ThemeValue<Attr> {
|
||||
fn from(from: Attr) -> Self {
|
||||
ThemeValue::Value(from)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ThemeValue<Color> {
|
||||
fn default() -> Self {
|
||||
ThemeValue::Value(Color::Default)
|
||||
|
@ -440,8 +452,16 @@ impl Default for Theme {
|
|||
add!("status.notification", dark = { fg: Color::Byte(219), bg: Color::Byte(88) }, light = { fg: Color::Byte(219), bg: Color::Byte(88) });
|
||||
|
||||
add!("tab.focused");
|
||||
add!("tab.unfocused");
|
||||
add!("tab.unfocused", dark = { fg: Color::Byte(15), bg: Color::Byte(8), }, light = { fg: Color::Byte(15), bg: Color::Byte(8), });
|
||||
add!("tab.bar");
|
||||
add!(
|
||||
"widgets.form.label",
|
||||
dark = { attrs: Attr::Bold },
|
||||
light = { attrs: Attr::Bold }
|
||||
);
|
||||
add!("widgets.form.field");
|
||||
add!("widgets.form.highlighted", light = { bg: Color::Byte(246) }, dark = { bg: Color::Byte(246) });
|
||||
add!("widgets.options.highlighted", light = { bg: Color::Byte(8) }, dark = { bg: Color::Byte(8) });
|
||||
|
||||
/* Mail Sidebar */
|
||||
|
||||
|
@ -598,13 +618,45 @@ impl Default for Theme {
|
|||
}
|
||||
);
|
||||
|
||||
add!("mail.listing.plain.even");
|
||||
/* PlainListing */
|
||||
add!("mail.listing.plain.even",
|
||||
dark = {
|
||||
bg: Color::Byte(236)
|
||||
},
|
||||
light = {
|
||||
bg: Color::Byte(252)
|
||||
}
|
||||
);
|
||||
add!("mail.listing.plain.odd");
|
||||
add!("mail.listing.plain.unseen");
|
||||
add!("mail.listing.conversations.subject");
|
||||
add!("mail.listing.conversations.from");
|
||||
add!("mail.listing.conversations.date");
|
||||
add!("mail.listing.conversations.unseen_padding");
|
||||
add!(
|
||||
"mail.listing.plain.unseen",
|
||||
dark = {
|
||||
fg: Color::Byte(0),
|
||||
bg: Color::Byte(251)
|
||||
|
||||
},
|
||||
light = {
|
||||
fg: Color::Byte(0),
|
||||
bg: Color::Byte(251)
|
||||
}
|
||||
);
|
||||
add!("mail.listing.plain.selected",
|
||||
dark = {
|
||||
bg: Color::Byte(210)
|
||||
},
|
||||
light = {
|
||||
bg: Color::Byte(210)
|
||||
}
|
||||
);
|
||||
add!(
|
||||
"mail.listing.plain.highlighted",
|
||||
dark = {
|
||||
bg: Color::Byte(246)
|
||||
},
|
||||
light = {
|
||||
bg: Color::Byte(244)
|
||||
}
|
||||
);
|
||||
|
||||
add!(
|
||||
"mail.view.headers",
|
||||
|
|
|
@ -179,6 +179,7 @@ pub struct State {
|
|||
draw_rate_limit: RateLimit,
|
||||
stdout: Option<StateStdout>,
|
||||
child: Option<ForkType>,
|
||||
draw_horizontal_segment_fn: fn(&mut State, usize, usize, usize) -> (),
|
||||
pub mode: UIMode,
|
||||
components: Vec<Box<dyn Component>>,
|
||||
pub context: Context,
|
||||
|
@ -274,6 +275,14 @@ impl State {
|
|||
components: Vec::with_capacity(1),
|
||||
timer,
|
||||
draw_rate_limit: RateLimit::new(1, 3),
|
||||
draw_horizontal_segment_fn: if env::var("NO_COLOR").is_ok()
|
||||
&& (settings.terminal.use_color.is_false()
|
||||
|| settings.terminal.use_color.is_internal())
|
||||
{
|
||||
State::draw_horizontal_segment_no_color
|
||||
} else {
|
||||
State::draw_horizontal_segment
|
||||
},
|
||||
|
||||
context: Context {
|
||||
accounts,
|
||||
|
@ -457,18 +466,18 @@ impl State {
|
|||
continue;
|
||||
}
|
||||
if let Some((x_start, x_end)) = segment.take() {
|
||||
self.draw_horizontal_segment(x_start, x_end, y);
|
||||
(self.draw_horizontal_segment_fn)(self, x_start, x_end, y);
|
||||
}
|
||||
match segment {
|
||||
ref mut s @ None => {
|
||||
*s = Some((*x_start, *x_end));
|
||||
}
|
||||
ref mut s @ Some(_) if s.unwrap().1 < *x_start => {
|
||||
self.draw_horizontal_segment(s.unwrap().0, s.unwrap().1, y);
|
||||
(self.draw_horizontal_segment_fn)(self, s.unwrap().0, s.unwrap().1, y);
|
||||
*s = Some((*x_start, *x_end));
|
||||
}
|
||||
ref mut s @ Some(_) if s.unwrap().1 < *x_end => {
|
||||
self.draw_horizontal_segment(s.unwrap().0, s.unwrap().1, y);
|
||||
(self.draw_horizontal_segment_fn)(self, s.unwrap().0, s.unwrap().1, y);
|
||||
*s = Some((s.unwrap().1, *x_end));
|
||||
}
|
||||
Some((_, ref mut x)) => {
|
||||
|
@ -477,7 +486,7 @@ impl State {
|
|||
}
|
||||
}
|
||||
if let Some((x_start, x_end)) = segment {
|
||||
self.draw_horizontal_segment(x_start, x_end, y);
|
||||
(self.draw_horizontal_segment_fn)(self, x_start, x_end, y);
|
||||
}
|
||||
}
|
||||
self.flush();
|
||||
|
@ -521,6 +530,33 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
fn draw_horizontal_segment_no_color(&mut self, x_start: usize, x_end: usize, y: usize) {
|
||||
write!(
|
||||
self.stdout(),
|
||||
"{}",
|
||||
cursor::Goto(x_start as u16 + 1, (y + 1) as u16)
|
||||
)
|
||||
.unwrap();
|
||||
let mut current_attrs = Attr::Default;
|
||||
let Self {
|
||||
ref grid,
|
||||
ref mut stdout,
|
||||
..
|
||||
} = self;
|
||||
let stdout = stdout.as_mut().unwrap();
|
||||
write!(stdout, "\x1B[m").unwrap();
|
||||
for x in x_start..=x_end {
|
||||
let c = &grid[(x, y)];
|
||||
if c.attrs() != current_attrs {
|
||||
c.attrs().write(current_attrs, stdout).unwrap();
|
||||
current_attrs = c.attrs();
|
||||
}
|
||||
if !c.empty() {
|
||||
write!(stdout, "{}", c.ch()).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw the entire screen from scratch.
|
||||
pub fn render(&mut self) {
|
||||
self.update_size();
|
||||
|
|
|
@ -366,19 +366,6 @@ impl CellBuffer {
|
|||
RowIterator { row, col: 0..0 }
|
||||
}
|
||||
}
|
||||
|
||||
/// row_iter() but with `RangeFrom`.
|
||||
/// See `RowIterator` documentation.
|
||||
pub fn row_iter_from(&self, bounds: std::ops::RangeFrom<usize>, row: usize) -> RowIterator {
|
||||
if row < self.rows {
|
||||
RowIterator {
|
||||
row,
|
||||
col: std::cmp::min(self.cols.saturating_sub(1), bounds.start)..self.cols,
|
||||
}
|
||||
} else {
|
||||
RowIterator { row, col: 0..0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for CellBuffer {
|
||||
|
@ -1407,6 +1394,24 @@ pub enum Attr {
|
|||
BoldReverseUnderline = 0b111,
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -1415,6 +1420,23 @@ impl core::ops::BitAnd for Attr {
|
|||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
fn default() -> Self {
|
||||
Attr::Default
|
||||
|
|
Loading…
Reference in New Issue