vvim.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. #ifndef VVIM_H
  2. #define VVIM_H
  3. #include <QObject>
  4. #include <QString>
  5. #include <QTextCursor>
  6. #include "vutils.h"
  7. class VEdit;
  8. class QKeyEvent;
  9. class VEditConfig;
  10. class QKeyEvent;
  11. enum class VimMode {
  12. Normal = 0,
  13. Insert,
  14. Visual,
  15. VisualLine,
  16. Replace,
  17. Invalid
  18. };
  19. class VVim : public QObject
  20. {
  21. Q_OBJECT
  22. public:
  23. explicit VVim(VEdit *p_editor);
  24. // Handle key press event.
  25. // Returns true if the event is consumed and need no more handling.
  26. bool handleKeyPressEvent(QKeyEvent *p_event);
  27. // Return current mode.
  28. VimMode getMode() const;
  29. // Set current mode.
  30. void setMode(VimMode p_mode);
  31. signals:
  32. // Emit when current mode has been changed.
  33. void modeChanged(VimMode p_mode);
  34. private slots:
  35. // When user use mouse to select texts in Normal mode, we should change to
  36. // Visual mode.
  37. void selectionToVisualMode(bool p_hasText);
  38. private:
  39. // Struct for a key press.
  40. struct Key
  41. {
  42. Key(int p_key, int p_modifiers = Qt::NoModifier)
  43. : m_key(p_key), m_modifiers(p_modifiers)
  44. {
  45. }
  46. int m_key;
  47. int m_modifiers;
  48. bool isDigit() const
  49. {
  50. return m_key >= Qt::Key_0
  51. && m_key <= Qt::Key_9
  52. && m_modifiers == Qt::NoModifier;
  53. }
  54. int toDigit() const
  55. {
  56. V_ASSERT(isDigit());
  57. return m_key - Qt::Key_0;
  58. }
  59. bool operator==(const Key &p_key) const
  60. {
  61. return p_key.m_key == m_key && p_key.m_modifiers == m_modifiers;
  62. }
  63. };
  64. // Supported actions.
  65. enum class Action
  66. {
  67. Move = 0,
  68. Delete,
  69. Copy,
  70. Paste,
  71. Change,
  72. Indent,
  73. UnIndent,
  74. ToUpper,
  75. ToLower,
  76. DeleteToClipboard,
  77. CopyToClipboard,
  78. PasteFromClipboard,
  79. ChangeToClipboard,
  80. Invalid
  81. };
  82. // Supported movements.
  83. enum class Movement
  84. {
  85. Left = 0,
  86. Right,
  87. Up,
  88. Down,
  89. VisualUp,
  90. VisualDown,
  91. PageUp,
  92. PageDown,
  93. HalfPageUp,
  94. HalfPageDown,
  95. StartOfLine,
  96. EndOfLine,
  97. FirstCharacter,
  98. LineJump,
  99. StartOfDocument,
  100. EndOfDocument,
  101. Invalid
  102. };
  103. // Supported ranges.
  104. enum class Range
  105. {
  106. Line = 0,
  107. Word,
  108. Invalid
  109. };
  110. enum class TokenType { Action = 0, Repeat, Movement, Range, Invalid };
  111. struct Token
  112. {
  113. Token(Action p_action)
  114. : m_type(TokenType::Action), m_action(p_action) {}
  115. Token(int p_repeat)
  116. : m_type(TokenType::Repeat), m_repeat(p_repeat) {}
  117. Token(Movement p_movement)
  118. : m_type(TokenType::Movement), m_movement(p_movement) {}
  119. Token(Range p_range)
  120. : m_type(TokenType::Range), m_range(p_range) {}
  121. Token() : m_type(TokenType::Invalid) {}
  122. bool isRepeat() const
  123. {
  124. return m_type == TokenType::Repeat;
  125. }
  126. bool isAction() const
  127. {
  128. return m_type == TokenType::Action;
  129. }
  130. bool isMovement() const
  131. {
  132. return m_type == TokenType::Movement;
  133. }
  134. bool isRange() const
  135. {
  136. return m_type == TokenType::Range;
  137. }
  138. QString toString() const
  139. {
  140. QString str;
  141. switch (m_type) {
  142. case TokenType::Action:
  143. str = QString("action %1").arg((int)m_action);
  144. break;
  145. case TokenType::Repeat:
  146. str = QString("repeat %1").arg(m_repeat);
  147. break;
  148. case TokenType::Movement:
  149. str = QString("movement %1").arg((int)m_movement);
  150. break;
  151. case TokenType::Range:
  152. str = QString("range %1").arg((int)m_range);
  153. break;
  154. default:
  155. str = "invalid";
  156. }
  157. return str;
  158. }
  159. TokenType m_type;
  160. union
  161. {
  162. Action m_action;
  163. int m_repeat;
  164. Movement m_movement;
  165. Range m_range;
  166. };
  167. };
  168. // Reset all key state info.
  169. void resetState();
  170. // Now m_tokens constitute a command. Execute it.
  171. // Will clear @p_tokens.
  172. void processCommand(QList<Token> &p_tokens);
  173. // Return the number represented by @p_keys.
  174. // Return -1 if @p_keys is not a valid digit sequence.
  175. int numberFromKeySequence(const QList<Key> &p_keys);
  176. // Try to generate a Repeat token from @p_keys and insert it to @p_tokens.
  177. // If succeed, clear @p_keys and return true.
  178. bool tryGetRepeatToken(QList<Key> &p_keys, QList<Token> &p_tokens);
  179. // @p_tokens is the arguments of the Action::Move action.
  180. void processMoveAction(QList<Token> &p_tokens);
  181. // Clear selection if there is any.
  182. // Returns true if there is selection.
  183. bool clearSelection();
  184. // Get the block count of one page step in vertical scroll bar.
  185. int blockCountOfPageStep() const;
  186. // Expand selection in the VisualLiine mode which will change the position
  187. // of @p_cursor.
  188. void expandSelectionInVisualLineMode(QTextCursor &p_cursor);
  189. VEdit *m_editor;
  190. const VEditConfig *m_editConfig;
  191. VimMode m_mode;
  192. QList<Key> m_keys;
  193. QList<Token> m_tokens;
  194. // Whether reset the position in block when moving cursor.
  195. bool m_resetPositionInBlock;
  196. };
  197. #endif // VVIM_H