components: fix shortcut section order
Tests / Test on ${{ matrix.build }} (linux-amd64, ubuntu-latest, stable, x86_64-unknown-linux-gnu) (push) Successful in 8m2s Details

Shortcut sections are shown in order, sorted by focus--as if widgets are
stacked vertically by the order you've opened them. In some widgets that
order was wrong.

Also, when a parent widget retrieved its child shortcuts, sometimes it
overwrote children sections if they both have them. This commit adds a
sealed trait ExtendShortcutsMaps that instead of overriding them, it
merges them with the child map having the priority.

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
pull/284/head
Manos Pitsidianakis 2023-08-21 14:53:29 +03:00
parent f193bdf685
commit 96f0b3e6b4
Signed by: Manos Pitsidianakis
GPG Key ID: 7729C7707F7E09D0
4 changed files with 74 additions and 33 deletions

View File

@ -75,6 +75,29 @@ impl std::fmt::UpperHex for ComponentId {
pub type ShortcutMap = IndexMap<&'static str, Key>;
pub type ShortcutMaps = IndexMap<&'static str, ShortcutMap>;
mod private {
pub trait Sealed {}
}
impl private::Sealed for ShortcutMaps {}
pub trait ExtendShortcutsMaps: private::Sealed {
fn extend_shortcuts(&mut self, other: Self);
}
impl ExtendShortcutsMaps for ShortcutMaps {
fn extend_shortcuts(&mut self, mut other: Self) {
other.retain(|k, v| {
if let Some(m) = self.get_mut(k) {
m.extend(v.iter().map(|(k, v)| (*k, v.clone())));
false
} else {
true
}
});
self.extend(other.into_iter());
}
}
#[derive(Debug, Clone, Copy)]
pub enum PageMovement {
Up(usize),

View File

@ -29,7 +29,9 @@ use melib::{backends::EnvelopeHashBatch, Address};
use smallvec::SmallVec;
use super::*;
use crate::{conf::accounts::JobRequest, types::segment_tree::SegmentTree};
use crate::{
components::ExtendShortcutsMaps, conf::accounts::JobRequest, types::segment_tree::SegmentTree,
};
// [ref:TODO]: emoji_text_presentation_selector should be printed along with the chars
// before it but not as a separate Cell
@ -2152,17 +2154,18 @@ impl Component for Listing {
}
fn shortcuts(&self, context: &Context) -> ShortcutMaps {
let mut map = if let Some(s) = self.status.as_ref() {
let mut map = ShortcutMaps::default();
if self.focus != ListingFocus::Menu && self.component.unfocused() {
map.extend_shortcuts(self.view.shortcuts(context));
}
map.extend_shortcuts(if let Some(s) = self.status.as_ref() {
s.shortcuts(context)
} else {
self.component.shortcuts(context)
};
});
let mut config_map = context.settings.shortcuts.listing.key_values();
if self.focus != ListingFocus::Menu {
config_map.remove("open_mailbox");
if self.component.unfocused() {
map.extend(self.view.shortcuts(context).into_iter());
}
}
map.insert(Shortcuts::LISTING, config_map);

View File

@ -48,7 +48,7 @@ use std::collections::HashSet;
use indexmap::IndexMap;
pub use self::tables::*;
use crate::{jobs::JobId, melib::text_processing::TextProcessing};
use crate::{components::ExtendShortcutsMaps, jobs::JobId, melib::text_processing::TextProcessing};
#[derive(Default, Debug, Clone)]
pub struct SearchPattern {
@ -854,8 +854,7 @@ impl Tabbed {
dirty: true,
id: ComponentId::default(),
};
ret.help_curr_views
.extend(ret.shortcuts(context).into_iter());
ret.help_curr_views.extend_shortcuts(ret.shortcuts(context));
ret
}
@ -937,6 +936,18 @@ impl Tabbed {
new.realize(self.id().into(), context);
self.children.push(new);
}
fn update_help_curr_views(&mut self, context: &Context) {
let mut children_maps = self.children[self.cursor_pos].shortcuts(context);
children_maps.extend_shortcuts(self.shortcuts(context));
if let Some(i) = children_maps
.get_index_of(Shortcuts::GENERAL)
.filter(|i| i + 1 != children_maps.len())
{
children_maps.move_index(i, children_maps.len().saturating_sub(1));
}
self.help_curr_views = children_maps;
}
}
impl std::fmt::Display for Tabbed {
@ -990,11 +1001,16 @@ impl Component for Tabbed {
if (self.show_shortcuts && self.dirty) || must_redraw_shortcuts {
let mut children_maps = self.children[self.cursor_pos].shortcuts(context);
let our_map = self.shortcuts(context);
children_maps.extend(our_map.into_iter());
children_maps.extend_shortcuts(self.shortcuts(context));
if children_maps.is_empty() {
return;
}
if let Some(i) = children_maps
.get_index_of(Shortcuts::GENERAL)
.filter(|i| i + 1 != children_maps.len())
{
children_maps.move_index(i, children_maps.len().saturating_sub(1));
}
if (children_maps == self.help_curr_views) && must_redraw_shortcuts {
let dialog_area = align_area(
area,
@ -1021,7 +1037,10 @@ impl Component for Tabbed {
None,
);
write_string_to_grid(
"Press ? to close",
&format!(
"Press {} to close",
children_maps[Shortcuts::GENERAL]["toggle_help"]
),
grid,
self.theme_default.fg,
self.theme_default.bg,
@ -1097,7 +1116,7 @@ impl Component for Tabbed {
}
let mut max_length = 6;
let mut max_width =
"Press ? to close, use COMMAND \"search\" to find shortcuts".len() + 3;
"Press XXXX to close, use COMMAND \"search\" to find shortcuts".len() + 3;
let mut max_first_column_width = 3;
@ -1200,7 +1219,10 @@ impl Component for Tabbed {
None,
);
write_string_to_grid(
"Press ? to close",
&format!(
"Press {} to close",
self.help_curr_views[Shortcuts::GENERAL]["toggle_help"]
),
grid,
self.theme_default.fg,
self.theme_default.bg,
@ -1363,9 +1385,7 @@ impl Component for Tabbed {
self.children[self.cursor_pos]
.process_event(&mut UIEvent::VisibilityChange(false), context);
self.cursor_pos = no % self.children.len();
let mut children_maps = self.children[self.cursor_pos].shortcuts(context);
children_maps.extend(self.shortcuts(context));
self.help_curr_views = children_maps;
self.update_help_curr_views(context);
context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::UpdateStatus(
@ -1381,9 +1401,7 @@ impl Component for Tabbed {
self.children[self.cursor_pos]
.process_event(&mut UIEvent::VisibilityChange(false), context);
self.cursor_pos = (self.cursor_pos + 1) % self.children.len();
let mut children_maps = self.children[self.cursor_pos].shortcuts(context);
children_maps.extend(self.shortcuts(context));
self.help_curr_views = children_maps;
self.update_help_curr_views(context);
context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::UpdateStatus(
@ -1414,9 +1432,7 @@ impl Component for Tabbed {
.process_event(&mut UIEvent::VisibilityChange(false), context);
self.cursor_pos = self.children.len() - 1;
self.children[self.cursor_pos].set_dirty(true);
let mut children_maps = self.children[self.cursor_pos].shortcuts(context);
children_maps.extend(self.shortcuts(context));
self.help_curr_views = children_maps;
self.update_help_curr_views(context);
return true;
}
UIEvent::Action(Tab(Close)) => {
@ -1425,9 +1441,7 @@ impl Component for Tabbed {
}
let id = self.children[self.cursor_pos].id();
self.children[self.cursor_pos].kill(id, context);
let mut children_maps = self.children[self.cursor_pos].shortcuts(context);
children_maps.extend(self.shortcuts(context));
self.help_curr_views = children_maps;
self.update_help_curr_views(context);
self.set_dirty(true);
return true;
}
@ -1442,9 +1456,7 @@ impl Component for Tabbed {
self.children.remove(c_idx);
self.cursor_pos = 0;
self.set_dirty(true);
let mut children_maps = self.children[self.cursor_pos].shortcuts(context);
children_maps.extend(self.shortcuts(context));
self.help_curr_views = children_maps;
self.update_help_curr_views(context);
return true;
} else {
log::debug!(

View File

@ -20,8 +20,11 @@
*/
use super::*;
use crate::terminal::cells::boundaries::{
HORZ_BOUNDARY, VERT_BOUNDARY, _LIGHT_DOWN_AND_HORIZONTAL, _LIGHT_UP_AND_HORIZONTAL,
use crate::{
components::ExtendShortcutsMaps,
terminal::cells::boundaries::{
HORZ_BOUNDARY, VERT_BOUNDARY, _LIGHT_DOWN_AND_HORIZONTAL, _LIGHT_UP_AND_HORIZONTAL,
},
};
/// A horizontally split in half container.
@ -106,7 +109,7 @@ impl Component for HSplit {
fn shortcuts(&self, context: &Context) -> ShortcutMaps {
let mut top_map = self.top.shortcuts(context);
top_map.extend(self.bottom.shortcuts(context).into_iter());
top_map.extend_shortcuts(self.bottom.shortcuts(context));
top_map
}
@ -243,7 +246,7 @@ impl Component for VSplit {
fn shortcuts(&self, context: &Context) -> ShortcutMaps {
let mut right_map = self.right.shortcuts(context);
right_map.extend(self.left.shortcuts(context).into_iter());
right_map.extend_shortcuts(self.left.shortcuts(context));
right_map
}