conf: add a light theme option

embed
Manos Pitsidianakis 2019-10-06 10:58:47 +03:00
parent a0602274f8
commit b25f10f92a
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
9 changed files with 186 additions and 45 deletions

6
meli.1
View File

@ -62,6 +62,12 @@ The main visual navigation tool is the left-side sidebar. The menu's visibility
).
.Pp
The view into each folder has 4 modes: plain, threaded, conversations and compact. Plain views each mail indvidually, threaded shows their thread relationship visually, and conversations includes one entry per thread of emails (compact is one row per thread).
.Pp
If you're using a light color palette in your terminal, you can set
.Em theme = "light"
in the
.Em terminal
section of your configuration.
.Bd -literal
^^ .-=-=-=-. ^^
^^ (`-=-=-=-=-`) ^^

View File

@ -41,7 +41,7 @@ Newline means LF (0x0A) or CRLF (0x0D 0x0A).
.Pp
Refer to TOML documentation for valid TOML syntax.
.Sh SECTIONS
The top level sections of the config are accounts, shortcuts, notifications, pager, composing, pgp.
The top level sections of the config are accounts, shortcuts, notifications, pager, composing, pgp, terminal.
.Pp
.Sy example configuration
.Bd -literal
@ -85,6 +85,9 @@ scroll_up = 'k'
scroll_down = 'j'
page_up = PageUp
page_down = PageDown
[terminal]
theme = "light"
.Ed
.Pp
available options are listed below.
@ -308,6 +311,12 @@ auto verify signed e-mail according to RFC3156
.\" default value
.Pq Em "gpg2"
.El
.Sh TERMINAL
.Bl -tag -width "danger_accept_invalid_certs boolean" -offset -indent
.It Cm theme Ar String
(optional) select between these themes: light / dark
.\" default value
.Pq Em dark
.Sh SEE ALSO
.Xr meli 1
.Sh CONFORMING TO

View File

@ -84,3 +84,6 @@
#auto_sign = false # always sign sent messages
#auto_verify_signatures = true # always verify signatures when reading signed e-mails
#gpg_binary = "/usr/bin/gpg2" #optional
#
#[terminal]
#theme = "dark" # or "light"

View File

@ -93,14 +93,26 @@ impl ListingTrait for CompactListing {
let thread_node = &threads.thread_nodes[&i];
let fg_color = self.data_columns.columns[0][(0, idx)].fg();
let bg_color = if self.cursor_pos.2 == idx {
Color::Byte(246)
} else if self.selection[&i] {
Color::Byte(210)
} else if thread_node.has_unseen() {
Color::Byte(251)
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 thread_node.has_unseen() {
Color::Byte(251)
} else {
self.data_columns.columns[0][(0, idx)].bg()
}
} else {
self.data_columns.columns[0][(0, idx)].bg()
if self.cursor_pos.2 == idx {
Color::Byte(246)
} else if self.selection[&i] {
Color::Byte(210)
} else if thread_node.has_unseen() {
Color::Byte(251)
} else {
self.data_columns.columns[0][(0, idx)].bg()
}
};
let (upper_left, bottom_right) = area;
@ -639,12 +651,22 @@ impl CompactListing {
} else {
Color::Default
};
let bg_color = if thread_node.has_unseen() {
Color::Byte(251)
} else if idx % 2 == 0 {
Color::Byte(236)
let bg_color = if context.settings.terminal.theme == "light" {
if thread_node.has_unseen() {
Color::Byte(251)
} else if idx % 2 == 0 {
Color::Byte(252)
} else {
Color::Default
}
} else {
Color::Default
if thread_node.has_unseen() {
Color::Byte(253)
} else if idx % 2 == 0 {
Color::Byte(236)
} else {
Color::Default
}
};
let (x, _) = write_string_to_grid(
&idx.to_string(),

View File

@ -146,6 +146,12 @@ impl ListingTrait for ConversationsListing {
((0, 3 * idx), pos_dec(self.content.size(), (1, 1))),
);
let padding_fg = if context.settings.terminal.theme == "light" {
Color::Byte(254)
} else {
Color::Byte(235)
};
let (upper_left, bottom_right) = area;
let width = self.content.size().0;
let (x, y) = upper_left;
@ -157,7 +163,7 @@ impl ListingTrait for ConversationsListing {
grid[(x, y + 1)].set_fg(fg_color);
grid[(x, y + 1)].set_bg(bg_color);
grid[(x, y + 2)].set_fg(Color::Byte(235));
grid[(x, y + 2)].set_fg(padding_fg);
grid[(x, y + 2)].set_bg(bg_color);
}
} else if width < width!(area) {
@ -169,7 +175,7 @@ impl ListingTrait for ConversationsListing {
grid[(x, y + 1)].set_fg(fg_color);
grid[(x, y + 1)].set_bg(bg_color);
grid[(x, y + 2)].set_fg(Color::Byte(235));
grid[(x, y + 2)].set_fg(padding_fg);
grid[(x, y + 2)].set_bg(bg_color);
}
}
@ -362,6 +368,12 @@ impl ListingTrait for ConversationsListing {
/* fill any remaining columns, if our view is wider than self.content */
let width = self.content.size().0;
let padding_fg = if context.settings.terminal.theme == "light" {
Color::Byte(254)
} else {
Color::Byte(235)
};
if width < width!(area) {
let y_offset = get_y(upper_left);
for y in 0..rows {
@ -372,7 +384,7 @@ impl ListingTrait for ConversationsListing {
grid[(x, y_offset + 3 * y + 2)].set_fg(Color::Default);
grid[(x, y_offset + 3 * y + 1)].set_bg(bg_color);
grid[(x, y_offset + 3 * y + 2)].set_ch('▓');
grid[(x, y_offset + 3 * y + 2)].set_fg(Color::Byte(235));
grid[(x, y_offset + 3 * y + 2)].set_fg(padding_fg);
grid[(x, y_offset + 3 * y + 2)].set_bg(bg_color);
}
}
@ -643,6 +655,12 @@ impl ConversationsListing {
let width = std::cmp::min(MAX_COLS, max_entry_columns);
self.content = CellBuffer::new(width, 4 * rows.len(), Cell::with_char(' '));
let padding_fg = if context.settings.terminal.theme == "light" {
Color::Byte(254)
} else {
Color::Byte(235)
};
for ((idx, root_idx), strings) in threads.root_iter().enumerate().zip(rows) {
let thread_node = &threads.thread_nodes()[&root_idx];
let i = if let Some(i) = thread_node.message() {
@ -724,7 +742,7 @@ impl ConversationsListing {
}
for x in 0..width {
self.content[(x, 3 * idx + 2)].set_ch('▓');
self.content[(x, 3 * idx + 2)].set_fg(Color::Byte(235));
self.content[(x, 3 * idx + 2)].set_fg(padding_fg);
self.content[(x, 3 * idx + 2)].set_bg(bg_color);
}
}
@ -1074,10 +1092,15 @@ impl Component for ConversationsListing {
fg_color,
bg_color,
);
let padding_fg = if context.settings.terminal.theme == "light" {
Color::Byte(254)
} else {
Color::Byte(235)
};
change_colors(
&mut self.content,
((0, 3 * row + 2), (width - 1, 3 * row + 2)),
Color::Byte(235),
padding_fg,
bg_color,
);
let rows = (get_y(bottom_right) - get_y(upper_left) + 1) / 3;

View File

@ -102,14 +102,26 @@ impl ListingTrait for PlainListing {
} else {
Color::Default
};
let bg_color = if self.cursor_pos.2 == idx {
Color::Byte(246)
} else if !envelope.is_seen() {
Color::Byte(251)
} else if idx % 2 == 0 {
Color::Byte(236)
let bg_color = if context.settings.terminal.theme == "light" {
if self.cursor_pos.2 == idx {
Color::Byte(246)
} else if !envelope.is_seen() {
Color::Byte(251)
} else if idx % 2 == 0 {
Color::Byte(252)
} else {
Color::Default
}
} else {
Color::Default
if self.cursor_pos.2 == idx {
Color::Byte(246)
} else if !envelope.is_seen() {
Color::Byte(251)
} else if idx % 2 == 0 {
Color::Byte(236)
} else {
Color::Default
}
};
change_colors(grid, area, fg_color, bg_color);
}
@ -369,12 +381,22 @@ impl PlainListing {
} else {
Color::Default
};
let bg_color = if !envelope.is_seen() {
Color::Byte(251)
} else if idx % 2 == 0 {
Color::Byte(236)
let bg_color = if context.settings.terminal.theme == "light" {
if !envelope.is_seen() {
Color::Byte(251)
} else if idx % 2 == 0 {
Color::Byte(252)
} else {
Color::Default
}
} else {
Color::Default
if !envelope.is_seen() {
Color::Byte(251)
} else if idx % 2 == 0 {
Color::Byte(236)
} else {
Color::Default
}
};
let (x, _) = write_string_to_grid(
&rows[idx].0,
@ -432,12 +454,20 @@ impl PlainListing {
}
}
fn unhighlight_line(&mut self, idx: usize) {
fn unhighlight_line(&mut self, idx: usize, context: &Context) {
let fg_color = Color::Default;
let bg_color = if idx % 2 == 0 {
Color::Byte(236)
let bg_color = if context.settings.terminal.theme == "light" {
if idx % 2 == 0 {
Color::Byte(252)
} else {
Color::Default
}
} else {
Color::Default
if idx % 2 == 0 {
Color::Byte(236)
} else {
Color::Default
}
};
change_colors(
&mut self.content,
@ -503,7 +533,7 @@ impl Component for PlainListing {
}
};
if must_unhighlight {
self.unhighlight_line(idx);
self.unhighlight_line(idx, context);
}
let mid = get_y(upper_left) + total_rows - bottom_entity_rows;
self.draw_list(

View File

@ -334,6 +334,12 @@ impl Component for MailView {
}
let envelope: &Envelope = &account.get_env(&self.coordinates.2);
let header_fg = if context.settings.terminal.theme == "light" {
Color::Black
} else {
Color::Byte(33)
};
if self.mode == ViewMode::Raw {
clear_area(grid, area);
context.dirty_areas.push_back(area);
@ -342,7 +348,7 @@ impl Component for MailView {
let (x, y) = write_string_to_grid(
&format!("Date: {}", envelope.date_as_str()),
grid,
Color::Byte(33),
header_fg,
Color::Default,
Attr::Default,
area,
@ -356,7 +362,7 @@ impl Component for MailView {
let (x, y) = write_string_to_grid(
&format!("From: {}", envelope.field_from_to_string()),
grid,
Color::Byte(33),
header_fg,
Color::Default,
Attr::Default,
(set_y(upper_left, y + 1), bottom_right),
@ -370,7 +376,7 @@ impl Component for MailView {
let (x, y) = write_string_to_grid(
&format!("To: {}", envelope.field_to_to_string()),
grid,
Color::Byte(33),
header_fg,
Color::Default,
Attr::Default,
(set_y(upper_left, y + 1), bottom_right),
@ -384,7 +390,7 @@ impl Component for MailView {
let (x, y) = write_string_to_grid(
&format!("Subject: {}", envelope.subject()),
grid,
Color::Byte(33),
header_fg,
Color::Default,
Attr::Default,
(set_y(upper_left, y + 1), bottom_right),
@ -398,7 +404,7 @@ impl Component for MailView {
let (x, mut y) = write_string_to_grid(
&format!("Message-ID: <{}>", envelope.message_id_raw()),
grid,
Color::Byte(33),
header_fg,
Color::Default,
Attr::Default,
(set_y(upper_left, y + 1), bottom_right),
@ -413,7 +419,7 @@ impl Component for MailView {
let (x, _y) = write_string_to_grid(
&format!("In-Reply-To: {}", envelope.in_reply_to_display().unwrap()),
grid,
Color::Byte(33),
header_fg,
Color::Default,
Attr::Default,
(set_y(upper_left, y + 1), bottom_right),
@ -435,7 +441,7 @@ impl Component for MailView {
.join(", ")
),
grid,
Color::Byte(33),
header_fg,
Color::Default,
Attr::Default,
(set_y(upper_left, _y + 1), bottom_right),
@ -461,7 +467,7 @@ impl Component for MailView {
let (_x, _) = write_string_to_grid(
"List-ID: ",
grid,
Color::Byte(33),
header_fg,
Color::Default,
Attr::Default,
(set_y(upper_left, y), bottom_right),
@ -482,7 +488,7 @@ impl Component for MailView {
let (_x, _) = write_string_to_grid(
" Available actions: [ ",
grid,
Color::Byte(33),
header_fg,
Color::Default,
Attr::Default,
((x, y), bottom_right),
@ -528,7 +534,7 @@ impl Component for MailView {
}
if archive.is_some() || post.is_some() || unsubscribe.is_some() {
grid[(x - 2, y)].set_ch(' ');
grid[(x - 1, y)].set_fg(Color::Byte(33));
grid[(x - 1, y)].set_fg(header_fg);
grid[(x - 1, y)].set_bg(Color::Default);
grid[(x - 1, y)].set_ch(']');
}

View File

@ -29,6 +29,7 @@ pub mod notifications;
pub mod pager;
pub mod pgp;
pub mod shortcuts;
pub mod terminal;
pub mod accounts;
pub use self::accounts::Account;
@ -38,6 +39,7 @@ pub use self::shortcuts::*;
use self::default_vals::*;
use self::notifications::NotificationsSettings;
use self::terminal::TerminalSettings;
use crate::pager::PagerSettings;
use melib::backends::SpecialUseMailbox;
use melib::conf::AccountSettings;
@ -277,6 +279,8 @@ struct FileSettings {
composing: ComposingSettings,
#[serde(default)]
pgp: PGPSettings,
#[serde(default)]
terminal: TerminalSettings,
}
#[derive(Debug, Clone, Default)]
@ -306,6 +310,7 @@ pub struct Settings {
pub shortcuts: Shortcuts,
pub composing: ComposingSettings,
pub pgp: PGPSettings,
pub terminal: TerminalSettings,
}
impl FileSettings {
@ -394,6 +399,7 @@ impl Settings {
shortcuts: fs.shortcuts,
composing: fs.composing,
pgp: fs.pgp,
terminal: fs.terminal,
}
}
}

View File

@ -0,0 +1,36 @@
/*
* meli - configuration module.
*
* Copyright 2019 Manos Pitsidianakis
*
* This file is part of meli.
*
* meli is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* meli is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
/// Settings for terminal display
#[derive(Debug, Deserialize, Clone, Serialize)]
pub struct TerminalSettings {
#[serde(default)]
/// light, dark
pub theme: String,
}
impl Default for TerminalSettings {
fn default() -> Self {
TerminalSettings {
theme: "dark".to_string(),
}
}
}