conf: add a light theme option
parent
a0602274f8
commit
b25f10f92a
6
meli.1
6
meli.1
|
@ -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
|
||||
^^ .-=-=-=-. ^^
|
||||
^^ (`-=-=-=-=-`) ^^
|
||||
|
|
11
meli.conf.5
11
meli.conf.5
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -93,7 +93,18 @@ 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 {
|
||||
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 {
|
||||
if self.cursor_pos.2 == idx {
|
||||
Color::Byte(246)
|
||||
} else if self.selection[&i] {
|
||||
Color::Byte(210)
|
||||
|
@ -101,6 +112,7 @@ impl ListingTrait for CompactListing {
|
|||
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() {
|
||||
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 {
|
||||
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(),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -102,7 +102,18 @@ impl ListingTrait for PlainListing {
|
|||
} else {
|
||||
Color::Default
|
||||
};
|
||||
let bg_color = if self.cursor_pos.2 == idx {
|
||||
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 {
|
||||
if self.cursor_pos.2 == idx {
|
||||
Color::Byte(246)
|
||||
} else if !envelope.is_seen() {
|
||||
Color::Byte(251)
|
||||
|
@ -110,6 +121,7 @@ impl ListingTrait for PlainListing {
|
|||
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() {
|
||||
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 {
|
||||
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 {
|
||||
let bg_color = if context.settings.terminal.theme == "light" {
|
||||
if idx % 2 == 0 {
|
||||
Color::Byte(252)
|
||||
} else {
|
||||
Color::Default
|
||||
}
|
||||
} else {
|
||||
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(
|
||||
|
|
|
@ -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(']');
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue