mod.rs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. use std::collections::HashMap;
  2. use crate::errors::*;
  3. use crate::{view::monitor::Monitor, workspace::Workspace};
  4. use error::ErrorRenderer;
  5. use error_chain::bail;
  6. use insert::InsertRenderer;
  7. use linked_hash_map::LinkedHashMap;
  8. use normal::NormalRenderer;
  9. use smallvec::SmallVec;
  10. use strum::EnumIter;
  11. use workspace::{WorkspaceModeData, WorkspaceRender};
  12. use yaml_rust::Yaml;
  13. use super::handler::handle_map;
  14. use super::Application;
  15. pub mod error;
  16. mod insert;
  17. mod normal;
  18. pub mod workspace;
  19. pub enum ModeData {
  20. Normal,
  21. Error(Error),
  22. Exit,
  23. Insert,
  24. Workspace(WorkspaceModeData),
  25. // Other(OtherData)
  26. }
  27. #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, EnumIter)]
  28. pub enum ModeKey {
  29. Normal,
  30. Error,
  31. Exit,
  32. Insert,
  33. Workspace,
  34. }
  35. impl ModeKey {
  36. pub fn to_string(&self) -> Option<String> {
  37. match self {
  38. ModeKey::Normal => Some("normal".into()),
  39. ModeKey::Insert => Some("insert".into()),
  40. ModeKey::Workspace => Some("workspace".into()),
  41. _ => None,
  42. }
  43. }
  44. pub fn generate_handle_map(
  45. &self,
  46. mode_map: &mut HashMap<
  47. String,
  48. HashMap<String, SmallVec<[fn(&mut Application) -> Result<()>; 4]>>,
  49. >,
  50. extra: Option<&LinkedHashMap<Yaml, Yaml>>,
  51. default: &LinkedHashMap<Yaml, Yaml>,
  52. ) -> Result<()> {
  53. let handle_map = handle_map();
  54. let mut command_map =
  55. HashMap::<String, SmallVec<[fn(&mut Application) -> Result<()>; 4]>>::new();
  56. if let Some(mode) = self.to_string() {
  57. if let Some(yaml) = default.get(&Yaml::String(mode.clone())) {
  58. if let Some(keys) = yaml.as_hash() {
  59. self.parse_mode_keybindings(keys, &handle_map, &mut command_map)?;
  60. }
  61. }
  62. if let Some(extra) = extra {
  63. if let Some(yaml) = extra.get(&Yaml::String(mode.clone())) {
  64. if let Some(keys) = yaml.as_hash() {
  65. self.parse_mode_keybindings(keys, &handle_map, &mut command_map)?;
  66. }
  67. }
  68. }
  69. mode_map.insert(mode, command_map);
  70. }
  71. Ok(())
  72. }
  73. fn parse_mode_keybindings(
  74. &self,
  75. keybindings: &LinkedHashMap<Yaml, Yaml>,
  76. handle_map: &HashMap<&str, fn(&mut Application) -> Result<()>>,
  77. result: &mut HashMap<String, SmallVec<[fn(&mut Application) -> Result<()>; 4]>>,
  78. ) -> Result<()> {
  79. for (key, handle) in keybindings {
  80. if let Some(key) = key.as_str() {
  81. let mut closures = SmallVec::new();
  82. match handle {
  83. Yaml::String(command_key) => {
  84. closures.push(
  85. *handle_map
  86. .get(command_key.as_str())
  87. .ok_or_else(|| format!("command \"{command_key:?}\" not found"))?,
  88. );
  89. }
  90. Yaml::Array(commands) => {
  91. for command in commands {
  92. let command_key = command.as_str().ok_or_else(|| {
  93. format!(
  94. "Keymap command \"{:?}\" couldn't be parsed as a string",
  95. command
  96. )
  97. })?;
  98. closures.push(
  99. *handle_map.get(command_key).ok_or_else(|| {
  100. format!("command \"{command_key:?}\" not found")
  101. })?,
  102. );
  103. }
  104. }
  105. _ => {
  106. bail!(format!("conmand: \"{handle:?}\" couldn't be parsed"));
  107. }
  108. }
  109. result.insert(key.to_string(), closures);
  110. }
  111. }
  112. Ok(())
  113. }
  114. }
  115. pub trait ModeRenderer {
  116. fn render(workspace: &mut Workspace, monitor: &mut Monitor, mode: &mut ModeData) -> Result<()>;
  117. }
  118. pub struct ModeRouter;
  119. impl ModeRenderer for ModeRouter {
  120. fn render(workspace: &mut Workspace, monitor: &mut Monitor, mode: &mut ModeData) -> Result<()> {
  121. match mode {
  122. ModeData::Normal => NormalRenderer::render(workspace, monitor, mode),
  123. ModeData::Error(_) => ErrorRenderer::render(workspace, monitor, mode),
  124. ModeData::Insert => InsertRenderer::render(workspace, monitor, mode),
  125. ModeData::Workspace(_) => WorkspaceRender::render(workspace, monitor, mode),
  126. ModeData::Exit => todo!(),
  127. }
  128. }
  129. }