2021-01-02 11:59:55 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								/*
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 * Copyright (c) 2021, the SerenityOS developers.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 *
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								 * SPDX-License-Identifier: BSD-2-Clause
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-02 11:59:55 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 */
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#pragma once
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
											
												LibGUI: Implement Vim motion system
This patch implements Vim motions.  The VimMotion class will accept
keycodes from the editing engine to build up a motion, and will
signal when a motion is complete via VimMotion::is_complete().  The
editing engine can then call VimMotion::get_range() to obtain a
TextRange object which can be used to perform operations on the text,
or VimMotion::get_position() to obtain a TextPosition which is the
new position of the cursor after the motion.
Currently, the following motions are supported:
- h/j/k/l, regular Vim line and character movements
- 0/^/$, start/end of line and start of non-blank
- w/e/b/ge, word-related movements
- W/E/B/gE, WORD (anything non-blank) versions of the above motions
- gg/G, document related movements
- t/f, to/find character
All motions except gg/G accept a number prefix to repeat the motion that
many times.
This patch updates insert, normal and visual modes to use this motion
system for movement.
											
										 
										
											2021-04-18 02:32:42 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								#include <AK/Optional.h>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <LibCore/Object.h>
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-02 11:59:55 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <LibGUI/EditingEngine.h>
							 | 
						
					
						
							
								
									
										
										
											
												LibGUI: Implement Vim motion system
This patch implements Vim motions.  The VimMotion class will accept
keycodes from the editing engine to build up a motion, and will
signal when a motion is complete via VimMotion::is_complete().  The
editing engine can then call VimMotion::get_range() to obtain a
TextRange object which can be used to perform operations on the text,
or VimMotion::get_position() to obtain a TextPosition which is the
new position of the cursor after the motion.
Currently, the following motions are supported:
- h/j/k/l, regular Vim line and character movements
- 0/^/$, start/end of line and start of non-blank
- w/e/b/ge, word-related movements
- W/E/B/gE, WORD (anything non-blank) versions of the above motions
- gg/G, document related movements
- t/f, to/find character
All motions except gg/G accept a number prefix to repeat the motion that
many times.
This patch updates insert, normal and visual modes to use this motion
system for movement.
											
										 
										
											2021-04-18 02:32:42 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								#include <LibGUI/TextRange.h>
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-02 11:59:55 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								namespace GUI {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
											
												LibGUI: Implement Vim motion system
This patch implements Vim motions.  The VimMotion class will accept
keycodes from the editing engine to build up a motion, and will
signal when a motion is complete via VimMotion::is_complete().  The
editing engine can then call VimMotion::get_range() to obtain a
TextRange object which can be used to perform operations on the text,
or VimMotion::get_position() to obtain a TextPosition which is the
new position of the cursor after the motion.
Currently, the following motions are supported:
- h/j/k/l, regular Vim line and character movements
- 0/^/$, start/end of line and start of non-blank
- w/e/b/ge, word-related movements
- W/E/B/gE, WORD (anything non-blank) versions of the above motions
- gg/G, document related movements
- t/f, to/find character
All motions except gg/G accept a number prefix to repeat the motion that
many times.
This patch updates insert, normal and visual modes to use this motion
system for movement.
											
										 
										
											2021-04-18 02:32:42 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								// Wrapper over TextPosition that makes it easier to move it around as a cursor,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// and to get the current line or character.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class VimCursor {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								public:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    VimCursor(TextEditor& editor, TextPosition initial_position, bool forwards)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        : m_editor(editor)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        , m_position(initial_position)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        , m_forwards(forwards)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void move_forwards();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void move_backwards();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    // Move a single character in the current direction.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void move();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    // Move a single character in reverse.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void move_reverse();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    // Peek a single character in the current direction.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    u32 peek();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    // Peek a single character in reverse.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    u32 peek_reverse();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    // Get the character the cursor is currently on.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    u32 current_char();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    // Get the line the cursor is currently on.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    TextDocumentLine& current_line();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    // Get the current position.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    TextPosition& current_position() { return m_position; }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    // Did we hit the edge of the document?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool hit_edge() { return m_hit_edge; }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    // Will the next move cross a line boundary?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool will_cross_line_boundary();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    // Did we cross a line boundary?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool crossed_line_boundary() { return m_crossed_line_boundary; }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    // Are we on an empty line?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool on_empty_line();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    // Are we going forwards?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool forwards() { return m_forwards; }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								private:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    TextEditor& m_editor;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    TextPosition m_position;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool m_forwards;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    u32 m_cached_char { 0 };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool m_hit_edge { false };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool m_crossed_line_boundary { false };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class VimMotion {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								public:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    enum class Unit {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        // The motion isn't complete yet, or was invalid.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Unknown,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        // Document. Anything non-negative is counted as G while anything else is gg.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Document,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        // Lines.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Line,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        // A sequence of letters, digits and underscores, or a sequence of other
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        // non-blank characters separated by whitespace.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Word,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        // A sequence of non-blank characters separated by whitespace.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        // This is how Vim separates w from W.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        WORD,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        // End of a word. This is basically the same as a word but it doesn't
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        // trim the spaces at the end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        EndOfWord,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        // End of a WORD.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        EndOfWORD,
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-01 10:01:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        // Characters (or Unicode code points based on how pedantic you want to
							 | 
						
					
						
							
								
									
										
										
											
												LibGUI: Implement Vim motion system
This patch implements Vim motions.  The VimMotion class will accept
keycodes from the editing engine to build up a motion, and will
signal when a motion is complete via VimMotion::is_complete().  The
editing engine can then call VimMotion::get_range() to obtain a
TextRange object which can be used to perform operations on the text,
or VimMotion::get_position() to obtain a TextPosition which is the
new position of the cursor after the motion.
Currently, the following motions are supported:
- h/j/k/l, regular Vim line and character movements
- 0/^/$, start/end of line and start of non-blank
- w/e/b/ge, word-related movements
- W/E/B/gE, WORD (anything non-blank) versions of the above motions
- gg/G, document related movements
- t/f, to/find character
All motions except gg/G accept a number prefix to repeat the motion that
many times.
This patch updates insert, normal and visual modes to use this motion
system for movement.
											
										 
										
											2021-04-18 02:32:42 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        // get).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Character,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        // Used for find-mode.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Find
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    enum class FindMode {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        /// Find mode is not enabled.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        None,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        /// Finding until the given character.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        To,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        /// Finding through the given character.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Find
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void add_key_code(KeyCode key, bool ctrl, bool shift, bool alt);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Optional<TextRange> get_range(class VimEditingEngine& engine, bool normalize_for_position = false);
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-11 19:15:21 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Optional<TextRange> get_repeat_range(class VimEditingEngine& engine, Unit, bool normalize_for_position = false);
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-26 23:37:56 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Optional<TextPosition> get_position(VimEditingEngine& engine, bool in_visual_mode = false);
							 | 
						
					
						
							
								
									
										
										
											
												LibGUI: Implement Vim motion system
This patch implements Vim motions.  The VimMotion class will accept
keycodes from the editing engine to build up a motion, and will
signal when a motion is complete via VimMotion::is_complete().  The
editing engine can then call VimMotion::get_range() to obtain a
TextRange object which can be used to perform operations on the text,
or VimMotion::get_position() to obtain a TextPosition which is the
new position of the cursor after the motion.
Currently, the following motions are supported:
- h/j/k/l, regular Vim line and character movements
- 0/^/$, start/end of line and start of non-blank
- w/e/b/ge, word-related movements
- W/E/B/gE, WORD (anything non-blank) versions of the above motions
- gg/G, document related movements
- t/f, to/find character
All motions except gg/G accept a number prefix to repeat the motion that
many times.
This patch updates insert, normal and visual modes to use this motion
system for movement.
											
										 
										
											2021-04-18 02:32:42 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    void reset();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    /// Returns whether the motion should consume the next character no matter what.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    /// Used for f and t motions.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool should_consume_next_character() { return m_should_consume_next_character; }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool is_complete() { return m_is_complete; }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool is_cancelled() { return m_is_complete && m_unit == Unit::Unknown; }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Unit unit() { return m_unit; }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    int amount() { return m_amount; }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    // FIXME: come up with a better way to signal start/end of line than sentinels?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    static constexpr int START_OF_LINE = NumericLimits<int>::min();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    static constexpr int START_OF_NON_WHITESPACE = NumericLimits<int>::min() + 1;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    static constexpr int END_OF_LINE = NumericLimits<int>::max();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								private:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void calculate_document_range(TextEditor&);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void calculate_line_range(TextEditor&, bool normalize_for_position);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void calculate_word_range(VimCursor&, int amount, bool normalize_for_position);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void calculate_WORD_range(VimCursor&, int amount, bool normalize_for_position);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void calculate_character_range(VimCursor&, int amount, bool normalize_for_position);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void calculate_find_range(VimCursor&, int amount);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Unit m_unit { Unit::Unknown };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    int m_amount { 0 };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool m_is_complete { false };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool m_guirky_mode { false };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool m_should_consume_next_character { false };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    FindMode m_find_mode { FindMode::None };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    u32 m_next_character { 0 };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    size_t m_start_line { 0 };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    size_t m_start_column { 0 };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    size_t m_end_line { 0 };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    size_t m_end_column { 0 };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-02 11:59:55 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class VimEditingEngine final : public EditingEngine {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								public:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    virtual CursorWidth cursor_width() const override;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-01 20:58:27 +03:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    virtual bool on_key(KeyEvent const& event) override;
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-02 11:59:55 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-02-02 19:01:54 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								private:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    enum VimMode {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Normal,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Insert,
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-25 15:27:49 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        Visual,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        VisualLine
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-02 11:59:55 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-25 23:24:33 +10:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    enum YankType {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Line,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Selection
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-18 11:33:33 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    enum class Casing {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Uppercase,
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-18 22:34:23 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        Lowercase,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Invertcase
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-18 11:33:33 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-02 11:59:55 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    VimMode m_vim_mode { VimMode::Normal };
							 | 
						
					
						
							
								
									
										
										
											
												LibGUI: Implement Vim motion system
This patch implements Vim motions.  The VimMotion class will accept
keycodes from the editing engine to build up a motion, and will
signal when a motion is complete via VimMotion::is_complete().  The
editing engine can then call VimMotion::get_range() to obtain a
TextRange object which can be used to perform operations on the text,
or VimMotion::get_position() to obtain a TextPosition which is the
new position of the cursor after the motion.
Currently, the following motions are supported:
- h/j/k/l, regular Vim line and character movements
- 0/^/$, start/end of line and start of non-blank
- w/e/b/ge, word-related movements
- W/E/B/gE, WORD (anything non-blank) versions of the above motions
- gg/G, document related movements
- t/f, to/find character
All motions except gg/G accept a number prefix to repeat the motion that
many times.
This patch updates insert, normal and visual modes to use this motion
system for movement.
											
										 
										
											2021-04-18 02:32:42 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    VimMotion m_motion;
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-02 11:59:55 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-25 23:24:33 +10:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    YankType m_yank_type {};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    String m_yank_buffer {};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void yank(YankType);
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-11 19:15:21 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    void yank(TextRange, YankType yank_type);
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-10 22:24:03 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    void put_before();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void put_after();
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-25 23:24:33 +10:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-26 23:37:56 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    TextPosition m_selection_start_position = {};
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-18 20:39:41 +10:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    void update_selection_on_cursor_move();
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-26 23:37:56 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    void clamp_cursor_position();
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-18 20:39:41 +10:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    void clear_visual_mode_data();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-02-02 19:01:54 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    KeyCode m_previous_key {};
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-02 11:59:55 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void switch_to_normal_mode();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void switch_to_insert_mode();
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-18 20:39:41 +10:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    void switch_to_visual_mode();
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-25 15:27:49 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    void switch_to_visual_line_mode();
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-26 20:29:05 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    void move_half_page_up();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void move_half_page_down();
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-11 22:22:27 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    void move_to_previous_empty_lines_block();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void move_to_next_empty_lines_block();
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-02 11:59:55 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-01 20:58:27 +03:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    bool on_key_in_insert_mode(KeyEvent const& event);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool on_key_in_normal_mode(KeyEvent const& event);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool on_key_in_visual_mode(KeyEvent const& event);
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-25 15:27:49 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    bool on_key_in_visual_line_mode(KeyEvent const& event);
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-08 16:26:20 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-18 11:33:33 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    void casefold_selection(Casing);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-08 16:26:20 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    virtual EngineType engine_type() const override { return EngineType::Vim; }
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-02 11:59:55 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								}
							 |