summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2019-10-06 11:28:12 +0300
committerManos Pitsidianakis <el13635@mail.ntua.gr>2019-10-06 11:32:35 +0300
commit6f816d29c56ffcdb8937464ac3e460c63135979a (patch)
tree6b376b986af65930b53e8c1fe070a0c411293bdd
parentb25f10f92a299309a8319c22c3ca0c7da8b6689f (diff)
conf: add ascii_drawing option
If set to true, box drawing is done with ascii characters.
-rw-r--r--meli.conf.55
-rw-r--r--ui/src/components.rs41
-rw-r--r--ui/src/components/mail/compose.rs7
-rw-r--r--ui/src/components/mail/listing/compact.rs36
-rw-r--r--ui/src/components/mail/listing/conversations.rs15
-rw-r--r--ui/src/components/mail/view.rs1
-rw-r--r--ui/src/components/mail/view/thread.rs2
-rw-r--r--ui/src/components/utilities.rs53
-rw-r--r--ui/src/conf/terminal.rs3
-rw-r--r--ui/src/state.rs11
-rw-r--r--ui/src/terminal/cells.rs16
11 files changed, 135 insertions, 55 deletions
diff --git a/meli.conf.5 b/meli.conf.5
index 0c24bd5e..3ffd9569 100644
--- a/meli.conf.5
+++ b/meli.conf.5
@@ -317,6 +317,11 @@ auto verify signed e-mail according to RFC3156
(optional) select between these themes: light / dark
.\" default value
.Pq Em dark
+.It Cm ascii_drawing Ar boolean
+(optional) if true, box drawing will be done with ascii characters.
+.\" default value
+.Pq Em false
+.El
.Sh SEE ALSO
.Xr meli 1
.Sh CONFORMING TO
diff --git a/ui/src/components.rs b/ui/src/components.rs
index f19bcf99..dd3febb7 100644
--- a/ui/src/components.rs
+++ b/ui/src/components.rs
@@ -90,7 +90,7 @@ pub trait Component: Display + Debug + Send {
fn is_visible(&self) -> bool {
true
}
- fn can_quit_cleanly(&mut self) -> bool {
+ fn can_quit_cleanly(&mut self, _context: &Context) -> bool {
true
}
fn set_dirty(&mut self);
@@ -374,6 +374,17 @@ pub(crate) fn set_and_join_box(grid: &mut CellBuffer, idx: Pos, ch: char) {
* 0b____
*/
+ if grid.ascii_drawing {
+ grid[idx].set_ch(match ch {
+ '│' => '|',
+ '─' => '-',
+ _ => unreachable!(),
+ });
+
+ grid[idx].set_fg(Color::Byte(240));
+ return;
+ }
+
let bin_set = match ch {
'│' => set_and_join_vert(grid, idx),
'─' => set_and_join_horz(grid, idx),
@@ -391,19 +402,21 @@ pub fn create_box(grid: &mut CellBuffer, area: Area) {
let upper_left = upper_left!(area);
let bottom_right = bottom_right!(area);
- for x in get_x(upper_left)..get_x(bottom_right) {
- grid[(x, get_y(upper_left))].set_ch(HORZ_BOUNDARY);
- grid[(x, get_y(bottom_right))].set_ch(HORZ_BOUNDARY);
- grid[(x, get_y(bottom_right))].set_fg(Color::Byte(240));
- }
+ if !grid.ascii_drawing {
+ for x in get_x(upper_left)..get_x(bottom_right) {
+ grid[(x, get_y(upper_left))].set_ch(HORZ_BOUNDARY);
+ grid[(x, get_y(bottom_right))].set_ch(HORZ_BOUNDARY);
+ grid[(x, get_y(bottom_right))].set_fg(Color::Byte(240));
+ }
- for y in get_y(upper_left)..get_y(bottom_right) {
- grid[(get_x(upper_left), y)].set_ch(VERT_BOUNDARY);
- grid[(get_x(bottom_right), y)].set_ch(VERT_BOUNDARY);
- grid[(get_x(bottom_right), y)].set_fg(Color::Byte(240));
+ for y in get_y(upper_left)..get_y(bottom_right) {
+ grid[(get_x(upper_left), y)].set_ch(VERT_BOUNDARY);
+ grid[(get_x(bottom_right), y)].set_ch(VERT_BOUNDARY);
+ grid[(get_x(bottom_right), y)].set_fg(Color::Byte(240));
+ }
+ set_and_join_box(grid, upper_left, HORZ_BOUNDARY);
+ set_and_join_box(grid, set_x(upper_left, get_x(bottom_right)), HORZ_BOUNDARY);
+ set_and_join_box(grid, set_y(upper_left, get_y(bottom_right)), VERT_BOUNDARY);
+ set_and_join_box(grid, bottom_right, VERT_BOUNDARY);
}
- set_and_join_box(grid, upper_left, HORZ_BOUNDARY);
- set_and_join_box(grid, set_x(upper_left, get_x(bottom_right)), HORZ_BOUNDARY);
- set_and_join_box(grid, set_y(upper_left, get_y(bottom_right)), VERT_BOUNDARY);
- set_and_join_box(grid, bottom_right, VERT_BOUNDARY);
}
diff --git a/ui/src/components/mail/compose.rs b/ui/src/components/mail/compose.rs
index b9bfc739..25497994 100644
--- a/ui/src/components/mail/compose.rs
+++ b/ui/src/components/mail/compose.rs
@@ -171,6 +171,7 @@ impl Composer {
(list_address, list_address_string),
],
false,
+ context,
));
}
}
@@ -826,7 +827,7 @@ impl Component for Composer {
}
}
- fn kill(&mut self, uuid: Uuid, _context: &mut Context) {
+ fn kill(&mut self, uuid: Uuid, context: &mut Context) {
self.mode = ViewMode::Discard(
uuid,
Selector::new(
@@ -837,6 +838,7 @@ impl Component for Composer {
('n', "cancel".to_string()),
],
true,
+ context,
),
);
}
@@ -873,7 +875,7 @@ impl Component for Composer {
self.id = id;
}
- fn can_quit_cleanly(&mut self) -> bool {
+ fn can_quit_cleanly(&mut self, context: &Context) -> bool {
/* Play it safe and ask user for confirmation */
self.mode = ViewMode::Discard(
self.id,
@@ -885,6 +887,7 @@ impl Component for Composer {
('n', "cancel".to_string()),
],
true,
+ context,
),
);
self.set_dirty();
diff --git a/ui/src/components/mail/listing/compact.rs b/ui/src/components/mail/listing/compact.rs
index e486009d..82bf0786 100644
--- a/ui/src/components/mail/listing/compact.rs
+++ b/ui/src/components/mail/listing/compact.rs
@@ -405,7 +405,8 @@ impl ListingTrait for CompactListing {
),
ERROR,
);
- self.data_columns.columns[0] = CellBuffer::new(message.len(), 1, Cell::with_char(' '));
+ self.data_columns.columns[0] =
+ CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context);
write_string_to_grid(
&message,
&mut self.data_columns.columns[0],
@@ -422,7 +423,8 @@ impl ListingTrait for CompactListing {
} else {
self.length = 0;
let message = format!("No results for `{}`.", filter_term);
- self.data_columns.columns[0] = CellBuffer::new(message.len(), 1, Cell::with_char(' '));
+ self.data_columns.columns[0] =
+ CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context);
write_string_to_grid(
&message,
&mut self.data_columns.columns[0],
@@ -530,7 +532,7 @@ impl CompactListing {
Err(_) => {
let message: String = context.accounts[self.cursor_pos.0][folder_hash].to_string();
self.data_columns.columns[0] =
- CellBuffer::new(message.len(), 1, Cell::with_char(' '));
+ CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context);
self.length = 0;
write_string_to_grid(
message.as_str(),
@@ -610,19 +612,19 @@ impl CompactListing {
/* index column */
self.data_columns.columns[0] =
- CellBuffer::new(min_width.0, rows.len(), Cell::with_char(' '));
+ CellBuffer::new_with_context(min_width.0, rows.len(), Cell::with_char(' '), context);
/* date column */
self.data_columns.columns[1] =
- CellBuffer::new(min_width.1, rows.len(), Cell::with_char(' '));
+ CellBuffer::new_with_context(min_width.1, rows.len(), Cell::with_char(' '), context);
/* from column */
self.data_columns.columns[2] =
- CellBuffer::new(min_width.2, rows.len(), Cell::with_char(' '));
+ CellBuffer::new_with_context(min_width.2, rows.len(), Cell::with_char(' '), context);
/* flags column */
self.data_columns.columns[3] =
- CellBuffer::new(min_width.3, rows.len(), Cell::with_char(' '));
+ CellBuffer::new_with_context(min_width.3, rows.len(), Cell::with_char(' '), context);
/* subject column */
self.data_columns.columns[4] =
- CellBuffer::new(min_width.4, rows.len(), Cell::with_char(' '));
+ CellBuffer::new_with_context(min_width.4, rows.len(), Cell::with_char(' '), context);
for ((idx, root_idx), strings) in threads.root_iter().enumerate().zip(rows) {
let thread_node = &threads.thread_nodes()[&root_idx];
@@ -750,8 +752,12 @@ impl CompactListing {
if self.length == 0 {
let mailbox = &account[self.cursor_pos.1];
let message = mailbox.to_string();
- self.data_columns.columns[0] =
- CellBuffer::new(message.len(), self.length + 1, Cell::with_char(' '));
+ self.data_columns.columns[0] = CellBuffer::new_with_context(
+ message.len(),
+ self.length + 1,
+ Cell::with_char(' '),
+ context,
+ );
write_string_to_grid(
&message,
&mut self.data_columns.columns[0],
@@ -803,19 +809,19 @@ impl CompactListing {
/* index column */
self.data_columns.columns[0] =
- CellBuffer::new(min_width.0, rows.len(), Cell::with_char(' '));
+ CellBuffer::new_with_context(min_width.0, rows.len(), Cell::with_char(' '), context);
/* date column */
self.data_columns.columns[1] =
- CellBuffer::new(min_width.1, rows.len(), Cell::with_char(' '));
+ CellBuffer::new_with_context(min_width.1, rows.len(), Cell::with_char(' '), context);
/* from column */
self.data_columns.columns[2] =
- CellBuffer::new(min_width.2, rows.len(), Cell::with_char(' '));
+ CellBuffer::new_with_context(min_width.2, rows.len(), Cell::with_char(' '), context);
/* flags column */
self.data_columns.columns[3] =
- CellBuffer::new(min_width.3, rows.len(), Cell::with_char(' '));
+ CellBuffer::new_with_context(min_width.3, rows.len(), Cell::with_char(' '), context);
/* subject column */
self.data_columns.columns[4] =
- CellBuffer::new(min_width.4, rows.len(), Cell::with_char(' '));
+ CellBuffer::new_with_context(min_width.4, rows.len(), Cell::with_char(' '), context);
for ((idx, thread_hash), strings) in self.filtered_selection.iter().enumerate().zip(rows) {
let i = threads.thread_nodes()[thread_hash].message().unwrap();
diff --git a/ui/src/components/mail/listing/conversations.rs b/ui/src/components/mail/listing/conversations.rs
index 7289f081..4010907a 100644
--- a/ui/src/components/mail/listing/conversations.rs
+++ b/ui/src/components/mail/listing/conversations.rs
@@ -448,7 +448,8 @@ impl ListingTrait for ConversationsListing {
if let Some(error) = error {
self.length = 0;
let message = format!("Error: {}", error.to_string());
- self.content = CellBuffer::new(message.len(), 1, Cell::with_char(' '));
+ self.content =
+ CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context);
write_string_to_grid(
&message,
&mut self.content,
@@ -465,7 +466,8 @@ impl ListingTrait for ConversationsListing {
} else {
self.length = 0;
let message = format!("No results for `{}`.", filter_term);
- self.content = CellBuffer::new(message.len(), 1, Cell::with_char(' '));
+ self.content =
+ CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context);
write_string_to_grid(
&message,
&mut self.content,
@@ -576,7 +578,8 @@ impl ConversationsListing {
Ok(()) => {}
Err(_) => {
let message: String = context.accounts[self.cursor_pos.0][folder_hash].to_string();
- self.content = CellBuffer::new(message.len(), 1, Cell::with_char(' '));
+ self.content =
+ CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context);
self.length = 0;
write_string_to_grid(
message.as_str(),
@@ -653,7 +656,8 @@ impl ConversationsListing {
selection.retain(|e, _| order.contains_key(e));
let width = std::cmp::min(MAX_COLS, max_entry_columns);
- self.content = CellBuffer::new(width, 4 * rows.len(), Cell::with_char(' '));
+ self.content =
+ CellBuffer::new_with_context(width, 4 * rows.len(), Cell::with_char(' '), context);
let padding_fg = if context.settings.terminal.theme == "light" {
Color::Byte(254)
@@ -749,7 +753,8 @@ impl ConversationsListing {
if self.length == 0 {
let mailbox = &account[self.cursor_pos.1];
let message = mailbox.to_string();
- self.content = CellBuffer::new(message.len(), 1, Cell::with_char(' '));
+ self.content =
+ CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context);
write_string_to_grid(
&message,
&mut self.content,
diff --git a/ui/src/components/mail/view.rs b/ui/src/components/mail/view.rs
index 6845e28a..1a6dbc57 100644
--- a/ui/src/components/mail/view.rs
+++ b/ui/src/components/mail/view.rs
@@ -706,6 +706,7 @@ impl Component for MailView {
"select contacts to add",
entries,
false,
+ context,
));
self.dirty = true;
return true;
diff --git a/ui/src/components/mail/view/thread.rs b/ui/src/components/mail/view/thread.rs
index f84ad207..a5100e66 100644
--- a/ui/src/components/mail/view/thread.rs
+++ b/ui/src/components/mail/view/thread.rs
@@ -222,7 +222,7 @@ impl ThreadView {
e.heading = string;
width = cmp::max(width, e.index.0 * 4 + e.heading.grapheme_width() + 2);
}
- let mut content = CellBuffer::new(width, height, Cell::default());
+ let mut content = CellBuffer::new_with_context(width, height, Cell::default(), context);
if self.reversed {
for (y, e) in self.entries.iter().rev().enumerate() {
/* Box character drawing stuff */
diff --git a/ui/src/components/utilities.rs b/ui/src/components/utilities.rs
index 9c744fb1..a065ea2a 100644
--- a/ui/src/components/utilities.rs
+++ b/ui/src/components/utilities.rs
@@ -305,7 +305,9 @@ impl Pager {
let height = lines.len() + 1;
let width = width.unwrap_or_else(|| lines.iter().map(|l| l.len()).max().unwrap_or(0));
+ let ascii_drawing = self.content.ascii_drawing;
let mut content = CellBuffer::new(width, height, Cell::with_char(' '));
+ content.set_ascii_drawing(ascii_drawing);
Pager::print_string(&mut content, lines);
self.text = text.to_string();
self.content = content;
@@ -361,7 +363,11 @@ impl Pager {
let height = lines.len() + 1;
let width = width.unwrap_or_else(|| lines.iter().map(|l| l.len()).max().unwrap_or(0));
- let mut content = CellBuffer::new(width, height, Cell::with_char(' '));
+ let mut content = if let Some(context) = context {
+ CellBuffer::new_with_context(width, height, Cell::with_char(' '), context)
+ } else {
+ CellBuffer::new(width, height, Cell::with_char(' '))
+ };
//interpret_format_flowed(&text);
Pager::print_string(&mut content, lines);
content
@@ -479,7 +485,8 @@ impl Component for Pager {
let height = lines.len() + 1;
self.width = width;
self.height = height;
- self.content = CellBuffer::new(width, height, Cell::with_char(' '));
+ self.content =
+ CellBuffer::new_with_context(width, height, Cell::with_char(' '), context);
Pager::print_string(&mut self.content, lines);
}
if self.cursor_pos + height >= self.height {
@@ -1067,8 +1074,8 @@ impl Component for StatusBar {
self.id = id;
}
- fn can_quit_cleanly(&mut self) -> bool {
- self.container.can_quit_cleanly()
+ fn can_quit_cleanly(&mut self, context: &Context) -> bool {
+ self.container.can_quit_cleanly(context)
}
}
@@ -1335,7 +1342,8 @@ impl Component for Tabbed {
),
);
}
- self.help_content = CellBuffer::new(max_width, max_length + 2, Cell::default());
+ self.help_content =
+ CellBuffer::new_with_context(max_width, max_length + 2, Cell::default(), context);
let (width, height) = self.help_content.size();
let (cols, rows) = (width!(area), height!(area));
if cols == 0 || rows == 0 {
@@ -1556,9 +1564,9 @@ impl Component for Tabbed {
self.id = id;
}
- fn can_quit_cleanly(&mut self) -> bool {
+ fn can_quit_cleanly(&mut self, context: &Context) -> bool {
for (i, c) in self.children.iter_mut().enumerate() {
- if !c.can_quit_cleanly() {
+ if !c.can_quit_cleanly(context) {
self.cursor_pos = i;
self.set_dirty();
return false;
@@ -1843,7 +1851,12 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Component for Selector<T> {
}
impl<T: PartialEq + Debug + Clone + Sync + Send> Selector<T> {
- pub fn new(title: &str, entries: Vec<(T, String)>, single_only: bool) -> Selector<T> {
+ pub fn new(
+ title: &str,
+ entries: Vec<(T, String)>,
+ single_only: bool,
+ context: &Context,
+ ) -> Selector<T> {
let width = std::cmp::max(
"OK Cancel".len(),
std::cmp::max(
@@ -1863,9 +1876,11 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Selector<T> {
/* Extra room for buttons Okay/Cancel */
3
};
- let mut content = CellBuffer::new(width, height, Cell::with_char(' '));
+ let mut content =
+ CellBuffer::new_with_context(width, height, Cell::with_char(' '), context);
+ let ascii_drawing = context.settings.terminal.ascii_drawing;
write_string_to_grid(
- "┏━",
+ if ascii_drawing { "+-" } else { "┏━" },
&mut content,
Color::Byte(8),
Color::Default,
@@ -1884,7 +1899,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Selector<T> {
);
for i in 1..(width - title.len() - 1) {
write_string_to_grid(
- "━",
+ if ascii_drawing { "-" } else { "━" },
&mut content,
Color::Byte(8),
Color::Default,
@@ -1894,7 +1909,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Selector<T> {
);
}
write_string_to_grid(
- "┓",
+ if ascii_drawing { "+" } else { "┓" },
&mut content,
Color::Byte(8),
Color::Default,
@@ -1903,7 +1918,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Selector<T> {
false,
);
write_string_to_grid(
- "┗",
+ if ascii_drawing { "+" } else { "┗" },
&mut content,
Color::Byte(8),
Color::Default,
@@ -1912,7 +1927,11 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Selector<T> {
false,
);
write_string_to_grid(
- &"━".repeat(width - 2),
+ &if ascii_drawing {
+ "-".repeat(width - 2)
+ } else {
+ "━".repeat(width - 2)
+ },
&mut content,
Color::Byte(8),
Color::Default,
@@ -1921,7 +1940,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Selector<T> {
false,
);
write_string_to_grid(
- "┛",
+ if ascii_drawing { "+" } else { "┛" },
&mut content,
Color::Byte(8),
Color::Default,
@@ -1931,7 +1950,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Selector<T> {
);
for i in 1..height - 1 {
write_string_to_grid(
- "┃",
+ if ascii_drawing { "|" } else { "┃" },
&mut content,
Color::Byte(8),
Color::Default,
@@ -1940,7 +1959,7 @@ impl<T: PartialEq + Debug + Clone + Sync + Send> Selector<T> {
false,
);
write_string_to_grid(
- "┃",
+ if ascii_drawing { "|" } else { "┃" },
&mut content,
Color::Byte(8),
Color::Default,
diff --git a/ui/src/conf/terminal.rs b/ui/src/conf/terminal.rs
index 2861cb50..2e6887c2 100644
--- a/ui/src/conf/terminal.rs
+++ b/ui/src/conf/terminal.rs
@@ -25,12 +25,15 @@ pub struct TerminalSettings {
#[serde(default)]
/// light, dark
pub theme: String,
+ #[serde(default)]
+ pub ascii_drawing: bool,
}
impl Default for TerminalSettings {
fn default() -> Self {
TerminalSettings {
theme: "dark".to_string(),
+ ascii_drawing: false,
}
}
}
diff --git a/ui/src/state.rs b/ui/src/state.rs
index c924669f..57446366 100644
--- a/ui/src/state.rs
+++ b/ui/src/state.rs
@@ -235,6 +235,10 @@ impl State {
},
threads: FnvHashMap::with_capacity_and_hasher(1, Default::default()),
};
+ if s.context.settings.terminal.ascii_drawing {
+ s.grid.set_ascii_drawing(true);
+ }
+
for a in s.context.accounts.iter_mut() {
for worker in a.workers.values_mut() {
if let Some(worker) = worker.as_mut() {
@@ -513,7 +517,12 @@ impl State {
}
pub fn can_quit_cleanly(&mut self) -> bool {
- self.components.iter_mut().all(|c| c.can_quit_cleanly())
+ let State {
+ ref mut components,
+ ref context,
+ ..
+ } = self;
+ components.iter_mut().all(|c| c.can_quit_cleanly(context))
}
pub fn register_component(&mut self, component: Box<dyn Component>) {
diff --git a/ui/src/terminal/cells.rs b/ui/src/terminal/cells.rs
index 0db2f079..ef7773bf 100644
--- a/ui/src/terminal/cells.rs
+++ b/ui/src/terminal/cells.rs
@@ -25,6 +25,7 @@
*/
use super::position::*;
+use crate::state::Context;
use text_processing::wcwidth;
use std::convert::From;
@@ -105,6 +106,7 @@ pub struct CellBuffer {
cols: usize,
rows: usize,
buf: Vec<Cell>,
+ pub ascii_drawing: bool,
}
impl fmt::Debug for CellBuffer {
@@ -137,9 +139,23 @@ impl CellBuffer {
cols,
rows,
buf: vec![cell; cols * rows],
+ ascii_drawing: false,
}
}
+ pub fn new_with_context(cols: usize, rows: usize, cell: Cell, context: &Context) -> CellBuffer {
+ CellBuffer {
+ cols,
+ rows,
+ buf: vec![cell; cols * rows],
+ ascii_drawing: context.settings.terminal.ascii_drawing,
+ }
+ }
+
+ pub fn set_ascii_drawing(&mut self, new_val: bool) {
+ self.ascii_drawing = new_val;
+ }
+
/// Resizes `CellBuffer` to the given number of rows and columns, using the given `Cell` as
/// a blank.
pub fn resize(&mut self, newcols: usize, newrows: usize, blank: Cell) {