themes/shortcuts: preserve order of keys

memfd
Manos Pitsidianakis 2020-08-17 15:53:59 +03:00
parent 8a6bf3b217
commit bb4754e38a
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
4 changed files with 32 additions and 37 deletions

View File

@ -46,15 +46,13 @@ pub mod svg;
use std::fmt;
use std::fmt::{Debug, Display};
use std::collections::HashMap;
use indexmap::IndexMap;
use uuid::Uuid;
use super::{Key, StatusEvent, UIEvent};
pub type ComponentId = Uuid;
pub type ShortcutMap = HashMap<&'static str, Key>;
pub type ShortcutMaps = HashMap<&'static str, ShortcutMap>;
pub type ShortcutMap = IndexMap<&'static str, Key>;
pub type ShortcutMaps = IndexMap<&'static str, ShortcutMap>;
/// Types implementing this Trait can draw on the terminal and receive events.
/// If a type wants to skip drawing if it has not changed anything, it can hold some flag in its

View File

@ -610,7 +610,7 @@ impl Component for Pager {
self.dirty = value;
}
fn get_shortcuts(&self, context: &Context) -> ShortcutMaps {
let config_map: HashMap<&'static str, Key> = context.settings.shortcuts.pager.key_values();
let config_map: IndexMap<&'static str, Key> = context.settings.shortcuts.pager.key_values();
let mut ret: ShortcutMaps = Default::default();
ret.insert(Pager::DESCRIPTION, config_map);
ret
@ -1438,9 +1438,7 @@ impl Component for Tabbed {
let mut max_width =
"Press ? to close, use COMMAND \"search\" to find shortcuts".len() + 3;
let mut shortcuts = children_maps.iter().collect::<Vec<_>>();
shortcuts.sort_by_key(|(k, _)| *k);
for (desc, shortcuts) in shortcuts.iter() {
for (desc, shortcuts) in children_maps.iter() {
max_length += shortcuts.len() + 3;
max_width = std::cmp::max(
max_width,
@ -1508,7 +1506,7 @@ impl Component for Tabbed {
);
}
let mut idx = 2;
for (desc, shortcuts) in shortcuts.iter() {
for (desc, shortcuts) in children_maps.iter() {
write_string_to_grid(
desc,
&mut self.help_content,
@ -1519,8 +1517,6 @@ impl Component for Tabbed {
None,
);
idx += 2;
let mut shortcuts = shortcuts.iter().collect::<Vec<_>>();
shortcuts.sort_unstable_by_key(|(ref k, _)| *k);
for (k, v) in shortcuts {
debug!(&(k, v));
let (x, y) = write_string_to_grid(

View File

@ -21,8 +21,8 @@
use super::DotAddressable;
use crate::terminal::Key;
use indexmap::IndexMap;
use melib::{MeliError, Result};
use std::collections::HashMap;
#[macro_export]
macro_rules! shortcut {
@ -121,7 +121,7 @@ macro_rules! shortcut_key_values {
}
}
/// Returns a hashmap of all shortcuts and their values
pub fn key_values(&self) -> HashMap<&'static str, Key> {
pub fn key_values(&self) -> IndexMap<&'static str, Key> {
[
$((stringify!($fname),(self.$fname).clone()),)*
].iter().cloned().collect()

View File

@ -30,11 +30,12 @@
use crate::terminal::{Attr, Color};
use crate::Context;
use indexmap::IndexMap;
use melib::{MeliError, Result};
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use smallvec::SmallVec;
use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
use std::collections::HashSet;
#[inline(always)]
pub fn value(context: &Context, key: &'static str) -> ThemeAttribute {
@ -486,16 +487,16 @@ impl<'de> Deserialize<'de> for ThemeValue<Color> {
pub struct Themes {
pub light: Theme,
pub dark: Theme,
pub other_themes: HashMap<String, Theme>,
pub other_themes: IndexMap<String, Theme>,
}
#[derive(Debug, Clone)]
pub struct Theme {
color_aliases: HashMap<Cow<'static, str>, ThemeValue<Color>>,
attr_aliases: HashMap<Cow<'static, str>, ThemeValue<Attr>>,
color_aliases: IndexMap<Cow<'static, str>, ThemeValue<Color>>,
attr_aliases: IndexMap<Cow<'static, str>, ThemeValue<Attr>>,
#[cfg(feature = "regexp")]
text_format_regexps: HashMap<Cow<'static, str>, SmallVec<[TextFormatterSetting; 32]>>,
pub keys: HashMap<Cow<'static, str>, ThemeAttributeInner>,
text_format_regexps: IndexMap<Cow<'static, str>, SmallVec<[TextFormatterSetting; 32]>>,
pub keys: IndexMap<Cow<'static, str>, ThemeAttributeInner>,
}
#[cfg(feature = "regexp")]
@ -734,14 +735,14 @@ mod regexp {
use std::ops::{Deref, DerefMut};
impl Deref for Theme {
type Target = HashMap<Cow<'static, str>, ThemeAttributeInner>;
type Target = IndexMap<Cow<'static, str>, ThemeAttributeInner>;
fn deref(&self) -> &Self::Target {
&self.keys
}
}
impl DerefMut for Theme {
fn deref_mut(&mut self) -> &mut HashMap<Cow<'static, str>, ThemeAttributeInner> {
fn deref_mut(&mut self) -> &mut IndexMap<Cow<'static, str>, ThemeAttributeInner> {
&mut self.keys
}
}
@ -766,19 +767,19 @@ impl<'de> Deserialize<'de> for Themes {
#[serde(default)]
dark: ThemeOptions,
#[serde(flatten, default)]
other_themes: HashMap<String, ThemeOptions>,
other_themes: IndexMap<String, ThemeOptions>,
}
#[derive(Deserialize, Default)]
struct ThemeOptions {
#[serde(default)]
color_aliases: HashMap<Cow<'static, str>, ThemeValue<Color>>,
color_aliases: IndexMap<Cow<'static, str>, ThemeValue<Color>>,
#[serde(default)]
attr_aliases: HashMap<Cow<'static, str>, ThemeValue<Attr>>,
attr_aliases: IndexMap<Cow<'static, str>, ThemeValue<Attr>>,
#[cfg(feature = "regexp")]
#[serde(default)]
text_format_regexps: HashMap<Cow<'static, str>, HashMap<String, RegexpOptions>>,
text_format_regexps: IndexMap<Cow<'static, str>, IndexMap<String, RegexpOptions>>,
#[serde(flatten, default)]
keys: HashMap<Cow<'static, str>, ThemeAttributeInnerOptions>,
keys: IndexMap<Cow<'static, str>, ThemeAttributeInnerOptions>,
}
#[cfg(feature = "regexp")]
#[derive(Deserialize, Default)]
@ -1284,9 +1285,9 @@ impl Themes {
impl Default for Themes {
fn default() -> Themes {
let mut light = HashMap::default();
let mut dark = HashMap::default();
let other_themes = HashMap::default();
let mut light = IndexMap::default();
let mut dark = IndexMap::default();
let other_themes = IndexMap::default();
macro_rules! add {
($key:literal, $($theme:ident={ $($name:ident : $val:expr),*$(,)? }),*$(,)?) => {
@ -1684,9 +1685,9 @@ impl Serialize for Themes {
where
S: Serializer,
{
let mut dark: HashMap<Cow<'static, str>, ThemeAttribute> = Default::default();
let mut light: HashMap<Cow<'static, str>, ThemeAttribute> = Default::default();
let mut other_themes: HashMap<String, _> = Default::default();
let mut dark: IndexMap<Cow<'static, str>, ThemeAttribute> = Default::default();
let mut light: IndexMap<Cow<'static, str>, ThemeAttribute> = Default::default();
let mut other_themes: IndexMap<String, _> = Default::default();
for k in self.dark.keys() {
dark.insert(
@ -1711,7 +1712,7 @@ impl Serialize for Themes {
}
for (name, t) in self.other_themes.iter() {
let mut new_map: HashMap<Cow<'static, str>, ThemeAttribute> = Default::default();
let mut new_map: IndexMap<Cow<'static, str>, ThemeAttribute> = Default::default();
for k in t.keys() {
new_map.insert(
@ -1746,8 +1747,8 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> {
fn is_cyclic_util<'a>(
course: Course,
k: &'a Cow<'static, str>,
visited: &mut HashMap<(&'a Cow<'static, str>, Course), bool>,
stack: &mut HashMap<(&'a Cow<'static, str>, Course), bool>,
visited: &mut IndexMap<(&'a Cow<'static, str>, Course), bool>,
stack: &mut IndexMap<(&'a Cow<'static, str>, Course), bool>,
path: &mut SmallVec<[(&'a Cow<'static, str>, Course); 16]>,
theme: &'a Theme,
) -> bool {
@ -1954,7 +1955,7 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> {
.keys()
.map(|k| ((k, Course::AttrAlias), false)),
)
.collect::<HashMap<(&Cow<'static, str>, Course), bool>>();
.collect::<IndexMap<(&Cow<'static, str>, Course), bool>>();
let mut stack = visited.clone();
for k in theme.keys() {