listing: add relative_list_indices setting for thread listing
parent
8abc9358a7
commit
561ba9c87b
|
@ -48,6 +48,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
Warn if draft has no subject and no body.
|
||||
|
||||
They can be disabled with `[composing.disabled_compose_hooks]` setting.
|
||||
- `e9cd800f` Added support for storing flags locally for NNTP accounts.
|
||||
- Added options to show relative row numbers in menus and listings to make jumping easier.
|
||||
`[listing.relative_menu_indices]` and `[listing.relative_list_indices]`.
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
@ -1145,6 +1145,12 @@ Should threads with differentiating Subjects show a list of those subjects on th
|
|||
In threaded listing style, repeat identical From column values within a thread.
|
||||
Not repeating adds empty space in the From column which might result in less visual clutter.
|
||||
.Pq Em "false" \" default value
|
||||
.It Ic relative_menu_indices Ar bool
|
||||
Show relative indices in menu mailboxes to quickly help with jumping to them.
|
||||
.Pq Em true \" default value
|
||||
.It Ic relative_list_indices Ar bool
|
||||
Show relative indices in listings to quickly help with jumping to them.
|
||||
.Pq Em true \" default value
|
||||
.El
|
||||
.Ss Examples of sidebar mailbox tree customization
|
||||
The default values
|
||||
|
|
|
@ -529,6 +529,9 @@ impl ListingTrait for ThreadListing {
|
|||
if self.cursor_pos.2 != self.new_cursor_pos.2 && prev_page_no == page_no {
|
||||
let old_cursor_pos = self.cursor_pos;
|
||||
self.cursor_pos = self.new_cursor_pos;
|
||||
if *account_settings!(context[self.cursor_pos.0].listing.relative_list_indices) {
|
||||
self.draw_relative_numbers(grid, area, top_idx);
|
||||
}
|
||||
for &(idx, highlight) in &[(old_cursor_pos.2, false), (self.new_cursor_pos.2, true)] {
|
||||
if idx >= self.length {
|
||||
continue; //bounds check
|
||||
|
@ -544,6 +547,9 @@ impl ListingTrait for ThreadListing {
|
|||
}
|
||||
context.dirty_areas.push_back(new_area);
|
||||
}
|
||||
if *account_settings!(context[self.cursor_pos.0].listing.relative_list_indices) {
|
||||
context.dirty_areas.push_back(area);
|
||||
}
|
||||
if !self.force_draw {
|
||||
return;
|
||||
}
|
||||
|
@ -569,6 +575,9 @@ impl ListingTrait for ThreadListing {
|
|||
/* copy table columns */
|
||||
self.data_columns
|
||||
.draw(grid, top_idx, self.cursor_pos.2, grid.bounds_iter(area));
|
||||
if *account_settings!(context[self.cursor_pos.0].listing.relative_list_indices) {
|
||||
self.draw_relative_numbers(grid, area, top_idx);
|
||||
}
|
||||
/* apply each row colors separately */
|
||||
for i in top_idx..(top_idx + height!(area)) {
|
||||
if let Some(row_attr) = self.rows.row_attr_cache.get(&i) {
|
||||
|
@ -907,19 +916,21 @@ impl ThreadListing {
|
|||
panic!();
|
||||
}
|
||||
let row_attr = self.rows.row_attr_cache[&idx];
|
||||
let (x, _) = write_string_to_grid(
|
||||
&idx.to_string(),
|
||||
&mut self.data_columns.columns[0],
|
||||
row_attr.fg,
|
||||
row_attr.bg,
|
||||
row_attr.attrs,
|
||||
((0, idx), (min_width.0, idx)),
|
||||
None,
|
||||
);
|
||||
for x in x..min_width.0 {
|
||||
self.data_columns.columns[0][(x, idx)]
|
||||
.set_bg(row_attr.bg)
|
||||
.set_attrs(row_attr.attrs);
|
||||
if !*account_settings!(context[self.cursor_pos.0].listing.relative_list_indices) {
|
||||
let (x, _) = write_string_to_grid(
|
||||
&idx.to_string(),
|
||||
&mut self.data_columns.columns[0],
|
||||
row_attr.fg,
|
||||
row_attr.bg,
|
||||
row_attr.attrs,
|
||||
((0, idx), (min_width.0, idx)),
|
||||
None,
|
||||
);
|
||||
for x in x..min_width.0 {
|
||||
self.data_columns.columns[0][(x, idx)]
|
||||
.set_bg(row_attr.bg)
|
||||
.set_attrs(row_attr.attrs);
|
||||
}
|
||||
}
|
||||
let (x, _) = write_string_to_grid(
|
||||
&strings.date,
|
||||
|
@ -1072,6 +1083,67 @@ impl ThreadListing {
|
|||
|
||||
*self.rows.entries.get_mut(idx).unwrap() = ((thread_hash, env_hash), strings);
|
||||
}
|
||||
|
||||
fn draw_relative_numbers(&mut self, grid: &mut CellBuffer, area: Area, top_idx: usize) {
|
||||
let width = self.data_columns.columns[0].size().0;
|
||||
let upper_left = upper_left!(area);
|
||||
for i in 0..height!(area) {
|
||||
let row_attr = row_attr!(self.color_cache, (top_idx + i) % 2 == 0, false, true, false);
|
||||
|
||||
clear_area(
|
||||
&mut self.data_columns.columns[0],
|
||||
((0, i), (width - 1, i + 1)),
|
||||
row_attr,
|
||||
);
|
||||
clear_area(
|
||||
grid,
|
||||
(
|
||||
pos_inc(upper_left, (0, i)),
|
||||
pos_inc(upper_left, (width - 1, i + 1)),
|
||||
),
|
||||
row_attr,
|
||||
);
|
||||
let (x, _) = write_string_to_grid(
|
||||
&if self.new_cursor_pos.2.saturating_sub(top_idx) == i {
|
||||
self.new_cursor_pos.2.to_string()
|
||||
} else {
|
||||
(i as isize - (self.new_cursor_pos.2 - top_idx) as isize)
|
||||
.abs()
|
||||
.to_string()
|
||||
},
|
||||
&mut self.data_columns.columns[0],
|
||||
row_attr.fg,
|
||||
row_attr.bg,
|
||||
row_attr.attrs,
|
||||
((0, i), (width, i + 1)),
|
||||
None,
|
||||
);
|
||||
for x in x..width {
|
||||
self.data_columns.columns[0][(x, i)]
|
||||
.set_ch(' ')
|
||||
.set_bg(row_attr.bg)
|
||||
.set_attrs(row_attr.attrs);
|
||||
}
|
||||
_ = write_string_to_grid(
|
||||
&if self.new_cursor_pos.2.saturating_sub(top_idx) == i {
|
||||
self.new_cursor_pos.2.to_string()
|
||||
} else {
|
||||
(i as isize - (self.new_cursor_pos.2 - top_idx) as isize)
|
||||
.abs()
|
||||
.to_string()
|
||||
},
|
||||
grid,
|
||||
row_attr.fg,
|
||||
row_attr.bg,
|
||||
row_attr.attrs,
|
||||
(
|
||||
pos_inc(upper_left, (0, i)),
|
||||
pos_inc(upper_left, (width, i + 1)),
|
||||
),
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for ThreadListing {
|
||||
|
|
|
@ -147,6 +147,11 @@ pub struct ListingSettings {
|
|||
/// them. Default: "true"
|
||||
#[serde(default = "true_val", alias = "relative-menu-indices")]
|
||||
pub relative_menu_indices: bool,
|
||||
|
||||
/// Show relative indices in listings to quickly help with jumping to
|
||||
/// them. Default: "true"
|
||||
#[serde(default = "true_val", alias = "relative-list-indices")]
|
||||
pub relative_list_indices: bool,
|
||||
}
|
||||
|
||||
const fn default_divider() -> char {
|
||||
|
@ -179,6 +184,7 @@ impl Default for ListingSettings {
|
|||
thread_subject_pack: true,
|
||||
threaded_repeat_identical_from_values: false,
|
||||
relative_menu_indices: true,
|
||||
relative_list_indices: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -218,6 +224,7 @@ impl DotAddressable for ListingSettings {
|
|||
.threaded_repeat_identical_from_values
|
||||
.lookup(field, tail),
|
||||
"relative_menu_indices" => self.relative_menu_indices.lookup(field, tail),
|
||||
"relative_list_indices" => self.relative_list_indices.lookup(field, tail),
|
||||
other => Err(Error::new(format!(
|
||||
"{} has no field named {}",
|
||||
parent_field, other
|
||||
|
|
|
@ -29,7 +29,7 @@ use melib::HeaderName;
|
|||
|
||||
# [derive (Debug , Serialize , Deserialize , Clone)] # [serde (deny_unknown_fields)] pub struct PagerSettingsOverride { # [doc = " Number of context lines when going to next page."] # [doc = " Default: 0"] # [serde (alias = "pager-context")] # [serde (default)] pub pager_context : Option < usize > , # [doc = " Stop at the end instead of displaying next mail."] # [doc = " Default: false"] # [serde (alias = "pager-stop")] # [serde (default)] pub pager_stop : Option < bool > , # [doc = " Always show headers when scrolling."] # [doc = " Default: true"] # [serde (alias = "sticky-headers" , alias = "headers-sticky" , alias = "headers_sticky")] # [serde (default)] pub sticky_headers : Option < bool > , # [doc = " The height of the pager in mail view, in percent."] # [doc = " Default: 80"] # [serde (alias = "pager-ratio")] # [serde (default)] pub pager_ratio : Option < usize > , # [doc = " A command to pipe mail output through for viewing in pager."] # [doc = " Default: None"] # [serde (deserialize_with = "non_empty_opt_string")] # [serde (default)] pub filter : Option < Option < String > > , # [doc = " A command to pipe html output before displaying it in a pager"] # [doc = " Default: None"] # [serde (deserialize_with = "non_empty_opt_string" , alias = "html-filter")] # [serde (default)] pub html_filter : Option < Option < String > > , # [doc = " Respect \"format=flowed\""] # [doc = " Default: true"] # [serde (alias = "format-flowed")] # [serde (default)] pub format_flowed : Option < bool > , # [doc = " Split long lines that would overflow on the x axis."] # [doc = " Default: true"] # [serde (alias = "split-long-lines")] # [serde (default)] pub split_long_lines : Option < bool > , # [doc = " Minimum text width in columns."] # [doc = " Default: 80"] # [serde (alias = "minimum-width")] # [serde (default)] pub minimum_width : Option < usize > , # [doc = " Choose `text/html` alternative if `text/plain` is empty in"] # [doc = " `multipart/alternative` attachments."] # [doc = " Default: true"] # [serde (alias = "auto-choose-multipart-alternative")] # [serde (default)] pub auto_choose_multipart_alternative : Option < ToggleFlag > , # [doc = " Show Date: in my timezone"] # [doc = " Default: true"] # [serde (alias = "show-date-in-my-timezone")] # [serde (default)] pub show_date_in_my_timezone : Option < ToggleFlag > , # [doc = " A command to launch URLs with. The URL will be given as the first"] # [doc = " argument of the command. Default: None"] # [serde (deserialize_with = "non_empty_opt_string")] # [serde (default)] pub url_launcher : Option < Option < String > > , # [doc = " A command to open html files."] # [doc = " Default: None"] # [serde (deserialize_with = "non_empty_opt_string" , alias = "html-open")] # [serde (default)] pub html_open : Option < Option < String > > , # [doc = " Extra headers to display, if present, in the default header preamble."] # [doc = " Default: []"] # [serde (alias = "show-extra-headers")] # [serde (default)] pub show_extra_headers : Option < Vec < String > > } impl Default for PagerSettingsOverride { fn default () -> Self { PagerSettingsOverride { pager_context : None , pager_stop : None , sticky_headers : None , pager_ratio : None , filter : None , html_filter : None , format_flowed : None , split_long_lines : None , minimum_width : None , auto_choose_multipart_alternative : None , show_date_in_my_timezone : None , url_launcher : None , html_open : None , show_extra_headers : None } } }
|
||||
|
||||
# [derive (Debug , Serialize , Deserialize , Clone)] # [serde (deny_unknown_fields)] pub struct ListingSettingsOverride { # [doc = " Number of context lines when going to next page."] # [doc = " Default: 0"] # [serde (alias = "context-lines")] # [serde (default)] pub context_lines : Option < usize > , # [doc = " Show auto-hiding scrollbar in accounts sidebar menu."] # [doc = " Default: True"] # [serde (default)] pub show_menu_scrollbar : Option < bool > , # [doc = " Datetime formatting passed verbatim to strftime(3)."] # [doc = " Default: %Y-%m-%d %T"] # [serde (alias = "datetime-fmt")] # [serde (default)] pub datetime_fmt : Option < Option < String > > , # [doc = " Show recent dates as `X {minutes,hours,days} ago`, up to 7 days."] # [doc = " Default: true"] # [serde (alias = "recent-dates")] # [serde (default)] pub recent_dates : Option < bool > , # [doc = " Show only envelopes that match this query"] # [doc = " Default: None"] # [serde (default)] pub filter : Option < Option < Query > > , # [serde (alias = "index-style")] # [serde (default)] pub index_style : Option < IndexStyle > , # [doc = " Default: \" \""] # [serde (default)] pub sidebar_mailbox_tree_has_sibling : Option < Option < String > > , # [doc = " Default: \" \""] # [serde (default)] pub sidebar_mailbox_tree_no_sibling : Option < Option < String > > , # [doc = " Default: \" \""] # [serde (default)] pub sidebar_mailbox_tree_has_sibling_leaf : Option < Option < String > > , # [doc = " Default: \" \""] # [serde (default)] pub sidebar_mailbox_tree_no_sibling_leaf : Option < Option < String > > , # [doc = " Default: ' '"] # [serde (default)] pub sidebar_divider : Option < char > , # [doc = " Default: 90"] # [serde (default)] pub sidebar_ratio : Option < usize > , # [doc = " Flag to show if thread entry contains unseen mail."] # [doc = " Default: \"●\""] # [serde (default)] pub unseen_flag : Option < Option < String > > , # [doc = " Flag to show if thread has been snoozed."] # [doc = " Default: \"💤\""] # [serde (default)] pub thread_snoozed_flag : Option < Option < String > > , # [doc = " Flag to show if thread entry has been selected."] # [doc = " Default: \"☑\u{fe0f}\""] # [serde (default)] pub selected_flag : Option < Option < String > > , # [doc = " Flag to show if thread entry contains attachments."] # [doc = " Default: \"📎\""] # [serde (default)] pub attachment_flag : Option < Option < String > > , # [doc = " Should threads with different Subjects show a list of those"] # [doc = " subjects on the entry title?"] # [doc = " Default: \"true\""] # [serde (default)] pub thread_subject_pack : Option < bool > , # [doc = " In threaded listing style, repeat identical From column values within a"] # [doc = " thread. Not repeating adds empty space in the From column which"] # [doc = " might result in less visual clutter."] # [doc = " Default: \"false\""] # [serde (default)] pub threaded_repeat_identical_from_values : Option < bool > , # [doc = " Show relative indices in menu mailboxes to quickly help with jumping to"] # [doc = " them. Default: \"true\""] # [serde (alias = "relative-menu-indices")] # [serde (default)] pub relative_menu_indices : Option < bool > } impl Default for ListingSettingsOverride { fn default () -> Self { ListingSettingsOverride { context_lines : None , show_menu_scrollbar : None , datetime_fmt : None , recent_dates : None , filter : None , index_style : None , sidebar_mailbox_tree_has_sibling : None , sidebar_mailbox_tree_no_sibling : None , sidebar_mailbox_tree_has_sibling_leaf : None , sidebar_mailbox_tree_no_sibling_leaf : None , sidebar_divider : None , sidebar_ratio : None , unseen_flag : None , thread_snoozed_flag : None , selected_flag : None , attachment_flag : None , thread_subject_pack : None , threaded_repeat_identical_from_values : None , relative_menu_indices : None } } }
|
||||
# [derive (Debug , Serialize , Deserialize , Clone)] # [serde (deny_unknown_fields)] pub struct ListingSettingsOverride { # [doc = " Number of context lines when going to next page."] # [doc = " Default: 0"] # [serde (alias = "context-lines")] # [serde (default)] pub context_lines : Option < usize > , # [doc = " Show auto-hiding scrollbar in accounts sidebar menu."] # [doc = " Default: True"] # [serde (default)] pub show_menu_scrollbar : Option < bool > , # [doc = " Datetime formatting passed verbatim to strftime(3)."] # [doc = " Default: %Y-%m-%d %T"] # [serde (alias = "datetime-fmt")] # [serde (default)] pub datetime_fmt : Option < Option < String > > , # [doc = " Show recent dates as `X {minutes,hours,days} ago`, up to 7 days."] # [doc = " Default: true"] # [serde (alias = "recent-dates")] # [serde (default)] pub recent_dates : Option < bool > , # [doc = " Show only envelopes that match this query"] # [doc = " Default: None"] # [serde (default)] pub filter : Option < Option < Query > > , # [serde (alias = "index-style")] # [serde (default)] pub index_style : Option < IndexStyle > , # [doc = " Default: \" \""] # [serde (default)] pub sidebar_mailbox_tree_has_sibling : Option < Option < String > > , # [doc = " Default: \" \""] # [serde (default)] pub sidebar_mailbox_tree_no_sibling : Option < Option < String > > , # [doc = " Default: \" \""] # [serde (default)] pub sidebar_mailbox_tree_has_sibling_leaf : Option < Option < String > > , # [doc = " Default: \" \""] # [serde (default)] pub sidebar_mailbox_tree_no_sibling_leaf : Option < Option < String > > , # [doc = " Default: ' '"] # [serde (default)] pub sidebar_divider : Option < char > , # [doc = " Default: 90"] # [serde (default)] pub sidebar_ratio : Option < usize > , # [doc = " Flag to show if thread entry contains unseen mail."] # [doc = " Default: \"●\""] # [serde (default)] pub unseen_flag : Option < Option < String > > , # [doc = " Flag to show if thread has been snoozed."] # [doc = " Default: \"💤\""] # [serde (default)] pub thread_snoozed_flag : Option < Option < String > > , # [doc = " Flag to show if thread entry has been selected."] # [doc = " Default: \"☑\u{fe0f}\""] # [serde (default)] pub selected_flag : Option < Option < String > > , # [doc = " Flag to show if thread entry contains attachments."] # [doc = " Default: \"📎\""] # [serde (default)] pub attachment_flag : Option < Option < String > > , # [doc = " Should threads with different Subjects show a list of those"] # [doc = " subjects on the entry title?"] # [doc = " Default: \"true\""] # [serde (default)] pub thread_subject_pack : Option < bool > , # [doc = " In threaded listing style, repeat identical From column values within a"] # [doc = " thread. Not repeating adds empty space in the From column which"] # [doc = " might result in less visual clutter."] # [doc = " Default: \"false\""] # [serde (default)] pub threaded_repeat_identical_from_values : Option < bool > , # [doc = " Show relative indices in menu mailboxes to quickly help with jumping to"] # [doc = " them. Default: \"true\""] # [serde (alias = "relative-menu-indices")] # [serde (default)] pub relative_menu_indices : Option < bool > , # [doc = " Show relative indices in listings to quickly help with jumping to"] # [doc = " them. Default: \"true\""] # [serde (alias = "relative-list-indices")] # [serde (default)] pub relative_list_indices : Option < bool > } impl Default for ListingSettingsOverride { fn default () -> Self { ListingSettingsOverride { context_lines : None , show_menu_scrollbar : None , datetime_fmt : None , recent_dates : None , filter : None , index_style : None , sidebar_mailbox_tree_has_sibling : None , sidebar_mailbox_tree_no_sibling : None , sidebar_mailbox_tree_has_sibling_leaf : None , sidebar_mailbox_tree_no_sibling_leaf : None , sidebar_divider : None , sidebar_ratio : None , unseen_flag : None , thread_snoozed_flag : None , selected_flag : None , attachment_flag : None , thread_subject_pack : None , threaded_repeat_identical_from_values : None , relative_menu_indices : None , relative_list_indices : None } } }
|
||||
|
||||
# [derive (Debug , Serialize , Deserialize , Clone)] # [serde (deny_unknown_fields)] pub struct NotificationsSettingsOverride { # [doc = " Enable notifications."] # [doc = " Default: True"] # [serde (default)] pub enable : Option < bool > , # [doc = " A command to pipe notifications through."] # [doc = " Default: None"] # [serde (default)] pub script : Option < Option < String > > , # [doc = " A command to pipe new mail notifications through (preferred over"] # [doc = " `script`). Default: None"] # [serde (default)] pub new_mail_script : Option < Option < String > > , # [doc = " A file location which has its size changed when new mail arrives (max"] # [doc = " 128 bytes). Can be used to trigger new mail notifications eg with"] # [doc = " `xbiff(1)`. Default: None"] # [serde (alias = "xbiff-file-path")] # [serde (default)] pub xbiff_file_path : Option < Option < String > > , # [serde (alias = "play-sound")] # [serde (default)] pub play_sound : Option < ToggleFlag > , # [serde (alias = "sound-file")] # [serde (default)] pub sound_file : Option < Option < String > > } impl Default for NotificationsSettingsOverride { fn default () -> Self { NotificationsSettingsOverride { enable : None , script : None , new_mail_script : None , xbiff_file_path : None , play_sound : None , sound_file : None } } }
|
||||
|
||||
|
|
Loading…
Reference in New Issue