Class: Canopus::Vim
- Inherits:
-
Object
- Object
- Canopus::Vim
- Includes:
- Commandable, Motionable, OperatorCapable, TextObjectSelectable
- Defined in:
- lib/canopus/vim.rb,
sig/vim.rbs
Defined Under Namespace
Modules: Commandable, Motionable, OperatorCapable, TextObjectSelectable
Constant Summary collapse
- OPERATORS =
%w[d c y > < = gu gU g~].freeze
- VISUAL_MODES =
%i[visual visual_line visual_block].freeze
Instance Attribute Summary collapse
-
#command_line ⇒ String?
readonly
Returns the value of attribute command_line.
-
#macros ⇒ Hash[String, Array[String]]
readonly
Returns the value of attribute macros.
-
#marks ⇒ Hash[String, Buffer::Anchor]
readonly
Returns the value of attribute marks.
-
#mode ⇒ mode
readonly
Returns the value of attribute mode.
-
#on_command ⇒ ^(String) -> void?
Returns the value of attribute on_command.
-
#registers ⇒ Hash[String, register]
readonly
Returns the value of attribute registers.
-
#status ⇒ String
readonly
Returns the value of attribute status.
Instance Method Summary collapse
-
#cursor_position ⇒ Integer
Zero-based UTF-8 byte offset of the active edge, including visual mode.
-
#deactivate ⇒ self
On blur: finish insert history and return to Normal, preserving registers.
-
#dispose ⇒ void
On close: finish history and release every owned buffer anchor.
-
#feed(key) ⇒ void
Input is a single grapheme or a normalized key such as "esc" or "ctrl-v".
-
#initialize(editor) ⇒ Vim
constructor
A new instance of Vim.
Constructor Details
#initialize(editor) ⇒ Vim
Returns a new instance of Vim.
10 11 12 13 14 15 |
# File 'lib/canopus/vim.rb', line 10 def initialize(editor) @editor, @mode = editor, :normal @registers, @marks, @macros = {}, {}, {} @count, @command, @last_change = +"", [], [] @register, @status, @play_depth = '"', "NORMAL", 0 end |
Instance Attribute Details
#command_line ⇒ String? (readonly)
Returns the value of attribute command_line.
7 8 9 |
# File 'lib/canopus/vim.rb', line 7 def command_line @command_line end |
#macros ⇒ Hash[String, Array[String]] (readonly)
Returns the value of attribute macros.
7 8 9 |
# File 'lib/canopus/vim.rb', line 7 def macros @macros end |
#marks ⇒ Hash[String, Buffer::Anchor] (readonly)
Returns the value of attribute marks.
7 8 9 |
# File 'lib/canopus/vim.rb', line 7 def marks @marks end |
#mode ⇒ mode (readonly)
Returns the value of attribute mode.
7 8 9 |
# File 'lib/canopus/vim.rb', line 7 def mode @mode end |
#on_command ⇒ ^(String) -> void?
Returns the value of attribute on_command.
8 9 10 |
# File 'lib/canopus/vim.rb', line 8 def on_command @on_command end |
#registers ⇒ Hash[String, register] (readonly)
Returns the value of attribute registers.
7 8 9 |
# File 'lib/canopus/vim.rb', line 7 def registers @registers end |
#status ⇒ String (readonly)
Returns the value of attribute status.
7 8 9 |
# File 'lib/canopus/vim.rb', line 7 def status @status end |
Instance Method Details
#cursor_position ⇒ Integer
Zero-based UTF-8 byte offset of the active edge, including visual mode.
21 |
# File 'sig/vim.rbs', line 21 def cursor_position = visual? ? @visual_head : @editor.primary.head |
#deactivate ⇒ self
On blur: finish insert history and return to Normal, preserving registers.
21 22 23 24 25 26 |
# File 'lib/canopus/vim.rb', line 21 def deactivate %i[insert replace].include?(@mode) ? insert_key("esc") : escape @command_line = nil @status = "NORMAL" self end |
#dispose ⇒ void
This method returns an undefined value.
On close: finish history and release every owned buffer anchor.
25 26 27 28 29 30 |
# File 'sig/vim.rbs', line 25 def dispose end_group (@marks.values + [@block_insert_start]).compact.uniq.each { |anchor| @editor.buffer.release_anchor(anchor) } @marks.clear @block_insert_start = nil end |
#feed(key) ⇒ void
This method returns an undefined value.
Input is a single grapheme or a normalized key such as "esc" or "ctrl-v".
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'sig/vim.rbs', line 19 def feed(key) @message = nil key = "esc" if key == "\e" key = "enter" if ["\r", "\n"].include?(key) @macros[@recording] << key if @recording && !(key == "q" && @mode == :normal && !@prefix) return command_key(key) if @command_line return insert_key(key) if %i[insert replace].include?(@mode) @visual_keys << key if visual? && @visual_keys @command << key return escape if %w[esc ctrl-c].include?(key) return prefix_key(key) if @prefix if key.match?(/\A\d\z/) && (key != "0" || !@count.empty?) @count << key return end explicit = !@count.empty? count = explicit ? @count.to_i.clamp(1, 10_000) : 1 @count.clear return operate_key(key, count, explicit) if @operator if visual? && (%w[d c y > < = x s D C Y].include?(key)) return operate_visual({"x" => "d", "s" => "c", "D" => "d", "C" => "c", "Y" => "y"}.fetch(key, key), count: count) end if visual? && %w[i a].include?(key) @prefix, @prefix_count = key, count return end case key when "i", "a", "I", "A", "o", "O", "R" enter_insert(key, count) when "v", "V", "ctrl-v" requested = {"v" => :visual, "V" => :visual_line, "ctrl-v" => :visual_block}.fetch(key) if @mode == requested escape else @visual_anchor = @visual_head = cursor_position unless visual? @mode = requested @visual_keys = @command.dup update_visual @command.clear end when "d", "c", "y", ">", "<", "=" @operator, @operator_count, @operator_explicit = key, count, explicit when "g", "f", "F", "t", "T", "m", "'", "`", '"', "@", "r" @prefix, @prefix_count, @prefix_explicit = key, count, explicit when "q" if @recording save_macro_register(@recording) @recording = nil @command.clear else @prefix = "q" end when "x", "X", "s" first = cursor_position endpoint = horizontal(first, key == "X" ? -count : count, insertion: true) operate(key == "s" ? "c" : "d", [first, endpoint].min...[first, endpoint].max) when "D", "C", "Y", "S" if %w[Y S].include?(key) operate(key == "Y" ? "y" : "c", line_range(count), linewise: true) else ending = line_end([row_at(cursor_position) + count - 1, last_row].min) operate(key == "D" ? "d" : "c", cursor_position...ending) end when "p", "P" then paste(key == "p", count) when "u", "ctrl-r" groups = @macro_groups || 0 groups.times { @editor.buffer.end_undo_group } begin count.times { key == "u" ? @editor.undo : @editor.redo } ensure groups.times { @editor.buffer.begin_undo_group } end @editor.select(normal_offset(@editor.primary.head)) @command.clear when "." change = @last_change.dup @command.clear count.times { replay(change) } when "J" then join_lines(count) when "~" if visual? operate_visual("g~") else first = cursor_position ending = horizontal(first, count, insertion: true) operate("g~", first...ending, destination: normal_offset(ending)) end when ":", "/", "?" @command_line, @command_type = +"", key @command_line = +"'<,'>" if key == ":" && visual? when "n", "N" search_next(reverse: key == "N", count: count) @command.clear when "*", "#" range = text_object("w", inner: true, count: 1) if range @search = "\\b#{Regexp.escape(@editor.buffer.rope.byteslice(range).to_s)}\\b" @search_direction = key == "*" ? 1 : -1 search_next(count: count) end @command.clear else move(key, count, explicit: explicit) @command.clear end rescue Error end_group @mode, @operator, @prefix = :normal, nil, nil raise ensure @status = @message || (@command_line ? "#{@command_type}#{@command_line}" : @mode.to_s.upcase) end |