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