mod.rs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. use std::{collections::HashMap, ffi::OsStr, fs::read_to_string, path::PathBuf};
  2. use crate::{
  3. application::{
  4. mode::{ModeData, ModeKey},
  5. Application,
  6. },
  7. errors::*,
  8. };
  9. use crossterm::event::{Event, KeyEvent, KeyEventKind, KeyModifiers};
  10. use linked_hash_map::LinkedHashMap;
  11. use smallvec::SmallVec;
  12. use strum::IntoEnumIterator;
  13. use yaml_rust::{Yaml, YamlLoader};
  14. const INPUT_CONFIG_NAME: &str = "input.yaml";
  15. pub struct InputLoader;
  16. impl InputLoader {
  17. pub fn load(
  18. path: PathBuf,
  19. ) -> Result<HashMap<String, HashMap<String, SmallVec<[fn(&mut Application) -> Result<()>; 4]>>>>
  20. {
  21. #[cfg(not(feature = "dragonos"))]
  22. let data = Self::load_user(path)?;
  23. #[cfg(feature = "dragonos")]
  24. let data = None;
  25. let default = Self::load_default()?;
  26. let handle_map = Self::generate_handle_map(
  27. data,
  28. default
  29. .as_hash()
  30. .ok_or_else(|| "default input config didn't return a hash of key bindings")?,
  31. )?;
  32. Ok(handle_map)
  33. }
  34. fn generate_handle_map(
  35. extra_data: Option<LinkedHashMap<Yaml, Yaml>>,
  36. default: &LinkedHashMap<Yaml, Yaml>,
  37. ) -> Result<HashMap<String, HashMap<String, SmallVec<[fn(&mut Application) -> Result<()>; 4]>>>>
  38. {
  39. let mut handle_map = HashMap::new();
  40. for mode_key in ModeKey::iter() {
  41. mode_key.generate_handle_map(&mut handle_map, extra_data.as_ref(), default)?;
  42. }
  43. Ok(handle_map)
  44. }
  45. fn load_user(path: PathBuf) -> Result<Option<LinkedHashMap<Yaml, Yaml>>> {
  46. let readdir = path.read_dir()?;
  47. let mut entries = readdir
  48. .filter_map(|f| f.ok())
  49. .map(|f| f.path())
  50. .filter(|f| f.is_file())
  51. .filter(|f| {
  52. f.file_name().is_some() && f.file_name().unwrap() == OsStr::new(INPUT_CONFIG_NAME)
  53. });
  54. let entry = entries.next();
  55. if let Some(entry) = entry {
  56. let yaml = YamlLoader::load_from_str(&read_to_string(entry.clone())?)
  57. .chain_err(|| format!("Couldn't parse input config file: {:?}", entry))?
  58. .into_iter()
  59. .next()
  60. .chain_err(|| "No input document found")?;
  61. let yaml_hash = yaml
  62. .as_hash()
  63. .ok_or_else(|| "extra input config didn't return a hash of key bindings")?;
  64. return Ok(Some(yaml_hash.clone()));
  65. }
  66. Ok(None)
  67. }
  68. fn load_default() -> Result<Yaml> {
  69. YamlLoader::load_from_str(include_str!("default.yaml"))
  70. .chain_err(|| "Couldn't parse default input config file")?
  71. .into_iter()
  72. .next()
  73. .chain_err(|| "No default input document found")
  74. }
  75. }
  76. pub struct InputMapper;
  77. impl InputMapper {
  78. pub fn event_map_str(event: Event) -> Option<String> {
  79. match event {
  80. Event::FocusGained => None,
  81. Event::FocusLost => None,
  82. Event::Key(key_event) => {
  83. return Some(Self::key_event_map_str(key_event));
  84. }
  85. Event::Mouse(_) => None,
  86. Event::Paste(_) => None,
  87. Event::Resize(_, _) => None,
  88. }
  89. }
  90. fn key_event_map_str(event: KeyEvent) -> String {
  91. if let KeyEventKind::Press = event.kind {
  92. let mut modifier = String::new();
  93. if event.modifiers.contains(KeyModifiers::CONTROL) {
  94. modifier.push_str("ctrl-");
  95. }
  96. if event.modifiers.contains(KeyModifiers::ALT) {
  97. modifier.push_str("alt-");
  98. }
  99. if event.modifiers.contains(KeyModifiers::SHIFT) {
  100. modifier.push_str("shift-");
  101. }
  102. let keycode_str = match event.code {
  103. crossterm::event::KeyCode::Backspace => "backspace".into(),
  104. crossterm::event::KeyCode::Enter => "enter".into(),
  105. crossterm::event::KeyCode::Left => "left".into(),
  106. crossterm::event::KeyCode::Right => "right".into(),
  107. crossterm::event::KeyCode::Up => "up".into(),
  108. crossterm::event::KeyCode::Down => "down".into(),
  109. crossterm::event::KeyCode::Home => "home".into(),
  110. crossterm::event::KeyCode::End => "end".into(),
  111. crossterm::event::KeyCode::PageUp => "pageup".into(),
  112. crossterm::event::KeyCode::PageDown => "pagedown".into(),
  113. crossterm::event::KeyCode::Tab => "tab".into(),
  114. crossterm::event::KeyCode::BackTab => "backtab".into(),
  115. crossterm::event::KeyCode::Delete => "delete".into(),
  116. crossterm::event::KeyCode::Insert => "insert".into(),
  117. crossterm::event::KeyCode::F(f) => format!("f{f}"),
  118. crossterm::event::KeyCode::Char(c) => c.into(),
  119. crossterm::event::KeyCode::Null => "".into(),
  120. crossterm::event::KeyCode::Esc => "escape".into(),
  121. crossterm::event::KeyCode::CapsLock => "caps_lock".into(),
  122. crossterm::event::KeyCode::ScrollLock => "scroll_lock".into(),
  123. crossterm::event::KeyCode::NumLock => "num_lock".into(),
  124. crossterm::event::KeyCode::PrintScreen => "print_screen".into(),
  125. crossterm::event::KeyCode::Pause => "pause".into(),
  126. crossterm::event::KeyCode::Menu => "menu".into(),
  127. crossterm::event::KeyCode::KeypadBegin => "keypad_begin".into(),
  128. crossterm::event::KeyCode::Media(_) => "".into(),
  129. crossterm::event::KeyCode::Modifier(modifier_key_code) => match modifier_key_code {
  130. crossterm::event::ModifierKeyCode::LeftShift
  131. | crossterm::event::ModifierKeyCode::IsoLevel3Shift
  132. | crossterm::event::ModifierKeyCode::IsoLevel5Shift
  133. | crossterm::event::ModifierKeyCode::RightShift => "shift".into(),
  134. crossterm::event::ModifierKeyCode::LeftControl
  135. | crossterm::event::ModifierKeyCode::RightControl => "ctrl".into(),
  136. crossterm::event::ModifierKeyCode::LeftAlt
  137. | crossterm::event::ModifierKeyCode::RightAlt => "alt".into(),
  138. crossterm::event::ModifierKeyCode::RightSuper
  139. | crossterm::event::ModifierKeyCode::LeftSuper => "super".into(),
  140. crossterm::event::ModifierKeyCode::RightHyper
  141. | crossterm::event::ModifierKeyCode::LeftHyper => "hyper".into(),
  142. crossterm::event::ModifierKeyCode::RightMeta
  143. | crossterm::event::ModifierKeyCode::LeftMeta => "meta".into(),
  144. },
  145. };
  146. format!("{}{}", modifier, keycode_str)
  147. } else {
  148. "".into()
  149. }
  150. }
  151. }